@rizom/brain 0.2.0-alpha.37 → 0.2.0-alpha.38
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 +31 -30
- package/dist/site.js +5 -5
- package/dist/site.js.map +1 -1
- package/package.json +1 -1
package/dist/brain.js
CHANGED
|
@@ -508,6 +508,7 @@ For these operations, ask for confirmation before executing:
|
|
|
508
508
|
When asking for confirmation, clearly describe what will happen.
|
|
509
509
|
|
|
510
510
|
### Entity-Specific Update Rules
|
|
511
|
+
- To approve a discovered contact/agent, use \`system_update\` on \`entityType: "agent"\` with \`id\` set to the saved local agent id and \`fields.status\` set to \`"approved"\`. Do not call \`system_update\` for approval without \`fields\`.
|
|
511
512
|
- To archive or remove a contact/agent, use \`system_update\` on \`entityType: "agent"\` and set \`fields.status\` to \`"archived"\`
|
|
512
513
|
- To attach an existing image as a cover, use \`system_set-cover\` even if you are not fully sure the image exists yet \u2014 let the tool validate it
|
|
513
514
|
- When a user asks to publish a latest social post, check the queue/list state first and describe the latest draft or post clearly
|
|
@@ -525,10 +526,10 @@ Instructions:
|
|
|
525
526
|
2. Search through available entities for relevant information
|
|
526
527
|
3. Provide accurate, contextual responses based on the data
|
|
527
528
|
4. If information is missing, clearly state what additional data might be helpful
|
|
528
|
-
5. Structure your response clearly and concisely`,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,schema:nq,formatter:new YO}});var XcA;var HcA=l(()=>{GA();XcA=Z.object({answer:Z.string().describe("The answer to the user's query"),sources:Z.array(Z.object({type:Z.string().describe("Type of source (e.g., note, article)"),title:Z.string().describe("Title or identifier of the source"),relevance:Z.number().min(0).max(1).describe("Relevance score")})).optional().describe("Sources used to generate the answer"),confidence:Z.enum(["high","medium","low"]).optional().describe("Confidence level of the answer"),suggestions:Z.array(Z.string()).optional().describe("Related topics or follow-up questions")})});var KcA=l(()=>{IcA();HcA()});var UcA=l(()=>{wcA();$cA();YcA();KcA()});class YK{static instance=null;daemons=new Map;logger;static getInstance(A=T2.getInstance()){return YK.instance??=new YK(A),YK.instance}static resetInstance(){YK.instance=null}static createFresh(A){return new YK(A)}constructor(A){this.logger=A.child("DaemonRegistry")}register(A,Q,B){if(this.daemons.has(A))this.logger.warn(`Daemon already registered: ${A}, overwriting`);let w={name:A,daemon:Q,pluginId:B,status:"stopped"};this.daemons.set(A,w),this.logger.debug(`Registered daemon: ${A} from plugin: ${B}`)}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}`);if(Q.status==="running"){this.logger.warn(`Daemon already running: ${A}`);return}Q.status="starting",delete Q.error;try{await Q.daemon.start(),Q.status="running",Q.startedAt=new Date,this.logger.debug(`Daemon started successfully: ${A}`)}catch(B){throw Q.status="error",Q.error=jI(B),this.logger.warn(`Daemon ${A} failed to start: ${L0(B)}`),B}}async stop(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);if(Q.status==="stopped"){this.logger.warn(`Daemon already stopped: ${A}`);return}Q.status="stopping";try{await Q.daemon.stop(),Q.status="stopped",Q.stoppedAt=new Date,this.logger.debug(`Daemon stopped successfully: ${A}`)}catch(B){throw Q.status="error",Q.error=jI(B),this.logger.error(`Failed to stop daemon: ${A}`,B),B}}async checkHealth(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);if(!Q.daemon.healthCheck)return;try{let B=await Q.daemon.healthCheck();return Q.health=B,B}catch(B){let w={status:"error",message:L0(B),lastCheck:new Date};return Q.health=w,w}}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((Q)=>({name:Q.name,pluginId:Q.pluginId,status:Q.status,health:Q.health}))}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 B;for(let w of Q)try{await this.start(w.name)}catch($){B??=jI($)}if(B)throw B}async stopPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Stopping ${Q.length} daemons for plugin: ${A}`);for(let B of Q)try{await this.stop(B.name)}catch(w){this.logger.error(`Failed to stop daemon: ${B.name}`,w)}}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(B){this.logger.error(`Failed to stop daemon during clear: ${Q.name}`,B)}this.daemons.clear(),this.logger.debug("All daemons cleared")}}var WcA=l(()=>{GA()});class sI{static instance=null;handlers=new Map;logger;static getInstance(A){return sI.instance??=new sI(A),sI.instance}static resetInstance(){sI.instance=null}static createFresh(A){return new sI(A)}constructor(A){this.logger=A}subscribe(A,Q,B){let w=async(Y)=>{let X=await Q(Y);if("noop"in X)return{id:`resp-${Date.now()}`,requestId:Y.id,timestamp:new Date().toISOString(),success:!0,data:void 0,error:void 0};if("success"in X)return{id:`resp-${Date.now()}`,requestId:Y.id,timestamp:new Date().toISOString(),success:X.success,data:X.data,error:X.error?{message:X.error}:void 0};throw Error("Invalid message response format")},$=B?{handler:w,filter:B}:{handler:w};if(!this.handlers.has(A))this.handlers.set(A,new Set);let D=this.handlers.get(A);if(D)D.add($);return this.logger.debug(`Registered handler for message type: ${A}`,{hasFilter:!!B,filterTarget:B?.target}),()=>{let Y=this.handlers.get(A);if(Y){if(Y.delete($),Y.size===0)this.handlers.delete(A)}}}async send(A,Q,B,w,$,D){let Y={id:`msg-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,type:A,timestamp:new Date().toISOString(),source:B,target:w,metadata:$,payload:Q},I=await this.publish(Y,D);if(I?.success)return{success:!0,data:I.data};return{success:!1,error:I?.error?.message??`No handler found for message type: ${A}`}}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:B}=A,w=this.handlers.get(B)??new Set;if(this.logger.debug(`Publishing message of type: ${B}`,{source:A.source,target:A.target,hasMetadata:!!A.metadata}),w.size===0)return this.logger.debug(`No handlers found for message type: ${B}`),null;let $=Array.from(w).filter((Y)=>this.matchesFilter(A,Y.filter));if($.length===0)return this.logger.debug(`No matching handlers for message type: ${B}`,{totalHandlers:w.size,target:A.target}),null;if(Q===!0){for(let Y of $)try{await Y.handler(A)}catch(I){this.logger.error(`Error in message handler for ${B}`,I)}return null}else{for(let Y of $)try{let I=await Y.handler(A);if(I)return I}catch(I){this.logger.error(`Error in message handler for ${B}`,I)}return null}}matchesFilter(A,Q){if(!Q)return!0;if(Q.source){if(!this.matchesPattern(A.source,Q.source))return!1}if(Q.target){if(!A.target||!this.matchesPattern(A.target,Q.target))return!1}if(Q.metadata){if(!A.metadata)return!1;for(let[B,w]of Object.entries(Q.metadata))if(A.metadata[B]!==w)return!1}if(Q.predicate)return Q.predicate(A);return!0}matchesPattern(A,Q){if(!A)return!1;if(Q instanceof RegExp)return Q.test(A);if(Q.includes("*")){let B=Q.split("*").map((w)=>w.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${B}$`).test(A)}return A===Q}validateMessage(A,Q){try{return{valid:!0,data:Q.parse(A)}}catch(B){if(B instanceof Z.ZodError)return{valid:!1,error:B.issues[0]?.message??"Validation failed"};return{valid:!1,error:"Unknown validation error"}}}hasHandlers(A){let Q=this.handlers.get(A);return Q!==void 0&&Q.size>0}unsubscribe(A,Q){this.clearHandlers(A)}clearHandlers(A){if(this.handlers.has(A))this.handlers.delete(A),this.logger.info(`Cleared all handlers for message type: ${A}`)}clearAllHandlers(){this.handlers.clear(),this.logger.info("Cleared all message handlers")}getHandlerCount(A){return this.handlers.get(A)?.size??0}getTargetedHandlerCount(A,Q){let B=this.handlers.get(A);if(!B)return 0;return Array.from(B).filter((w)=>w.filter?.target===Q).length}}var GcA=l(()=>{GA()});var JcA,FcA;var ZcA=l(()=>{GA();JcA=Z.object({success:Z.boolean(),data:Z.unknown().optional(),error:Z.string().optional()}),FcA=Z.object({id:Z.string().min(1),timestamp:Z.string(),type:Z.string().min(1),source:Z.string().min(1),target:Z.string().optional(),metadata:Z.record(Z.string(),Z.unknown()).optional()})});var vK1;var zcA=l(()=>{GA();ZcA();vK1=Z.object({id:Z.string().min(1),requestId:Z.string().min(1),success:Z.boolean(),data:Z.unknown().optional(),error:Z.object({message:Z.string(),code:Z.string().optional()}).optional(),timestamp:Z.string().datetime()})});var qcA=l(()=>{GcA();zcA()});function Y6A(A,Q,B,w,$){return["entity:created","entity:updated","entity:deleted"].map((Y)=>A.subscribe(Y,async(I)=>{if(I.payload.entityType===Q&&I.payload.entityId===B){await w();let X=Y.replace("entity:","");$.debug(`${Q} entity ${X}, cache refreshed`)}return{success:!0}}))}class aI{static instance=null;logger;config;static getInstance(A,Q){return aI.instance??=new aI(A,Q),aI.instance}static resetInstance(){aI.instance=null}static createFresh(A,Q){return new aI(A,Q)}constructor(A,Q){this.logger=A.child("ShellInitializer"),this.config=Q}registerShellTemplates(A){A.register(JR.name,JR),this.logger.debug("Shell system templates registered")}registerBaseEntityDisplayTemplate(A){A.register(LN.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:U2,formatter:new ov,requiredPermission:"public"}),this.logger.debug("Base entity display template registered")}registerFallbackBaseEntity(A){A.registerEntityType(k$.BASE,U2,new cO),this.logger.debug("Fallback base entity adapter registered")}registerBrainCharacterSupport(A){let Q=new zN;A.registerEntityType(k$.BRAIN_CHARACTER,Q.schema,Q),this.logger.debug("Brain character entity support registered")}registerAnchorProfileSupport(A){let Q=new cI;A.registerEntityType(k$.ANCHOR_PROFILE,Q.schema,Q),this.logger.debug("Anchor profile entity support registered")}async initializePlugins(A,Q){this.logger.debug(`Found ${this.config.plugins.length} plugins to register`);for(let B of this.config.plugins)this.logger.debug(`Registering plugin: ${B.id}`),A.registerPlugin(B);if(await A.initializePlugins(Q),!Q?.registerOnly){for(let{id:B,error:w}of A.getFailedPlugins())if(A.getPlugin(B)?.requiresDaemonStartup?.())throw w}this.logger.debug("Plugin initialization complete")}initializeServices(A){this.logger.debug("Initializing Shell services");let Q={debug:2,info:3,warn:4,error:5}[this.config.logging.level],B=A?.logger??T2.createFresh({level:Q,context:this.config.logging.context,format:this.config.logging.format==="json"?"json":"text",...this.config.logging.file?{logFile:this.config.logging.file}:{}}),w=A?.embeddingService??nI.getInstance({apiKey:this.config.ai.apiKey,logger:B}),$={apiKey:this.config.ai.apiKey,model:this.config.ai.model,temperature:this.config.ai.temperature,maxTokens:this.config.ai.maxTokens,webSearch:this.config.ai.webSearch,...this.config.ai.imageApiKey?{imageApiKey:this.config.ai.imageApiKey}:{}},D=A?.aiService??rI.getInstance($,B),Y=_4.getInstance(B),I=A?.messageBus??sI.getInstance(B),X=pD.getInstance(B),H=gI.getInstance(B),W=A?.renderService??PI.getInstance(X),J=A?.daemonRegistry??YK.getInstance(B),F=A?.pluginManager??QY.getInstance(B,J),z=new lD(this.config.permissions),V=A?.mcpService??dD.getInstance(I,B),E={url:this.config.jobQueueDatabase.url,...this.config.jobQueueDatabase.authToken&&{authToken:this.config.jobQueueDatabase.authToken}},L=k4.getInstance(E,B),k=b4.getInstance({embeddingService:w,entityRegistry:Y,logger:B,jobQueueService:L,messageBus:I,dbConfig:{url:this.config.database.url,...this.config.database.authToken&&{authToken:this.config.database.authToken}},embeddingDbConfig:{url:this.config.embeddingDatabase.url,...this.config.embeddingDatabase.authToken&&{authToken:this.config.embeddingDatabase.authToken}}}),_=A?.conversationService??j$.getInstance(B,I,{url:this.config.conversationDatabase.url,...this.config.conversationDatabase.authToken&&{authToken:this.config.conversationDatabase.authToken}}),j=A?.contentService??new Xg({logger:B,entityService:k,aiService:D,templateRegistry:X,dataSourceRegistry:H}),r=eD.getInstance(k,B,this.config.identity);Y6A(I,k$.BRAIN_CHARACTER,k$.BRAIN_CHARACTER,()=>r.refreshCache(),B);let n=b7.getInstance(k,B,this.config.profile),g=D6A({model:D.getModel(),modelId:D.getConfig().model,webSearch:D.getConfig().webSearch,temperature:D.getConfig().temperature,maxTokens:D.getConfig().maxTokens,messageBus:I}),T=S$.getInstance(V,_,r,n,B,{agentFactory:g});Y6A(I,k$.ANCHOR_PROFILE,k$.ANCHOR_PROFILE,()=>n.refreshCache(),B);for(let c of[k$.BRAIN_CHARACTER,k$.ANCHOR_PROFILE])Y6A(I,c,c,async()=>T.invalidateAgent(),B);I.subscribe("system:plugins:ready",async()=>{return B.debug("system:plugins:ready received, loading identity and profile caches"),await Promise.all([r.refreshCache(),n.refreshCache()]),{success:!0}}),I.subscribe("sync:initial:completed",async()=>{B.debug("sync:initial:completed received, initializing identity and profile services"),await r.initialize(),await n.initialize(),B.debug("Identity and profile services initialized");let c=X.list().filter((UA)=>!!UA.basePrompt);if(c.length>0)await Promise.all(c.map((UA)=>dH(k,UA.name,UA.basePrompt))),B.debug(`Materialized ${c.length} prompt entities`);return{success:!0}});let S=SI.getInstance(L,B),h=hI.getInstance(L,I,S,B),t=vI.getInstance(L,h,B,{pollInterval:100,concurrency:1,autoStart:!1});return{logger:B,entityRegistry:Y,messageBus:I,renderService:W,daemonRegistry:J,pluginManager:F,templateRegistry:X,dataSourceRegistry:H,mcpService:V,embeddingService:w,entityService:k,aiService:D,conversationService:_,contentService:j,jobQueueService:L,jobQueueWorker:t,batchJobManager:S,jobProgressMonitor:h,permissionService:z,identityService:r,profileService:n,agentService:T}}registerJobHandlers(A,Q,B){let w=DK.createFresh(Q,B);A.registerHandler("shell:content-generation",w,"shell")}wireShell(A,Q){A.pluginManager.setShell(Q)}async initializeAll(A,Q,B,w){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(A),this.registerBaseEntityDisplayTemplate(A),this.registerBrainCharacterSupport(Q),this.registerAnchorProfileSupport(Q),await this.initializePlugins(B,w),!Q.hasEntityType(k$.BASE))this.registerFallbackBaseEntity(Q);this.logger.debug("Shell ready")}catch($){throw this.logger.error("Shell initialization failed",$),$}}}function FR(){aI.resetInstance(),b4.resetInstance(),_4.resetInstance(),gI.resetInstance(),nI.resetInstance(),j$.resetInstance(),QY.resetInstance(),dD.resetInstance(),sI.resetInstance(),pD.resetInstance(),PI.resetInstance(),YK.resetInstance(),rI.resetInstance(),S$.resetInstance(),eD.resetInstance(),b7.resetInstance(),k4.resetInstance(),SI.resetInstance(),vI.resetInstance(),hI.resetInstance()}async function NcA(){let{Shell:A}=await Promise.resolve().then(() => (X6A(),VcA));await A.resetInstance(),FR()}var I6A=l(()=>{Ig();Ig();UcA();ke();WcA();P6();Ig();P6();EW();EW();S3();zW();qcA();B0();s8();GA();nO()});var LcA,McA,EcA,CcA,OcA,fcA,RcA,jcA,kcA,PcA,_cA,bcA,xcA,z5Q,q5Q,N5Q;var TcA=l(()=>{GA();LcA=Z.object({query:Z.string().describe("Search term"),entityType:Z.string().optional().describe("Entity type to filter by"),limit:Z.number().optional().describe("Maximum number of results")}),McA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID, slug, or title")}),EcA=Z.object({entityType:Z.string().describe("Entity type to list"),status:Z.string().optional().describe("Filter by status"),limit:Z.number().optional().describe("Maximum number of results (default: 20)")}),CcA=Z.object({entityType:Z.string().describe("Entity type to create"),title:Z.string().optional().describe("Title for the entity"),prompt:Z.string().optional().describe("Prompt for AI generation"),content:Z.string().optional().describe("Direct content to store"),url:Z.string().optional().describe("URL or domain for URL-first create flows such as saving a link or remote agent"),targetEntityType:Z.string().optional().describe("Attach to this entity type after creation (e.g. set as cover image)"),targetEntityId:Z.string().optional().describe("Attach to this entity ID after creation")}),OcA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID"),fields:Z.record(Z.unknown()).optional().describe("Partial frontmatter fields to update"),content:Z.string().optional().describe("Full markdown content replacement"),confirmed:Z.literal(!0).optional().describe("Confirm the update"),contentHash:Z.string().optional().describe("Content hash for optimistic concurrency")}),fcA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID"),confirmed:Z.literal(!0).optional().describe("Confirm the deletion")}),RcA=Z.object({entityType:Z.string().describe("Entity type to extract"),source:Z.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:Z.enum(["derive","rebuild"]).optional().describe("Batch mode: derive incrementally or rebuild from scratch"),confirmed:Z.literal(!0).optional().describe("Confirm destructive rebuild")}),jcA=Z.object({entityType:Z.string().describe("Entity type"),entityId:Z.string().describe("Entity ID or slug"),imageId:Z.string().nullable().describe("Image ID to set, or null to remove")}),kcA=Z.object({batchId:Z.string().optional().describe("Specific batch ID to check"),jobTypes:Z.array(Z.string()).optional().describe("Filter by job types")}),PcA=Z.object({conversationId:Z.string().describe("Conversation ID")}),_cA=Z.object({searchQuery:Z.string().optional().describe("Optional search query"),limit:Z.number().optional().describe("Maximum results (default: 20)")}),bcA=Z.object({conversationId:Z.string().describe("Conversation ID"),limit:Z.number().optional().describe("Maximum messages (default: 20)")}),xcA=Z.object({type:Z.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),z5Q=Z.object({entityId:Z.string().optional(),status:Z.enum(["created","generating"]),jobId:Z.string().optional()}),q5Q=Z.object({status:Z.literal("extracting"),jobId:Z.string(),entityType:Z.string(),source:Z.string().optional(),mode:Z.enum(["derive","rebuild"]).optional()}),N5Q=Z.object({entityType:Z.string(),entityId:Z.string(),imageId:Z.string().nullable()})});function ZR(A,Q,B,w,$={}){let{visibility:D="anchor"}=$;return{name:`${SK1}_${A}`,description:Q,inputSchema:B.shape,handler:async(Y,I)=>{let X=B.safeParse(Y);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.errors.map((H)=>`${H.path.join(".")}: ${H.message}`).join(", ")}`};try{return await w(X.data,I)}catch(H){return{success:!1,error:L0(H)}}},visibility:D}}function vcA(A){if(A.entityType==="image"&&A.content.startsWith("data:"))return{...A,content:"[binary image data \u2014 use metadata for image info]"};return A}function XV(A){if(A===void 0)return;let Q=A.trim();return Q.length>0?Q:void 0}function hK1(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 ScA(A){let{entityService:Q,conversationService:B,logger:w,jobs:$,entityRegistry:D}=A;return[yQ("system","search","Search entities using semantic search. Optionally filter by entity type.",LcA,async(Y)=>({success:!0,data:{results:(await Q.search(Y.query,{limit:Y.limit??A.searchLimit,...Y.entityType&&{types:[Y.entityType]}})).map((I)=>({...I,entity:vcA(I.entity)}))}}),{visibility:"public",cli:{name:"search"}}),yQ("system","get","Retrieve a specific entity by type and identifier (ID, slug, or title).",McA,async(Y)=>{if(!Q.getEntityTypes().includes(Y.entityType))return{success:!1,error:`Unknown entity type: ${Y.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let I=await pH(Q,Y.entityType,Y.id,w);return I.ok?{success:!0,data:{entity:vcA(I.entity)}}:{success:!1,error:I.error}},{visibility:"public",cli:{name:"get"}}),yQ("system","list","List entities by type. Returns metadata only \u2014 use system_get for full content.",EcA,async(Y)=>{if(!Q.getEntityTypes().includes(Y.entityType))return{success:!1,error:`Unknown entity type: ${Y.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let I={limit:Y.limit??20};if(Y.status)I.filter={metadata:{status:Y.status}};let H=(await Q.listEntities(Y.entityType,I)).map(({content:W,contentHash:J,...F})=>F);return{success:!0,data:{entities:H,count:H.length}}},{visibility:"public",cli:{name:"list"}}),ZR("check-job-status","Check the status of background operations",kcA,async(Y)=>{if(Y.batchId){let H=await $.getBatchStatus(Y.batchId);if(!H)return{success:!1,error:`No batch found with ID: ${Y.batchId}`};let W=H.totalOperations>0?Math.round(H.completedOperations/H.totalOperations*100):0;return{success:!0,data:{batchId:Y.batchId,status:H.status,progress:{total:H.totalOperations,completed:H.completedOperations,failed:H.failedOperations,percentComplete:W},currentOperation:H.currentOperation,errors:H.errors}}}let I=await $.getActiveJobs(Y.jobTypes),X=await $.getActiveBatches();return{success:!0,data:{summary:{activeJobs:I.length,activeBatches:X.length},jobs:I.map((H)=>({id:H.id,type:H.type,status:H.status,priority:H.priority,retryCount:H.retryCount,createdAt:new Date(H.createdAt).toISOString(),startedAt:H.startedAt?new Date(H.startedAt).toISOString():null})),batches:X.map((H)=>({batchId:H.batchId,status:H.status.status,totalOperations:H.status.totalOperations,completedOperations:H.status.completedOperations,failedOperations:H.status.failedOperations,currentOperation:H.status.currentOperation,pluginId:H.metadata.metadata.pluginId,errors:H.status.errors}))}}},{visibility:"public"}),yQ("system","get-conversation","Get conversation details",PcA,async(Y)=>{let I=await B.getConversation(Y.conversationId);if(!I)return{success:!1,error:`Conversation not found: ${Y.conversationId}`};return{success:!0,data:{id:I.id,interfaceType:I.interfaceType,channelId:I.channelId,created:I.created,lastActive:I.lastActive}}},{visibility:"public"}),yQ("system","list-conversations","List conversations, optionally filtered by search query",_cA,async(Y)=>{let I=await B.searchConversations(Y.searchQuery??""),X=I.slice(0,Y.limit??20);return{success:!0,data:{conversations:X.map((H)=>({id:H.id,interfaceType:H.interfaceType,channelId:H.channelId,created:H.created,lastActive:H.lastActive})),totalFound:I.length,returned:X.length,searchQuery:Y.searchQuery}}},{visibility:"public"}),yQ("system","get-messages","Get messages from a specific conversation",bcA,async(Y)=>{let I=await B.getMessages(Y.conversationId,{limit:Y.limit??20});return{success:!0,data:{conversationId:Y.conversationId,messages:I.map((X)=>({id:X.id,role:X.role,content:X.content,timestamp:X.timestamp})),messageCount:I.length,requestedLimit:Y.limit??20}}},{visibility:"public"}),yQ("system","status","Get system status including model, version, interfaces, and tools",Z.object({}),async()=>({success:!0,data:await A.getAppInfo()}),{visibility:"public",cli:{name:"status"}}),ZR("create","Create a new entity. Provide content for direct creation, a prompt for AI generation, or a url for URL-first flows.",CcA,async(Y,I)=>{let X=XV(Y.prompt),H=XV(Y.content),W=XV(Y.title),J=XV(Y.url),F=XV(Y.targetEntityType),z=XV(Y.targetEntityId);if(!!F!==!!z)return{success:!1,error:"Provide both 'targetEntityType' and 'targetEntityId' together, or omit both."};if(!H&&!X&&!J)return{success:!1,error:"Provide 'content' (direct create), 'prompt' (AI generation), or 'url' (URL-first create), or a supported combination."};let V={entityType:Y.entityType,...X&&{prompt:X},...W&&{title:W},...H&&{content:H},...J&&{url:J},...F&&{targetEntityType:F},...z&&{targetEntityId:z}},E=A.entityRegistry.getCreateInterceptor(V.entityType);if(E){let _={interfaceType:I.interfaceType,userId:I.userId,...I.channelId&&{channelId:I.channelId},...I.channelName&&{channelName:I.channelName}},j=await E(V,_);if(j.kind==="handled")return j.result;V=j.input}if(!V.content&&!V.prompt)return{success:!1,error:"URL-only creation is supported only for entity types that explicitly handle it. Provide 'content' or 'prompt' for this entity type."};if(V.prompt)try{return{success:!0,data:{status:"generating",jobId:await $.enqueue(`${V.entityType}:generation`,{prompt:V.prompt,...V.title&&{title:V.title},...V.content&&{content:V.content},...V.targetEntityType&&{targetEntityType:V.targetEntityType},...V.targetEntityId&&{targetEntityId:V.targetEntityId}},I)}}}catch(_){return{success:!1,error:_ instanceof Error?_.message:"Failed to queue generation job"}}let L=e1(V.title??`${V.entityType}-${Date.now()}`),k=new Date().toISOString();try{return{success:!0,data:{entityId:(await Q.createEntity({id:L,entityType:V.entityType,content:V.content??"",metadata:{title:V.title??L},created:k,updated:k})).entityId,status:"created"}}}catch(_){return{success:!1,error:_ instanceof Error?_.message:"Failed to create entity"}}},{visibility:"trusted"}),ZR("delete","Delete an entity. Requires confirmation.",fcA,async(Y)=>{let I=await pH(Q,Y.entityType,Y.id,w);if(!I.ok)return{success:!1,error:I.error};let{entity:X}=I;if(Y.confirmed){try{await Q.deleteEntity(Y.entityType,X.id)}catch(W){return{success:!1,error:W instanceof Error?W.message:"Failed to delete entity"}}return{success:!0,data:{deleted:X.id}}}return{needsConfirmation:!0,toolName:"system_delete",description:`Delete "${typeof X.metadata.title==="string"?X.metadata.title:X.id}"?
|
|
529
|
+
5. Structure your response clearly and concisely`,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,schema:nq,formatter:new YO}});var XcA;var HcA=l(()=>{GA();XcA=Z.object({answer:Z.string().describe("The answer to the user's query"),sources:Z.array(Z.object({type:Z.string().describe("Type of source (e.g., note, article)"),title:Z.string().describe("Title or identifier of the source"),relevance:Z.number().min(0).max(1).describe("Relevance score")})).optional().describe("Sources used to generate the answer"),confidence:Z.enum(["high","medium","low"]).optional().describe("Confidence level of the answer"),suggestions:Z.array(Z.string()).optional().describe("Related topics or follow-up questions")})});var KcA=l(()=>{IcA();HcA()});var UcA=l(()=>{wcA();$cA();YcA();KcA()});class YK{static instance=null;daemons=new Map;logger;static getInstance(A=T2.getInstance()){return YK.instance??=new YK(A),YK.instance}static resetInstance(){YK.instance=null}static createFresh(A){return new YK(A)}constructor(A){this.logger=A.child("DaemonRegistry")}register(A,Q,B){if(this.daemons.has(A))this.logger.warn(`Daemon already registered: ${A}, overwriting`);let w={name:A,daemon:Q,pluginId:B,status:"stopped"};this.daemons.set(A,w),this.logger.debug(`Registered daemon: ${A} from plugin: ${B}`)}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}`);if(Q.status==="running"){this.logger.warn(`Daemon already running: ${A}`);return}Q.status="starting",delete Q.error;try{await Q.daemon.start(),Q.status="running",Q.startedAt=new Date,this.logger.debug(`Daemon started successfully: ${A}`)}catch(B){throw Q.status="error",Q.error=jI(B),this.logger.warn(`Daemon ${A} failed to start: ${L0(B)}`),B}}async stop(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);if(Q.status==="stopped"){this.logger.warn(`Daemon already stopped: ${A}`);return}Q.status="stopping";try{await Q.daemon.stop(),Q.status="stopped",Q.stoppedAt=new Date,this.logger.debug(`Daemon stopped successfully: ${A}`)}catch(B){throw Q.status="error",Q.error=jI(B),this.logger.error(`Failed to stop daemon: ${A}`,B),B}}async checkHealth(A){let Q=this.daemons.get(A);if(!Q)throw Error(`Daemon not registered: ${A}`);if(!Q.daemon.healthCheck)return;try{let B=await Q.daemon.healthCheck();return Q.health=B,B}catch(B){let w={status:"error",message:L0(B),lastCheck:new Date};return Q.health=w,w}}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((Q)=>({name:Q.name,pluginId:Q.pluginId,status:Q.status,health:Q.health}))}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 B;for(let w of Q)try{await this.start(w.name)}catch($){B??=jI($)}if(B)throw B}async stopPlugin(A){let Q=this.getByPlugin(A);this.logger.debug(`Stopping ${Q.length} daemons for plugin: ${A}`);for(let B of Q)try{await this.stop(B.name)}catch(w){this.logger.error(`Failed to stop daemon: ${B.name}`,w)}}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(B){this.logger.error(`Failed to stop daemon during clear: ${Q.name}`,B)}this.daemons.clear(),this.logger.debug("All daemons cleared")}}var WcA=l(()=>{GA()});class sI{static instance=null;handlers=new Map;logger;static getInstance(A){return sI.instance??=new sI(A),sI.instance}static resetInstance(){sI.instance=null}static createFresh(A){return new sI(A)}constructor(A){this.logger=A}subscribe(A,Q,B){let w=async(Y)=>{let X=await Q(Y);if("noop"in X)return{id:`resp-${Date.now()}`,requestId:Y.id,timestamp:new Date().toISOString(),success:!0,data:void 0,error:void 0};if("success"in X)return{id:`resp-${Date.now()}`,requestId:Y.id,timestamp:new Date().toISOString(),success:X.success,data:X.data,error:X.error?{message:X.error}:void 0};throw Error("Invalid message response format")},$=B?{handler:w,filter:B}:{handler:w};if(!this.handlers.has(A))this.handlers.set(A,new Set);let D=this.handlers.get(A);if(D)D.add($);return this.logger.debug(`Registered handler for message type: ${A}`,{hasFilter:!!B,filterTarget:B?.target}),()=>{let Y=this.handlers.get(A);if(Y){if(Y.delete($),Y.size===0)this.handlers.delete(A)}}}async send(A,Q,B,w,$,D){let Y={id:`msg-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,type:A,timestamp:new Date().toISOString(),source:B,target:w,metadata:$,payload:Q},I=await this.publish(Y,D);if(I?.success)return{success:!0,data:I.data};return{success:!1,error:I?.error?.message??`No handler found for message type: ${A}`}}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:B}=A,w=this.handlers.get(B)??new Set;if(this.logger.debug(`Publishing message of type: ${B}`,{source:A.source,target:A.target,hasMetadata:!!A.metadata}),w.size===0)return this.logger.debug(`No handlers found for message type: ${B}`),null;let $=Array.from(w).filter((Y)=>this.matchesFilter(A,Y.filter));if($.length===0)return this.logger.debug(`No matching handlers for message type: ${B}`,{totalHandlers:w.size,target:A.target}),null;if(Q===!0){for(let Y of $)try{await Y.handler(A)}catch(I){this.logger.error(`Error in message handler for ${B}`,I)}return null}else{for(let Y of $)try{let I=await Y.handler(A);if(I)return I}catch(I){this.logger.error(`Error in message handler for ${B}`,I)}return null}}matchesFilter(A,Q){if(!Q)return!0;if(Q.source){if(!this.matchesPattern(A.source,Q.source))return!1}if(Q.target){if(!A.target||!this.matchesPattern(A.target,Q.target))return!1}if(Q.metadata){if(!A.metadata)return!1;for(let[B,w]of Object.entries(Q.metadata))if(A.metadata[B]!==w)return!1}if(Q.predicate)return Q.predicate(A);return!0}matchesPattern(A,Q){if(!A)return!1;if(Q instanceof RegExp)return Q.test(A);if(Q.includes("*")){let B=Q.split("*").map((w)=>w.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${B}$`).test(A)}return A===Q}validateMessage(A,Q){try{return{valid:!0,data:Q.parse(A)}}catch(B){if(B instanceof Z.ZodError)return{valid:!1,error:B.issues[0]?.message??"Validation failed"};return{valid:!1,error:"Unknown validation error"}}}hasHandlers(A){let Q=this.handlers.get(A);return Q!==void 0&&Q.size>0}unsubscribe(A,Q){this.clearHandlers(A)}clearHandlers(A){if(this.handlers.has(A))this.handlers.delete(A),this.logger.info(`Cleared all handlers for message type: ${A}`)}clearAllHandlers(){this.handlers.clear(),this.logger.info("Cleared all message handlers")}getHandlerCount(A){return this.handlers.get(A)?.size??0}getTargetedHandlerCount(A,Q){let B=this.handlers.get(A);if(!B)return 0;return Array.from(B).filter((w)=>w.filter?.target===Q).length}}var GcA=l(()=>{GA()});var JcA,FcA;var ZcA=l(()=>{GA();JcA=Z.object({success:Z.boolean(),data:Z.unknown().optional(),error:Z.string().optional()}),FcA=Z.object({id:Z.string().min(1),timestamp:Z.string(),type:Z.string().min(1),source:Z.string().min(1),target:Z.string().optional(),metadata:Z.record(Z.string(),Z.unknown()).optional()})});var vK1;var zcA=l(()=>{GA();ZcA();vK1=Z.object({id:Z.string().min(1),requestId:Z.string().min(1),success:Z.boolean(),data:Z.unknown().optional(),error:Z.object({message:Z.string(),code:Z.string().optional()}).optional(),timestamp:Z.string().datetime()})});var qcA=l(()=>{GcA();zcA()});function Y6A(A,Q,B,w,$){return["entity:created","entity:updated","entity:deleted"].map((Y)=>A.subscribe(Y,async(I)=>{if(I.payload.entityType===Q&&I.payload.entityId===B){await w();let X=Y.replace("entity:","");$.debug(`${Q} entity ${X}, cache refreshed`)}return{success:!0}}))}class aI{static instance=null;logger;config;static getInstance(A,Q){return aI.instance??=new aI(A,Q),aI.instance}static resetInstance(){aI.instance=null}static createFresh(A,Q){return new aI(A,Q)}constructor(A,Q){this.logger=A.child("ShellInitializer"),this.config=Q}registerShellTemplates(A){A.register(JR.name,JR),this.logger.debug("Shell system templates registered")}registerBaseEntityDisplayTemplate(A){A.register(LN.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:U2,formatter:new ov,requiredPermission:"public"}),this.logger.debug("Base entity display template registered")}registerFallbackBaseEntity(A){A.registerEntityType(k$.BASE,U2,new cO),this.logger.debug("Fallback base entity adapter registered")}registerBrainCharacterSupport(A){let Q=new zN;A.registerEntityType(k$.BRAIN_CHARACTER,Q.schema,Q),this.logger.debug("Brain character entity support registered")}registerAnchorProfileSupport(A){let Q=new cI;A.registerEntityType(k$.ANCHOR_PROFILE,Q.schema,Q),this.logger.debug("Anchor profile entity support registered")}async initializePlugins(A,Q){this.logger.debug(`Found ${this.config.plugins.length} plugins to register`);for(let B of this.config.plugins)this.logger.debug(`Registering plugin: ${B.id}`),A.registerPlugin(B);if(await A.initializePlugins(Q),!Q?.registerOnly){for(let{id:B,error:w}of A.getFailedPlugins())if(A.getPlugin(B)?.requiresDaemonStartup?.())throw w}this.logger.debug("Plugin initialization complete")}initializeServices(A){this.logger.debug("Initializing Shell services");let Q={debug:2,info:3,warn:4,error:5}[this.config.logging.level],B=A?.logger??T2.createFresh({level:Q,context:this.config.logging.context,format:this.config.logging.format==="json"?"json":"text",...this.config.logging.file?{logFile:this.config.logging.file}:{}}),w=A?.embeddingService??nI.getInstance({apiKey:this.config.ai.apiKey,logger:B}),$={apiKey:this.config.ai.apiKey,model:this.config.ai.model,temperature:this.config.ai.temperature,maxTokens:this.config.ai.maxTokens,webSearch:this.config.ai.webSearch,...this.config.ai.imageApiKey?{imageApiKey:this.config.ai.imageApiKey}:{}},D=A?.aiService??rI.getInstance($,B),Y=_4.getInstance(B),I=A?.messageBus??sI.getInstance(B),X=pD.getInstance(B),H=gI.getInstance(B),W=A?.renderService??PI.getInstance(X),J=A?.daemonRegistry??YK.getInstance(B),F=A?.pluginManager??QY.getInstance(B,J),z=new lD(this.config.permissions),V=A?.mcpService??dD.getInstance(I,B),E={url:this.config.jobQueueDatabase.url,...this.config.jobQueueDatabase.authToken&&{authToken:this.config.jobQueueDatabase.authToken}},L=k4.getInstance(E,B),k=b4.getInstance({embeddingService:w,entityRegistry:Y,logger:B,jobQueueService:L,messageBus:I,dbConfig:{url:this.config.database.url,...this.config.database.authToken&&{authToken:this.config.database.authToken}},embeddingDbConfig:{url:this.config.embeddingDatabase.url,...this.config.embeddingDatabase.authToken&&{authToken:this.config.embeddingDatabase.authToken}}}),_=A?.conversationService??j$.getInstance(B,I,{url:this.config.conversationDatabase.url,...this.config.conversationDatabase.authToken&&{authToken:this.config.conversationDatabase.authToken}}),j=A?.contentService??new Xg({logger:B,entityService:k,aiService:D,templateRegistry:X,dataSourceRegistry:H}),r=eD.getInstance(k,B,this.config.identity);Y6A(I,k$.BRAIN_CHARACTER,k$.BRAIN_CHARACTER,()=>r.refreshCache(),B);let n=b7.getInstance(k,B,this.config.profile),g=D6A({model:D.getModel(),modelId:D.getConfig().model,webSearch:D.getConfig().webSearch,temperature:D.getConfig().temperature,maxTokens:D.getConfig().maxTokens,messageBus:I}),T=S$.getInstance(V,_,r,n,B,{agentFactory:g});Y6A(I,k$.ANCHOR_PROFILE,k$.ANCHOR_PROFILE,()=>n.refreshCache(),B);for(let c of[k$.BRAIN_CHARACTER,k$.ANCHOR_PROFILE])Y6A(I,c,c,async()=>T.invalidateAgent(),B);I.subscribe("system:plugins:ready",async()=>{return B.debug("system:plugins:ready received, loading identity and profile caches"),await Promise.all([r.refreshCache(),n.refreshCache()]),{success:!0}}),I.subscribe("sync:initial:completed",async()=>{B.debug("sync:initial:completed received, initializing identity and profile services"),await r.initialize(),await n.initialize(),B.debug("Identity and profile services initialized");let c=X.list().filter((UA)=>!!UA.basePrompt);if(c.length>0)await Promise.all(c.map((UA)=>dH(k,UA.name,UA.basePrompt))),B.debug(`Materialized ${c.length} prompt entities`);return{success:!0}});let S=SI.getInstance(L,B),h=hI.getInstance(L,I,S,B),t=vI.getInstance(L,h,B,{pollInterval:100,concurrency:1,autoStart:!1});return{logger:B,entityRegistry:Y,messageBus:I,renderService:W,daemonRegistry:J,pluginManager:F,templateRegistry:X,dataSourceRegistry:H,mcpService:V,embeddingService:w,entityService:k,aiService:D,conversationService:_,contentService:j,jobQueueService:L,jobQueueWorker:t,batchJobManager:S,jobProgressMonitor:h,permissionService:z,identityService:r,profileService:n,agentService:T}}registerJobHandlers(A,Q,B){let w=DK.createFresh(Q,B);A.registerHandler("shell:content-generation",w,"shell")}wireShell(A,Q){A.pluginManager.setShell(Q)}async initializeAll(A,Q,B,w){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(A),this.registerBaseEntityDisplayTemplate(A),this.registerBrainCharacterSupport(Q),this.registerAnchorProfileSupport(Q),await this.initializePlugins(B,w),!Q.hasEntityType(k$.BASE))this.registerFallbackBaseEntity(Q);this.logger.debug("Shell ready")}catch($){throw this.logger.error("Shell initialization failed",$),$}}}function FR(){aI.resetInstance(),b4.resetInstance(),_4.resetInstance(),gI.resetInstance(),nI.resetInstance(),j$.resetInstance(),QY.resetInstance(),dD.resetInstance(),sI.resetInstance(),pD.resetInstance(),PI.resetInstance(),YK.resetInstance(),rI.resetInstance(),S$.resetInstance(),eD.resetInstance(),b7.resetInstance(),k4.resetInstance(),SI.resetInstance(),vI.resetInstance(),hI.resetInstance()}async function NcA(){let{Shell:A}=await Promise.resolve().then(() => (X6A(),VcA));await A.resetInstance(),FR()}var I6A=l(()=>{Ig();Ig();UcA();ke();WcA();P6();Ig();P6();EW();EW();S3();zW();qcA();B0();s8();GA();nO()});var LcA,McA,EcA,CcA,OcA,fcA,RcA,jcA,kcA,PcA,_cA,bcA,xcA,z5Q,q5Q,N5Q;var TcA=l(()=>{GA();LcA=Z.object({query:Z.string().describe("Search term"),entityType:Z.string().optional().describe("Entity type to filter by"),limit:Z.number().optional().describe("Maximum number of results")}),McA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID, slug, or title")}),EcA=Z.object({entityType:Z.string().describe("Entity type to list"),status:Z.string().optional().describe("Filter by status"),limit:Z.number().optional().describe("Maximum number of results (default: 20)")}),CcA=Z.object({entityType:Z.string().describe("Entity type to create"),title:Z.string().optional().describe("Title for the entity"),prompt:Z.string().optional().describe("Prompt for AI generation"),content:Z.string().optional().describe("Direct content to store"),url:Z.string().optional().describe("URL or domain for URL-first create flows such as saving a link or remote agent"),targetEntityType:Z.string().optional().describe("Attach to this entity type after creation (e.g. set as cover image)"),targetEntityId:Z.string().optional().describe("Attach to this entity ID after creation")}),OcA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID"),fields:Z.record(Z.unknown()).optional().describe("Partial frontmatter fields to update. Use this for status, title, and metadata changes such as approving an agent."),content:Z.string().optional().describe("Full markdown content replacement only. Do not use this for status/title/frontmatter updates; use fields instead."),confirmed:Z.literal(!0).optional().describe("Confirm the update"),contentHash:Z.string().optional().describe("Content hash for optimistic concurrency")}),fcA=Z.object({entityType:Z.string().describe("Entity type"),id:Z.string().describe("Entity ID"),confirmed:Z.literal(!0).optional().describe("Confirm the deletion")}),RcA=Z.object({entityType:Z.string().describe("Entity type to extract"),source:Z.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:Z.enum(["derive","rebuild"]).optional().describe("Batch mode: derive incrementally or rebuild from scratch"),confirmed:Z.literal(!0).optional().describe("Confirm destructive rebuild")}),jcA=Z.object({entityType:Z.string().describe("Entity type"),entityId:Z.string().describe("Entity ID or slug"),imageId:Z.string().nullable().describe("Image ID to set, or null to remove")}),kcA=Z.object({batchId:Z.string().optional().describe("Specific batch ID to check"),jobTypes:Z.array(Z.string()).optional().describe("Filter by job types")}),PcA=Z.object({conversationId:Z.string().describe("Conversation ID")}),_cA=Z.object({searchQuery:Z.string().optional().describe("Optional search query"),limit:Z.number().optional().describe("Maximum results (default: 20)")}),bcA=Z.object({conversationId:Z.string().describe("Conversation ID"),limit:Z.number().optional().describe("Maximum messages (default: 20)")}),xcA=Z.object({type:Z.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),z5Q=Z.object({entityId:Z.string().optional(),status:Z.enum(["created","generating"]),jobId:Z.string().optional()}),q5Q=Z.object({status:Z.literal("extracting"),jobId:Z.string(),entityType:Z.string(),source:Z.string().optional(),mode:Z.enum(["derive","rebuild"]).optional()}),N5Q=Z.object({entityType:Z.string(),entityId:Z.string(),imageId:Z.string().nullable()})});function ZR(A,Q,B,w,$={}){let{visibility:D="anchor"}=$;return{name:`${SK1}_${A}`,description:Q,inputSchema:B.shape,handler:async(Y,I)=>{let X=B.safeParse(Y);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.errors.map((H)=>`${H.path.join(".")}: ${H.message}`).join(", ")}`};try{return await w(X.data,I)}catch(H){return{success:!1,error:L0(H)}}},visibility:D}}function vcA(A){if(A.entityType==="image"&&A.content.startsWith("data:"))return{...A,content:"[binary image data \u2014 use metadata for image info]"};return A}function XV(A){if(A===void 0)return;let Q=A.trim();return Q.length>0?Q:void 0}function hK1(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 ScA(A){let{entityService:Q,conversationService:B,logger:w,jobs:$,entityRegistry:D}=A;return[yQ("system","search","Search entities using semantic search. Optionally filter by entity type.",LcA,async(Y)=>({success:!0,data:{results:(await Q.search(Y.query,{limit:Y.limit??A.searchLimit,...Y.entityType&&{types:[Y.entityType]}})).map((I)=>({...I,entity:vcA(I.entity)}))}}),{visibility:"public",cli:{name:"search"}}),yQ("system","get","Retrieve a specific entity by type and identifier (ID, slug, or title).",McA,async(Y)=>{if(!Q.getEntityTypes().includes(Y.entityType))return{success:!1,error:`Unknown entity type: ${Y.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let I=await pH(Q,Y.entityType,Y.id,w);return I.ok?{success:!0,data:{entity:vcA(I.entity)}}:{success:!1,error:I.error}},{visibility:"public",cli:{name:"get"}}),yQ("system","list","List entities by type. Returns metadata only \u2014 use system_get for full content.",EcA,async(Y)=>{if(!Q.getEntityTypes().includes(Y.entityType))return{success:!1,error:`Unknown entity type: ${Y.entityType}. Available: ${Q.getEntityTypes().join(", ")}`};let I={limit:Y.limit??20};if(Y.status)I.filter={metadata:{status:Y.status}};let H=(await Q.listEntities(Y.entityType,I)).map(({content:W,contentHash:J,...F})=>F);return{success:!0,data:{entities:H,count:H.length}}},{visibility:"public",cli:{name:"list"}}),ZR("check-job-status","Check the status of background operations",kcA,async(Y)=>{if(Y.batchId){let H=await $.getBatchStatus(Y.batchId);if(!H)return{success:!1,error:`No batch found with ID: ${Y.batchId}`};let W=H.totalOperations>0?Math.round(H.completedOperations/H.totalOperations*100):0;return{success:!0,data:{batchId:Y.batchId,status:H.status,progress:{total:H.totalOperations,completed:H.completedOperations,failed:H.failedOperations,percentComplete:W},currentOperation:H.currentOperation,errors:H.errors}}}let I=await $.getActiveJobs(Y.jobTypes),X=await $.getActiveBatches();return{success:!0,data:{summary:{activeJobs:I.length,activeBatches:X.length},jobs:I.map((H)=>({id:H.id,type:H.type,status:H.status,priority:H.priority,retryCount:H.retryCount,createdAt:new Date(H.createdAt).toISOString(),startedAt:H.startedAt?new Date(H.startedAt).toISOString():null})),batches:X.map((H)=>({batchId:H.batchId,status:H.status.status,totalOperations:H.status.totalOperations,completedOperations:H.status.completedOperations,failedOperations:H.status.failedOperations,currentOperation:H.status.currentOperation,pluginId:H.metadata.metadata.pluginId,errors:H.status.errors}))}}},{visibility:"public"}),yQ("system","get-conversation","Get conversation details",PcA,async(Y)=>{let I=await B.getConversation(Y.conversationId);if(!I)return{success:!1,error:`Conversation not found: ${Y.conversationId}`};return{success:!0,data:{id:I.id,interfaceType:I.interfaceType,channelId:I.channelId,created:I.created,lastActive:I.lastActive}}},{visibility:"public"}),yQ("system","list-conversations","List conversations, optionally filtered by search query",_cA,async(Y)=>{let I=await B.searchConversations(Y.searchQuery??""),X=I.slice(0,Y.limit??20);return{success:!0,data:{conversations:X.map((H)=>({id:H.id,interfaceType:H.interfaceType,channelId:H.channelId,created:H.created,lastActive:H.lastActive})),totalFound:I.length,returned:X.length,searchQuery:Y.searchQuery}}},{visibility:"public"}),yQ("system","get-messages","Get messages from a specific conversation",bcA,async(Y)=>{let I=await B.getMessages(Y.conversationId,{limit:Y.limit??20});return{success:!0,data:{conversationId:Y.conversationId,messages:I.map((X)=>({id:X.id,role:X.role,content:X.content,timestamp:X.timestamp})),messageCount:I.length,requestedLimit:Y.limit??20}}},{visibility:"public"}),yQ("system","status","Get system status including model, version, interfaces, and tools",Z.object({}),async()=>({success:!0,data:await A.getAppInfo()}),{visibility:"public",cli:{name:"status"}}),ZR("create","Create a new entity. Provide content for direct creation, a prompt for AI generation, or a url for URL-first flows.",CcA,async(Y,I)=>{let X=XV(Y.prompt),H=XV(Y.content),W=XV(Y.title),J=XV(Y.url),F=XV(Y.targetEntityType),z=XV(Y.targetEntityId);if(!!F!==!!z)return{success:!1,error:"Provide both 'targetEntityType' and 'targetEntityId' together, or omit both."};if(!H&&!X&&!J)return{success:!1,error:"Provide 'content' (direct create), 'prompt' (AI generation), or 'url' (URL-first create), or a supported combination."};let V={entityType:Y.entityType,...X&&{prompt:X},...W&&{title:W},...H&&{content:H},...J&&{url:J},...F&&{targetEntityType:F},...z&&{targetEntityId:z}},E=A.entityRegistry.getCreateInterceptor(V.entityType);if(E){let _={interfaceType:I.interfaceType,userId:I.userId,...I.channelId&&{channelId:I.channelId},...I.channelName&&{channelName:I.channelName}},j=await E(V,_);if(j.kind==="handled")return j.result;V=j.input}if(!V.content&&!V.prompt)return{success:!1,error:"URL-only creation is supported only for entity types that explicitly handle it. Provide 'content' or 'prompt' for this entity type."};if(V.prompt)try{return{success:!0,data:{status:"generating",jobId:await $.enqueue(`${V.entityType}:generation`,{prompt:V.prompt,...V.title&&{title:V.title},...V.content&&{content:V.content},...V.targetEntityType&&{targetEntityType:V.targetEntityType},...V.targetEntityId&&{targetEntityId:V.targetEntityId}},I)}}}catch(_){return{success:!1,error:_ instanceof Error?_.message:"Failed to queue generation job"}}let L=e1(V.title??`${V.entityType}-${Date.now()}`),k=new Date().toISOString();try{return{success:!0,data:{entityId:(await Q.createEntity({id:L,entityType:V.entityType,content:V.content??"",metadata:{title:V.title??L},created:k,updated:k})).entityId,status:"created"}}}catch(_){return{success:!1,error:_ instanceof Error?_.message:"Failed to create entity"}}},{visibility:"trusted"}),ZR("delete","Delete an entity. Requires confirmation.",fcA,async(Y)=>{let I=await pH(Q,Y.entityType,Y.id,w);if(!I.ok)return{success:!1,error:I.error};let{entity:X}=I;if(Y.confirmed){try{await Q.deleteEntity(Y.entityType,X.id)}catch(W){return{success:!1,error:W instanceof Error?W.message:"Failed to delete entity"}}return{success:!0,data:{deleted:X.id}}}return{needsConfirmation:!0,toolName:"system_delete",description:`Delete "${typeof X.metadata.title==="string"?X.metadata.title:X.id}"?
|
|
529
530
|
|
|
530
531
|
Preview:
|
|
531
|
-
${X.content.slice(0,200)}`,args:{...Y,id:X.id,confirmed:!0}}},{visibility:"trusted"}),ZR("update","Update an entity's fields or content. Requires confirmation.",OcA,async(Y)=>{let I=await pH(Q,Y.entityType,Y.id,w);if(!I.ok)return{success:!1,error:I.error};let{entity:X}=I,H=hK1({...Y.fields!==void 0?{fields:Y.fields}:{},...Y.content!==void 0?{content:Y.content}:{}});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)"};if(Y.confirmed){if(Y.contentHash&&X.contentHash!==Y.contentHash)return{success:!1,error:"Entity was modified since you reviewed the changes. Please try again."};if(H.content!==void 0){let z=H.content.trim(),V=D.getEffectiveFrontmatterSchema(X.entityType);if(V){if(!z)return{success:!1,error:"Full content replacement cannot be empty for this entity type. Use 'fields' for partial updates."};try{D.getAdapter(X.entityType).parseFrontMatter(H.content,V)}catch{return{success:!1,error:"Invalid content replacement for this entity type. Provide full markdown with valid frontmatter, or use 'fields' for partial updates."}}}}let F=H.content!==void 0?{...X,content:H.content}:{...X,metadata:{...X.metadata,...H.fields}};try{await Q.updateEntity(F)}catch(z){return{success:!1,error:z instanceof Error?z.message:"Failed to update entity"}}return{success:!0,data:{updated:X.id}}}let W=typeof X.metadata.title==="string"?X.metadata.title:X.id,J;if(H.fields)J=Object.entries(H.fields).map(([F,z])=>`${F}: ${String(X.metadata[F]??"(empty)")} \u2192 ${String(z)}`).join(`
|
|
532
|
+
${X.content.slice(0,200)}`,args:{...Y,id:X.id,confirmed:!0}}},{visibility:"trusted"}),ZR("update","Update an entity's fields or content. Requires confirmation.",OcA,async(Y)=>{let I=await pH(Q,Y.entityType,Y.id,w);if(!I.ok)return{success:!1,error:I.error};let{entity:X}=I,H=hK1({...Y.fields!==void 0?{fields:Y.fields}:{},...Y.content!==void 0?{content:Y.content}:{}});if(!H.content&&!H.fields&&Y.confirmed&&X.entityType==="agent"&&X.metadata.status==="discovered")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)"};if(Y.confirmed){if(Y.contentHash&&X.contentHash!==Y.contentHash)return{success:!1,error:"Entity was modified since you reviewed the changes. Please try again."};if(H.content!==void 0){let z=H.content.trim(),V=D.getEffectiveFrontmatterSchema(X.entityType);if(V){if(!z)return{success:!1,error:"Full content replacement cannot be empty for this entity type. Use 'fields' for partial updates."};try{D.getAdapter(X.entityType).parseFrontMatter(H.content,V)}catch{return{success:!1,error:"Invalid content replacement for this entity type. Provide full markdown with valid frontmatter, or use 'fields' for partial updates."}}}}let F=H.content!==void 0?{...X,content:H.content}:{...X,metadata:{...X.metadata,...H.fields}};try{await Q.updateEntity(F)}catch(z){return{success:!1,error:z instanceof Error?z.message:"Failed to update entity"}}return{success:!0,data:{updated:X.id}}}let W=typeof X.metadata.title==="string"?X.metadata.title:X.id,J;if(H.fields)J=Object.entries(H.fields).map(([F,z])=>`${F}: ${String(X.metadata[F]??"(empty)")} \u2192 ${String(z)}`).join(`
|
|
532
533
|
`);else{let F=X.content.split(`
|
|
533
534
|
`),z=(H.content??"").split(`
|
|
534
535
|
`),V=[];for(let E=0;E<Math.max(F.length,z.length);E++)if((F[E]??"")!==(z[E]??"")){if(F[E])V.push(`- ${F[E]}`);if(z[E])V.push(`+ ${z[E]}`)}J=V.join(`
|
|
@@ -545,7 +546,7 @@ This will delete existing topics and regenerate them from scratch.`,args:{...Y,c
|
|
|
545
546
|
hash text NOT NULL,
|
|
546
547
|
created_at numeric
|
|
547
548
|
)
|
|
548
|
-
`;await A.session.run($);let Y=(await A.values(_A`SELECT id, hash, created_at FROM ${_A.identifier(w)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,I=[];for(let X of B)if(!Y||Number(Y[2])<X.folderMillis){for(let H of X.sql)I.push(A.run(_A.raw(H)));I.push(A.run(_A`INSERT INTO ${_A.identifier(w)} ("hash", "created_at") VALUES(${X.hash}, ${X.folderMillis})`))}await A.session.migrate(I)}var Ug=l(()=>{ocA();R5()});async function scA(A,Q){let B=Q?.child("entity-migrate")??T2.getInstance().child("entity-migrate"),{db:w,client:$,url:D}=lv(A);B.debug("Running entity database migrations...");try{await pv($,D);let I=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),await dv($),B.debug("Entity database migrations completed successfully")}catch(Y){throw B.error("Entity database migration failed:",Y),Y}finally{$.close()}}var acA=l(()=>{Ug();Qe();GA()});async function tcA(A,Q){let B=Q?.child("job-queue-migrate")??T2.getInstance().child("job-queue-migrate"),{db:w,client:$,url:D}=uv(A);B.debug("Running job queue migrations...");try{await cv($,D);let I=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),B.debug("Job queue migrations completed successfully")}catch(Y){throw B.error("Job queue migration failed:",Y),Y}finally{$.close()}}var ecA=l(()=>{Ug();tt();GA()});async function AlA(A,Q){let B=Q?.child("conversation-migrate")??T2.getInstance().child("conversation-migrate"),{db:w,client:$,url:D}=AS(A);B.debug("Running conversation database migrations...");try{if(D.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let I=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),B.debug("Conversation database migrations completed successfully")}catch(Y){throw B.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var QlA=l(()=>{Ug();je();GA()});class zR{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:rO,migrateEntities:scA,migrateJobQueue:tcA,migrateConversations:AlA}}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;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(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)}}var W6A=l(()=>{Hg();acA();ecA();QlA()});var Wg;var G6A=l(()=>{GA();Wg=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var wlA;var BlA=l(()=>{wlA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.37",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.1.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/react":"^19.0.3",typescript:"^5.3.3"}}});var ZQ=x((lK1,Gg)=>{(function(){function A(QA,FA){Object.defineProperty(w.prototype,QA,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",FA[0],FA[1])}})}function Q(QA){if(QA===null||typeof QA!=="object")return null;return QA=sA&&QA[sA]||QA["@@iterator"],typeof QA==="function"?QA:null}function B(QA,FA){QA=(QA=QA.constructor)&&(QA.displayName||QA.name)||"ReactClass";var nA=QA+"."+FA;JA[nA]||(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.",FA,QA),JA[nA]=!0)}function w(QA,FA,nA){this.props=QA,this.context=FA,this.refs=vA,this.updater=nA||MA}function $(){}function D(QA,FA,nA){this.props=QA,this.context=FA,this.refs=vA,this.updater=nA||MA}function Y(){}function I(QA){return""+QA}function X(QA){try{I(QA);var FA=!1}catch(m0){FA=!0}if(FA){FA=console;var nA=FA.error,y0=typeof Symbol==="function"&&Symbol.toStringTag&&QA[Symbol.toStringTag]||QA.constructor.name||"Object";return nA.call(FA,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y0),I(QA)}}function H(QA){if(QA==null)return null;if(typeof QA==="function")return QA.$$typeof===eA?null:QA.displayName||QA.name||null;if(typeof QA==="string")return QA;switch(QA){case e:return"Fragment";case KA:return"Profiler";case i:return"StrictMode";case h0:return"Suspense";case NA:return"SuspenseList";case VA:return"Activity"}if(typeof QA==="object")switch(typeof QA.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),QA.$$typeof){case d:return"Portal";case HA:return QA.displayName||"Context";case hA:return(QA._context.displayName||"Context")+".Consumer";case I0:var FA=QA.render;return QA=QA.displayName,QA||(QA=FA.displayName||FA.name||"",QA=QA!==""?"ForwardRef("+QA+")":"ForwardRef"),QA;case _0:return FA=QA.displayName||null,FA!==null?FA:H(QA.type)||"Memo";case X0:FA=QA._payload,QA=QA._init;try{return H(QA(FA))}catch(nA){}}return null}function W(QA){if(QA===e)return"<>";if(typeof QA==="object"&&QA!==null&&QA.$$typeof===X0)return"<...>";try{var FA=H(QA);return FA?"<"+FA+">":"<...>"}catch(nA){return"<...>"}}function J(){var QA=rA.A;return QA===null?null:QA.getOwner()}function F(){return Error("react-stack-top-frame")}function z(QA){if(CA.call(QA,"key")){var FA=Object.getOwnPropertyDescriptor(QA,"key").get;if(FA&&FA.isReactWarning)return!1}return QA.key!==void 0}function V(QA,FA){function nA(){AA||(AA=!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)",FA))}nA.isReactWarning=!0,Object.defineProperty(QA,"key",{get:nA,configurable:!0})}function E(){var QA=H(this.type);return c0[QA]||(c0[QA]=!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.")),QA=this.props.ref,QA!==void 0?QA:null}function L(QA,FA,nA,y0,m0,W1){var E0=nA.ref;return QA={$$typeof:s,type:QA,key:FA,props:nA,_owner:y0},(E0!==void 0?E0:null)!==null?Object.defineProperty(QA,"ref",{enumerable:!1,get:E}):Object.defineProperty(QA,"ref",{enumerable:!1,value:null}),QA._store={},Object.defineProperty(QA._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(QA,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(QA,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:m0}),Object.defineProperty(QA,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:W1}),Object.freeze&&(Object.freeze(QA.props),Object.freeze(QA)),QA}function k(QA,FA){return FA=L(QA.type,FA,QA.props,QA._owner,QA._debugStack,QA._debugTask),QA._store&&(FA._store.validated=QA._store.validated),FA}function _(QA){j(QA)?QA._store&&(QA._store.validated=1):typeof QA==="object"&&QA!==null&&QA.$$typeof===X0&&(QA._payload.status==="fulfilled"?j(QA._payload.value)&&QA._payload.value._store&&(QA._payload.value._store.validated=1):QA._store&&(QA._store.validated=1))}function j(QA){return typeof QA==="object"&&QA!==null&&QA.$$typeof===s}function r(QA){var FA={"=":"=0",":":"=2"};return"$"+QA.replace(/[=:]/g,function(nA){return FA[nA]})}function n(QA,FA){return typeof QA==="object"&&QA!==null&&QA.key!=null?(X(QA.key),r(""+QA.key)):FA.toString(36)}function g(QA){switch(QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason;default:switch(typeof QA.status==="string"?QA.then(Y,Y):(QA.status="pending",QA.then(function(FA){QA.status==="pending"&&(QA.status="fulfilled",QA.value=FA)},function(FA){QA.status==="pending"&&(QA.status="rejected",QA.reason=FA)})),QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason}}throw QA}function T(QA,FA,nA,y0,m0){var W1=typeof QA;if(W1==="undefined"||W1==="boolean")QA=null;var E0=!1;if(QA===null)E0=!0;else switch(W1){case"bigint":case"string":case"number":E0=!0;break;case"object":switch(QA.$$typeof){case s:case d:E0=!0;break;case X0:return E0=QA._init,T(E0(QA._payload),FA,nA,y0,m0)}}if(E0){E0=QA,m0=m0(E0);var E1=y0===""?"."+n(E0,0):y0;return D0(m0)?(nA="",E1!=null&&(nA=E1.replace(PA,"$&/")+"/"),T(m0,FA,nA,"",function(f2){return f2})):m0!=null&&(j(m0)&&(m0.key!=null&&(E0&&E0.key===m0.key||X(m0.key)),nA=k(m0,nA+(m0.key==null||E0&&E0.key===m0.key?"":(""+m0.key).replace(PA,"$&/")+"/")+E1),y0!==""&&E0!=null&&j(E0)&&E0.key==null&&E0._store&&!E0._store.validated&&(nA._store.validated=2),m0=nA),FA.push(m0)),1}if(E0=0,E1=y0===""?".":y0+":",D0(QA))for(var V1=0;V1<QA.length;V1++)y0=QA[V1],W1=E1+n(y0,V1),E0+=T(y0,FA,nA,W1,m0);else if(V1=Q(QA),typeof V1==="function")for(V1===QA.entries&&(TA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),TA=!0),QA=V1.call(QA),V1=0;!(y0=QA.next()).done;)y0=y0.value,W1=E1+n(y0,V1++),E0+=T(y0,FA,nA,W1,m0);else if(W1==="object"){if(typeof QA.then==="function")return T(g(QA),FA,nA,y0,m0);throw FA=String(QA),Error("Objects are not valid as a React child (found: "+(FA==="[object Object]"?"object with keys {"+Object.keys(QA).join(", ")+"}":FA)+"). If you meant to render a collection of children, use an array instead.")}return E0}function S(QA,FA,nA){if(QA==null)return QA;var y0=[],m0=0;return T(QA,y0,"","",function(W1){return FA.call(nA,W1,m0++)}),y0}function h(QA){if(QA._status===-1){var FA=QA._ioInfo;FA!=null&&(FA.start=FA.end=performance.now()),FA=QA._result;var nA=FA();if(nA.then(function(m0){if(QA._status===0||QA._status===-1){QA._status=1,QA._result=m0;var W1=QA._ioInfo;W1!=null&&(W1.end=performance.now()),nA.status===void 0&&(nA.status="fulfilled",nA.value=m0)}},function(m0){if(QA._status===0||QA._status===-1){QA._status=2,QA._result=m0;var W1=QA._ioInfo;W1!=null&&(W1.end=performance.now()),nA.status===void 0&&(nA.status="rejected",nA.reason=m0)}}),FA=QA._ioInfo,FA!=null){FA.value=nA;var y0=nA.displayName;typeof y0==="string"&&(FA.name=y0)}QA._status===-1&&(QA._status=0,QA._result=nA)}if(QA._status===1)return FA=QA._result,FA===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
549
|
+
`;await A.session.run($);let Y=(await A.values(_A`SELECT id, hash, created_at FROM ${_A.identifier(w)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,I=[];for(let X of B)if(!Y||Number(Y[2])<X.folderMillis){for(let H of X.sql)I.push(A.run(_A.raw(H)));I.push(A.run(_A`INSERT INTO ${_A.identifier(w)} ("hash", "created_at") VALUES(${X.hash}, ${X.folderMillis})`))}await A.session.migrate(I)}var Ug=l(()=>{ocA();R5()});async function scA(A,Q){let B=Q?.child("entity-migrate")??T2.getInstance().child("entity-migrate"),{db:w,client:$,url:D}=lv(A);B.debug("Running entity database migrations...");try{await pv($,D);let I=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),await dv($),B.debug("Entity database migrations completed successfully")}catch(Y){throw B.error("Entity database migration failed:",Y),Y}finally{$.close()}}var acA=l(()=>{Ug();Qe();GA()});async function tcA(A,Q){let B=Q?.child("job-queue-migrate")??T2.getInstance().child("job-queue-migrate"),{db:w,client:$,url:D}=uv(A);B.debug("Running job queue migrations...");try{await cv($,D);let I=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),B.debug("Job queue migrations completed successfully")}catch(Y){throw B.error("Job queue migration failed:",Y),Y}finally{$.close()}}var ecA=l(()=>{Ug();tt();GA()});async function AlA(A,Q){let B=Q?.child("conversation-migrate")??T2.getInstance().child("conversation-migrate"),{db:w,client:$,url:D}=AS(A);B.debug("Running conversation database migrations...");try{if(D.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let I=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await UV(w,{migrationsFolder:I}),B.debug("Conversation database migrations completed successfully")}catch(Y){throw B.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var QlA=l(()=>{Ug();je();GA()});class zR{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:rO,migrateEntities:scA,migrateJobQueue:tcA,migrateConversations:AlA}}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;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(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)}}var W6A=l(()=>{Hg();acA();ecA();QlA()});var Wg;var G6A=l(()=>{GA();Wg=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var wlA;var BlA=l(()=>{wlA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.38",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.1.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/react":"^19.0.3",typescript:"^5.3.3"}}});var ZQ=x((lK1,Gg)=>{(function(){function A(QA,FA){Object.defineProperty(w.prototype,QA,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",FA[0],FA[1])}})}function Q(QA){if(QA===null||typeof QA!=="object")return null;return QA=sA&&QA[sA]||QA["@@iterator"],typeof QA==="function"?QA:null}function B(QA,FA){QA=(QA=QA.constructor)&&(QA.displayName||QA.name)||"ReactClass";var nA=QA+"."+FA;JA[nA]||(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.",FA,QA),JA[nA]=!0)}function w(QA,FA,nA){this.props=QA,this.context=FA,this.refs=vA,this.updater=nA||MA}function $(){}function D(QA,FA,nA){this.props=QA,this.context=FA,this.refs=vA,this.updater=nA||MA}function Y(){}function I(QA){return""+QA}function X(QA){try{I(QA);var FA=!1}catch(m0){FA=!0}if(FA){FA=console;var nA=FA.error,y0=typeof Symbol==="function"&&Symbol.toStringTag&&QA[Symbol.toStringTag]||QA.constructor.name||"Object";return nA.call(FA,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y0),I(QA)}}function H(QA){if(QA==null)return null;if(typeof QA==="function")return QA.$$typeof===eA?null:QA.displayName||QA.name||null;if(typeof QA==="string")return QA;switch(QA){case e:return"Fragment";case KA:return"Profiler";case i:return"StrictMode";case h0:return"Suspense";case NA:return"SuspenseList";case VA:return"Activity"}if(typeof QA==="object")switch(typeof QA.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),QA.$$typeof){case d:return"Portal";case HA:return QA.displayName||"Context";case hA:return(QA._context.displayName||"Context")+".Consumer";case I0:var FA=QA.render;return QA=QA.displayName,QA||(QA=FA.displayName||FA.name||"",QA=QA!==""?"ForwardRef("+QA+")":"ForwardRef"),QA;case _0:return FA=QA.displayName||null,FA!==null?FA:H(QA.type)||"Memo";case X0:FA=QA._payload,QA=QA._init;try{return H(QA(FA))}catch(nA){}}return null}function W(QA){if(QA===e)return"<>";if(typeof QA==="object"&&QA!==null&&QA.$$typeof===X0)return"<...>";try{var FA=H(QA);return FA?"<"+FA+">":"<...>"}catch(nA){return"<...>"}}function J(){var QA=rA.A;return QA===null?null:QA.getOwner()}function F(){return Error("react-stack-top-frame")}function z(QA){if(CA.call(QA,"key")){var FA=Object.getOwnPropertyDescriptor(QA,"key").get;if(FA&&FA.isReactWarning)return!1}return QA.key!==void 0}function V(QA,FA){function nA(){AA||(AA=!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)",FA))}nA.isReactWarning=!0,Object.defineProperty(QA,"key",{get:nA,configurable:!0})}function E(){var QA=H(this.type);return c0[QA]||(c0[QA]=!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.")),QA=this.props.ref,QA!==void 0?QA:null}function L(QA,FA,nA,y0,m0,W1){var E0=nA.ref;return QA={$$typeof:s,type:QA,key:FA,props:nA,_owner:y0},(E0!==void 0?E0:null)!==null?Object.defineProperty(QA,"ref",{enumerable:!1,get:E}):Object.defineProperty(QA,"ref",{enumerable:!1,value:null}),QA._store={},Object.defineProperty(QA._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(QA,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(QA,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:m0}),Object.defineProperty(QA,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:W1}),Object.freeze&&(Object.freeze(QA.props),Object.freeze(QA)),QA}function k(QA,FA){return FA=L(QA.type,FA,QA.props,QA._owner,QA._debugStack,QA._debugTask),QA._store&&(FA._store.validated=QA._store.validated),FA}function _(QA){j(QA)?QA._store&&(QA._store.validated=1):typeof QA==="object"&&QA!==null&&QA.$$typeof===X0&&(QA._payload.status==="fulfilled"?j(QA._payload.value)&&QA._payload.value._store&&(QA._payload.value._store.validated=1):QA._store&&(QA._store.validated=1))}function j(QA){return typeof QA==="object"&&QA!==null&&QA.$$typeof===s}function r(QA){var FA={"=":"=0",":":"=2"};return"$"+QA.replace(/[=:]/g,function(nA){return FA[nA]})}function n(QA,FA){return typeof QA==="object"&&QA!==null&&QA.key!=null?(X(QA.key),r(""+QA.key)):FA.toString(36)}function g(QA){switch(QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason;default:switch(typeof QA.status==="string"?QA.then(Y,Y):(QA.status="pending",QA.then(function(FA){QA.status==="pending"&&(QA.status="fulfilled",QA.value=FA)},function(FA){QA.status==="pending"&&(QA.status="rejected",QA.reason=FA)})),QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason}}throw QA}function T(QA,FA,nA,y0,m0){var W1=typeof QA;if(W1==="undefined"||W1==="boolean")QA=null;var E0=!1;if(QA===null)E0=!0;else switch(W1){case"bigint":case"string":case"number":E0=!0;break;case"object":switch(QA.$$typeof){case s:case d:E0=!0;break;case X0:return E0=QA._init,T(E0(QA._payload),FA,nA,y0,m0)}}if(E0){E0=QA,m0=m0(E0);var E1=y0===""?"."+n(E0,0):y0;return D0(m0)?(nA="",E1!=null&&(nA=E1.replace(PA,"$&/")+"/"),T(m0,FA,nA,"",function(f2){return f2})):m0!=null&&(j(m0)&&(m0.key!=null&&(E0&&E0.key===m0.key||X(m0.key)),nA=k(m0,nA+(m0.key==null||E0&&E0.key===m0.key?"":(""+m0.key).replace(PA,"$&/")+"/")+E1),y0!==""&&E0!=null&&j(E0)&&E0.key==null&&E0._store&&!E0._store.validated&&(nA._store.validated=2),m0=nA),FA.push(m0)),1}if(E0=0,E1=y0===""?".":y0+":",D0(QA))for(var V1=0;V1<QA.length;V1++)y0=QA[V1],W1=E1+n(y0,V1),E0+=T(y0,FA,nA,W1,m0);else if(V1=Q(QA),typeof V1==="function")for(V1===QA.entries&&(TA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),TA=!0),QA=V1.call(QA),V1=0;!(y0=QA.next()).done;)y0=y0.value,W1=E1+n(y0,V1++),E0+=T(y0,FA,nA,W1,m0);else if(W1==="object"){if(typeof QA.then==="function")return T(g(QA),FA,nA,y0,m0);throw FA=String(QA),Error("Objects are not valid as a React child (found: "+(FA==="[object Object]"?"object with keys {"+Object.keys(QA).join(", ")+"}":FA)+"). If you meant to render a collection of children, use an array instead.")}return E0}function S(QA,FA,nA){if(QA==null)return QA;var y0=[],m0=0;return T(QA,y0,"","",function(W1){return FA.call(nA,W1,m0++)}),y0}function h(QA){if(QA._status===-1){var FA=QA._ioInfo;FA!=null&&(FA.start=FA.end=performance.now()),FA=QA._result;var nA=FA();if(nA.then(function(m0){if(QA._status===0||QA._status===-1){QA._status=1,QA._result=m0;var W1=QA._ioInfo;W1!=null&&(W1.end=performance.now()),nA.status===void 0&&(nA.status="fulfilled",nA.value=m0)}},function(m0){if(QA._status===0||QA._status===-1){QA._status=2,QA._result=m0;var W1=QA._ioInfo;W1!=null&&(W1.end=performance.now()),nA.status===void 0&&(nA.status="rejected",nA.reason=m0)}}),FA=QA._ioInfo,FA!=null){FA.value=nA;var y0=nA.displayName;typeof y0==="string"&&(FA.name=y0)}QA._status===-1&&(QA._status=0,QA._result=nA)}if(QA._status===1)return FA=QA._result,FA===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
549
550
|
|
|
550
551
|
Your code should look like:
|
|
551
552
|
const MyComponent = lazy(() => import('./MyComponent'))
|
|
@@ -1599,7 +1600,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
|
|
|
1599
1600
|
Title: "${A.entityTitle??I}"
|
|
1600
1601
|
|
|
1601
1602
|
Content:
|
|
1602
|
-
${A.entityContent}`,ZF1);X=w+k.imagePrompt}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:L0(k)})}}await this.reportProgress(B,{progress:J2.PROCESS,message:"Generating image"});let H=this.context.identity.get(),W=this.context.identity.getProfile(),F=wnA(H,W)+X,z;try{z=await this.context.ai.generateImage(F,{...$&&{aspectRatio:$}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:L0(k)}),K6.failure(k)}await this.reportProgress(B,{progress:J2.GENERATE,message:"Creating image entity"});let V=e1(I),E=nW.createImageEntity({dataUrl:z.dataUrl,title:I});if(await this.context.entityService.getEntity("image",V))this.logger.debug("Deleting existing image for regeneration",{imageId:V}),await this.context.entityService.deleteEntity("image",V);if(await this.context.entityService.createEntity({...E,id:V}),this.logger.debug("Created image entity",{imageId:V}),D&&Y){await this.reportProgress(B,{progress:J2.SAVE,message:`Updating ${D} with cover image`});let k=await av(this.context.entityService,D,Y,this.logger);if(!k)return K6.failure(Error(`Target entity not found: ${D}/${Y}`));let _=uq(k,V);await this.context.entities.update(_),this.logger.debug("Updated target entity with cover image",{targetEntityType:D,targetEntityId:Y,imageId:V})}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:V,targetEntityType:D,targetEntityId:Y}),{success:!0,imageId:V}}catch(X){return this.logger.error("Image generation job failed",{jobId:Q,error:L0(X)}),K6.failure(X)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}var $nA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.37",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/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 NF1=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});class VwA extends HQ{entityType=nW.entityType;schema=wj;adapter=nW;constructor(A={}){super("image",$nA,A,NF1)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,B){if(!A.targetEntityType||!A.targetEntityId)return{kind:"continue",input:A};let w=await pH(B.entityService,A.targetEntityType,A.targetEntityId,this.logger,"Target entity");if(!w.ok)return{kind:"handled",result:{success:!1,error:w.error}};return{kind:"continue",input:{...A,targetEntityId:w.entity.id}}}createGenerationHandler(A){return new Ry(A,this.logger)}async onRegister(A){let Q=new Ry(A,this.logger);A.jobs.registerHandler("image-generate",Q)}}function Yj(A){return new VwA(A)}B0();import{StdioServerTransport as VF1}from"@modelcontextprotocol/sdk/server/stdio.js";function DnA(){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 LwA(){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 jy(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(B,...w)=>Q.info(B,...w),debug:(B,...w)=>Q.debug(B,...w),error:(B,...w)=>Q.error(B,...w),warn:(B,...w)=>Q.warn(B,...w)}}return LwA()}class JY{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return JY.instance??=new JY(A),JY.instance}static resetInstance(){if(JY.instance)JY.instance.stop(),JY.instance=null}static createFresh(A){return new JY(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?jy(this.config.logger):DnA()}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 VF1,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 YnA}from"crypto";import{WebStandardStreamableHTTPServerTransport as LF1}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as MF1}from"@modelcontextprotocol/sdk/types.js";var EF1={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id","X-Content-Type-Options":"nosniff"};class KK{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?jy(this.config.logger):LwA(),this.authConfig=A.auth??{},!this.authConfig.disabled&&!this.authConfig.token)throw Error("MCP HTTP transport requires an auth token. Set MCP_AUTH_TOKEN in your environment, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return KK.instance??=new KK(A),KK.instance}static resetInstance(){KK.instance=null}static createFresh(A){return new KK(A)}withCors(A){let Q=new Headers(A.headers);for(let[B,w]of Object.entries(EF1))Q.set(B,w);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"}}))}getUnauthorizedResponse(A){return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},401)}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||!this.authConfig.token)return null;let B=A.headers.get("authorization");if(!B?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getUnauthorizedResponse("Unauthorized: Bearer token required");if(B.substring(7)!==this.authConfig.token)return this.logger.warn("Authentication failed: Invalid token"),this.getUnauthorizedResponse("Unauthorized: Invalid token");return this.logger.debug("Authentication successful"),null}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 B=await A.json();this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let w;if(Q&&this.transports[Q])w=this.transports[Q];else if(!Q&&MF1(B))w=new LF1({sessionIdGenerator:()=>YnA(),onsessioninitialized:(D)=>{this.logger.info(`Session initialized: ${D}`),this.transports[D]=w},onsessionclosed:(D)=>{this.logger.info(`Session closed: ${D}`),delete this.transports[D]}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(w);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await w.handleRequest(A,{parsedBody:B}))}catch(w){return this.logger.error("MCP transport error:",w),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:B}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'message' field"},400);let w=B??YnA();this.logger.debug(`POST /api/chat - conversation: ${w}`);try{let $=await this.agentService.chat(Q,w);return this.createJsonResponse($)}catch($){return this.logger.error("Agent chat error:",$),this.createJsonResponse({error:$ instanceof Error?$.message:"Internal error"},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let B=this.authenticate(A);if(B)return B;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);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:(B)=>this.handleRequest(B)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(B){if(B.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw B}}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}}GA();var MwA=Z.object({transport:Z.enum(["stdio","http"]).default("http"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional()});function InA(A,Q){return[]}B0();function EwA(A,Q){A.messaging.subscribe("job-progress",async(B)=>{let w=HN.safeParse(B.payload);if(!w.success)return Q.warn("Received invalid job-progress message",{error:w.error.message}),{success:!1};let $=w.data,D=$.type,Y=$.status,I=$.id;if(Q.debug(`${D} ${I} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${I}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${I}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var XnA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.37",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/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 oW extends yI{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",XnA,Q,MwA)}async getTools(){return InA(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});EwA(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;return this.httpServer=KK.createFresh({port:this.config.httpPort,logger:this.logger,auth:this.config.authToken?{token:this.config.authToken}:{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",B=this.context.permissions.getUserLevel("mcp",Q);if(this.config.transport==="http"&&this.config.authToken)B="anchor",this.logger.debug("HTTP auth token configured - authenticated users will have anchor permissions");if(this.mcpTransport.setPermissionLevel(B),this.logger.debug(`Starting MCP ${this.config.transport} transport with ${B} permissions`),this.config.transport==="stdio"){this.stdioServer=JY.createFresh();let w=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(w),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let w=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(w,this.mcpTransport),this.httpServer.connectAgentService(A.agentService),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(){JY.resetInstance(),KK.resetInstance()}}B0();GA();var t4=o0(RF0(),1);GA();B0();var DIA=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...wS.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var jF0={name:"@brains/discord",private:!0,version:"0.2.0-alpha.37",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 YIA=2000,ya1=8000,ma1=100;function Tc(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class PG extends tD{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",jF0,A,DIA);this.fetchText=Q.fetchText??Hv}async onRegister(A){await super.onRegister(A),this.client=new t4.Client({intents:[t4.GatewayIntentBits.Guilds,t4.GatewayIntentBits.GuildMessages,t4.GatewayIntentBits.MessageContent,t4.GatewayIntentBits.DirectMessages],partials:[t4.Partials.Channel]}),this.client.on(t4.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.once(t4.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(A,Q){if(!A||!this.client)return;let B=this.client.channels.cache.get(A);if(!Tc(B))return;let w=IO(Q,YIA);for(let $ of w)B.send($).catch((D)=>this.logger.error("Failed to send message",{error:D}))}async sendMessageWithId(A,Q){if(!A||!this.client)return;let B=this.client.channels.cache.get(A);if(!Tc(B))return;let w=IO(Q,YIA),$;for(let D of w)$=(await B.send(D)).id;return $}async editMessage(A,Q,B){if(!A||!this.client)return!1;let w=this.client.channels.cache.get(A);if(!Tc(w))return!1;try{return await(await w.messages.fetch(Q)).edit(B.slice(0,YIA)),!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,B=A.channel.isThread();if(Q&&!this.config.allowDMs)return;let w=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!w)return;let $=B&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id;if(this.config.allowedChannels.length>0&&!Q&&!this.config.allowedChannels.includes(A.channel.id))return;if(!Q&&!$&&this.config.requireMention&&!w){if(this.config.captureUrls){let I=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(I.length>0){await A.react(this.config.captureUrlEmoji).catch((X)=>this.logger.debug("React failed",{error:X}));for(let X of I)await this.captureUrlViaAgent(X,A.channel.id,A.author.id,"discord").catch((H)=>this.logger.error("URL capture failed",{error:H,url:X}))}}return}let D=this.stripMention(A.content);if(A.attachments.size>0){let I=this.context.permissions.getUserLevel("discord",A.author.id);if(I==="anchor"||I==="trusted")for(let H of A.attachments.values()){let W=H.name,J=H.contentType??void 0,F=H.size;if(!this.isUploadableTextFile(W,J))continue;if(!this.isFileSizeAllowed(F))continue;try{let z=await this.fetchText(H.url);D+=`
|
|
1603
|
+
${A.entityContent}`,ZF1);X=w+k.imagePrompt}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:L0(k)})}}await this.reportProgress(B,{progress:J2.PROCESS,message:"Generating image"});let H=this.context.identity.get(),W=this.context.identity.getProfile(),F=wnA(H,W)+X,z;try{z=await this.context.ai.generateImage(F,{...$&&{aspectRatio:$}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:L0(k)}),K6.failure(k)}await this.reportProgress(B,{progress:J2.GENERATE,message:"Creating image entity"});let V=e1(I),E=nW.createImageEntity({dataUrl:z.dataUrl,title:I});if(await this.context.entityService.getEntity("image",V))this.logger.debug("Deleting existing image for regeneration",{imageId:V}),await this.context.entityService.deleteEntity("image",V);if(await this.context.entityService.createEntity({...E,id:V}),this.logger.debug("Created image entity",{imageId:V}),D&&Y){await this.reportProgress(B,{progress:J2.SAVE,message:`Updating ${D} with cover image`});let k=await av(this.context.entityService,D,Y,this.logger);if(!k)return K6.failure(Error(`Target entity not found: ${D}/${Y}`));let _=uq(k,V);await this.context.entities.update(_),this.logger.debug("Updated target entity with cover image",{targetEntityType:D,targetEntityId:Y,imageId:V})}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:V,targetEntityType:D,targetEntityId:Y}),{success:!0,imageId:V}}catch(X){return this.logger.error("Image generation job failed",{jobId:Q,error:L0(X)}),K6.failure(X)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}var $nA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.38",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/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 NF1=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});class VwA extends HQ{entityType=nW.entityType;schema=wj;adapter=nW;constructor(A={}){super("image",$nA,A,NF1)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,B){if(!A.targetEntityType||!A.targetEntityId)return{kind:"continue",input:A};let w=await pH(B.entityService,A.targetEntityType,A.targetEntityId,this.logger,"Target entity");if(!w.ok)return{kind:"handled",result:{success:!1,error:w.error}};return{kind:"continue",input:{...A,targetEntityId:w.entity.id}}}createGenerationHandler(A){return new Ry(A,this.logger)}async onRegister(A){let Q=new Ry(A,this.logger);A.jobs.registerHandler("image-generate",Q)}}function Yj(A){return new VwA(A)}B0();import{StdioServerTransport as VF1}from"@modelcontextprotocol/sdk/server/stdio.js";function DnA(){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 LwA(){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 jy(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(B,...w)=>Q.info(B,...w),debug:(B,...w)=>Q.debug(B,...w),error:(B,...w)=>Q.error(B,...w),warn:(B,...w)=>Q.warn(B,...w)}}return LwA()}class JY{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return JY.instance??=new JY(A),JY.instance}static resetInstance(){if(JY.instance)JY.instance.stop(),JY.instance=null}static createFresh(A){return new JY(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?jy(this.config.logger):DnA()}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 VF1,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 YnA}from"crypto";import{WebStandardStreamableHTTPServerTransport as LF1}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as MF1}from"@modelcontextprotocol/sdk/types.js";var EF1={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id","X-Content-Type-Options":"nosniff"};class KK{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?jy(this.config.logger):LwA(),this.authConfig=A.auth??{},!this.authConfig.disabled&&!this.authConfig.token)throw Error("MCP HTTP transport requires an auth token. Set MCP_AUTH_TOKEN in your environment, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return KK.instance??=new KK(A),KK.instance}static resetInstance(){KK.instance=null}static createFresh(A){return new KK(A)}withCors(A){let Q=new Headers(A.headers);for(let[B,w]of Object.entries(EF1))Q.set(B,w);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"}}))}getUnauthorizedResponse(A){return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},401)}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||!this.authConfig.token)return null;let B=A.headers.get("authorization");if(!B?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getUnauthorizedResponse("Unauthorized: Bearer token required");if(B.substring(7)!==this.authConfig.token)return this.logger.warn("Authentication failed: Invalid token"),this.getUnauthorizedResponse("Unauthorized: Invalid token");return this.logger.debug("Authentication successful"),null}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 B=await A.json();this.logger.debug(`POST /mcp - Session: ${Q??"new"}`);try{let w;if(Q&&this.transports[Q])w=this.transports[Q];else if(!Q&&MF1(B))w=new LF1({sessionIdGenerator:()=>YnA(),onsessioninitialized:(D)=>{this.logger.info(`Session initialized: ${D}`),this.transports[D]=w},onsessionclosed:(D)=>{this.logger.info(`Session closed: ${D}`),delete this.transports[D]}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(w);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await w.handleRequest(A,{parsedBody:B}))}catch(w){return this.logger.error("MCP transport error:",w),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:B}=await A.json();if(!Q||typeof Q!=="string")return this.createJsonResponse({error:"Missing or invalid 'message' field"},400);let w=B??YnA();this.logger.debug(`POST /api/chat - conversation: ${w}`);try{let $=await this.agentService.chat(Q,w);return this.createJsonResponse($)}catch($){return this.logger.error("Agent chat error:",$),this.createJsonResponse({error:$ instanceof Error?$.message:"Internal error"},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let B=this.authenticate(A);if(B)return B;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);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:(B)=>this.handleRequest(B)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(B){if(B.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw B}}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}}GA();var MwA=Z.object({transport:Z.enum(["stdio","http"]).default("http"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional()});function InA(A,Q){return[]}B0();function EwA(A,Q){A.messaging.subscribe("job-progress",async(B)=>{let w=HN.safeParse(B.payload);if(!w.success)return Q.warn("Received invalid job-progress message",{error:w.error.message}),{success:!1};let $=w.data,D=$.type,Y=$.status,I=$.id;if(Q.debug(`${D} ${I} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${I}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${I}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var XnA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.38",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/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 oW extends yI{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",XnA,Q,MwA)}async getTools(){return InA(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});EwA(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;return this.httpServer=KK.createFresh({port:this.config.httpPort,logger:this.logger,auth:this.config.authToken?{token:this.config.authToken}:{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",B=this.context.permissions.getUserLevel("mcp",Q);if(this.config.transport==="http"&&this.config.authToken)B="anchor",this.logger.debug("HTTP auth token configured - authenticated users will have anchor permissions");if(this.mcpTransport.setPermissionLevel(B),this.logger.debug(`Starting MCP ${this.config.transport} transport with ${B} permissions`),this.config.transport==="stdio"){this.stdioServer=JY.createFresh();let w=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(w),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let w=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(w,this.mcpTransport),this.httpServer.connectAgentService(A.agentService),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(){JY.resetInstance(),KK.resetInstance()}}B0();GA();var t4=o0(RF0(),1);GA();B0();var DIA=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...wS.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var jF0={name:"@brains/discord",private:!0,version:"0.2.0-alpha.38",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 YIA=2000,ya1=8000,ma1=100;function Tc(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class PG extends tD{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",jF0,A,DIA);this.fetchText=Q.fetchText??Hv}async onRegister(A){await super.onRegister(A),this.client=new t4.Client({intents:[t4.GatewayIntentBits.Guilds,t4.GatewayIntentBits.GuildMessages,t4.GatewayIntentBits.MessageContent,t4.GatewayIntentBits.DirectMessages],partials:[t4.Partials.Channel]}),this.client.on(t4.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.once(t4.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(A,Q){if(!A||!this.client)return;let B=this.client.channels.cache.get(A);if(!Tc(B))return;let w=IO(Q,YIA);for(let $ of w)B.send($).catch((D)=>this.logger.error("Failed to send message",{error:D}))}async sendMessageWithId(A,Q){if(!A||!this.client)return;let B=this.client.channels.cache.get(A);if(!Tc(B))return;let w=IO(Q,YIA),$;for(let D of w)$=(await B.send(D)).id;return $}async editMessage(A,Q,B){if(!A||!this.client)return!1;let w=this.client.channels.cache.get(A);if(!Tc(w))return!1;try{return await(await w.messages.fetch(Q)).edit(B.slice(0,YIA)),!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,B=A.channel.isThread();if(Q&&!this.config.allowDMs)return;let w=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!w)return;let $=B&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id;if(this.config.allowedChannels.length>0&&!Q&&!this.config.allowedChannels.includes(A.channel.id))return;if(!Q&&!$&&this.config.requireMention&&!w){if(this.config.captureUrls){let I=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(I.length>0){await A.react(this.config.captureUrlEmoji).catch((X)=>this.logger.debug("React failed",{error:X}));for(let X of I)await this.captureUrlViaAgent(X,A.channel.id,A.author.id,"discord").catch((H)=>this.logger.error("URL capture failed",{error:H,url:X}))}}return}let D=this.stripMention(A.content);if(A.attachments.size>0){let I=this.context.permissions.getUserLevel("discord",A.author.id);if(I==="anchor"||I==="trusted")for(let H of A.attachments.values()){let W=H.name,J=H.contentType??void 0,F=H.size;if(!this.isUploadableTextFile(W,J))continue;if(!this.isFileSizeAllowed(F))continue;try{let z=await this.fetchText(H.url);D+=`
|
|
1603
1604
|
|
|
1604
1605
|
`+this.formatFileUploadMessage(W,z)}catch(z){this.logger.error("Failed to download attachment",{error:z,filename:W})}}}if(D=D.trim(),!D)return;let Y=A.channel.id;await this.routeToAgent(D,Y,A)}async routeToAgent(A,Q,B){if(!this.context)return;let w=this.context.agentService,$=Q;if(this.config.useThreads&&B.guild&&!B.channel.isThread())try{$=(await B.startThread({name:FW(A,ma1),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(X){this.logger.error("Failed to create thread",{error:X})}let D=`discord-${$}`,Y=this.context.permissions.getUserLevel("discord",B.author.id),I=B.guild?.name??"DM";this.startProcessingInput($);try{let X=this.client?.channels.cache.get($);if(Tc(X))this.startTypingIndicator(X);if(this.pendingConfirmations.has(D)){await this.handleConfirmationResponse(A,D,$);return}let H=await w.chat(A,D,{userPermissionLevel:Y,interfaceType:"discord",channelId:$,channelName:I});if(H.pendingConfirmation)this.pendingConfirmations.set(D,!0);let W=await this.sendMessageWithId($,H.text);if(W&&H.toolResults){for(let J of H.toolResults)if(J.jobId)this.trackAgentResponseForJob(J.jobId,W,$)}}catch(X){this.logger.error("Error handling message",{error:X,channelId:$}),this.sendMessageToChannel($,`**Error:** ${X instanceof Error?X.message:"Unknown error"}`)}finally{this.endProcessingInput(),this.stopTypingIndicator($)}}async handleConfirmationResponse(A,Q,B){let w=GN(A);if(!w){this.sendMessageToChannel(B,"_Please reply with **yes** to confirm or **no/cancel** to abort._");return}this.pendingConfirmations.delete(Q);let $=await this.context?.agentService.confirmPendingAction(Q,w.confirmed);if($)await this.sendMessageWithId(B,$.text)}startTypingIndicator(A){if(!this.config.showTypingIndicator)return;A.sendTyping().catch((B)=>this.logger.debug("Typing indicator failed",{error:B}));let Q=setInterval(()=>{A.sendTyping().catch((B)=>this.logger.debug("Typing indicator failed",{error:B}))},ya1);this.typingIntervals.set(A.id,Q)}stopTypingIndicator(A){let Q=this.typingIntervals.get(A);if(Q)clearInterval(Q),this.typingIntervals.delete(A)}stripMention(A){if(!this.client?.user)return A;return A.replace(new RegExp(`<@!?${this.client.user.id}>`,"g"),"").trim()}}B0();import{resolve as aL,join as ft1}from"path";var IIA=(A,Q,B)=>{return(w,$)=>{let D=-1;return Y(0);async function Y(I){if(I<=D)throw Error("next() called multiple times");D=I;let X,H=!1,W;if(A[I])W=A[I][0][0],w.req.routeIndex=I;else W=I===A.length&&$||void 0;if(W)try{X=await W(w,()=>Y(I+1))}catch(J){if(J instanceof Error&&Q)w.error=J,X=await Q(J,w),H=!0;else throw J}else if(w.finalized===!1&&B)X=await B(w);if(X&&(w.finalized===!1||H))w.res=X;return w}}};var kF0=Symbol();var PF0=async(A,Q=Object.create(null))=>{let{all:B=!1,dot:w=!1}=Q,D=(A instanceof vc?A.raw.headers:A.headers).get("Content-Type");if(D?.startsWith("multipart/form-data")||D?.startsWith("application/x-www-form-urlencoded"))return ua1(A,{all:B,dot:w});return{}};async function ua1(A,Q){let B=await A.formData();if(B)return ca1(B,Q);return{}}function ca1(A,Q){let B=Object.create(null);if(A.forEach((w,$)=>{if(!(Q.all||$.endsWith("[]")))B[$]=w;else la1(B,$,w)}),Q.dot)Object.entries(B).forEach(([w,$])=>{if(w.includes("."))pa1(B,w,$),delete B[w]});return B}var la1=(A,Q,B)=>{if(A[Q]!==void 0)if(Array.isArray(A[Q]))A[Q].push(B);else A[Q]=[A[Q],B];else if(!Q.endsWith("[]"))A[Q]=B;else A[Q]=[B]},pa1=(A,Q,B)=>{let w=A,$=Q.split(".");$.forEach((D,Y)=>{if(Y===$.length-1)w[D]=B;else{if(!w[D]||typeof w[D]!=="object"||Array.isArray(w[D])||w[D]instanceof File)w[D]=Object.create(null);w=w[D]}})};var HIA=(A)=>{let Q=A.split("/");if(Q[0]==="")Q.shift();return Q},_F0=(A)=>{let{groups:Q,path:B}=da1(A),w=HIA(B);return ia1(w,Q)},da1=(A)=>{let Q=[];return A=A.replace(/\{[^}]+\}/g,(B,w)=>{let $=`@${w}`;return Q.push([$,B]),$}),{groups:Q,path:A}},ia1=(A,Q)=>{for(let B=Q.length-1;B>=0;B--){let[w]=Q[B];for(let $=A.length-1;$>=0;$--)if(A[$].includes(w)){A[$]=A[$].replace(w,Q[B][1]);break}}return A},Sc={},bF0=(A,Q)=>{if(A==="*")return"*";let B=A.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(B){let w=`${A}#${Q}`;if(!Sc[w])if(B[2])Sc[w]=Q&&Q[0]!==":"&&Q[0]!=="*"?[w,B[1],new RegExp(`^${B[2]}(?=/${Q})`)]:[A,B[1],new RegExp(`^${B[2]}$`)];else Sc[w]=[A,B[1],!0];return Sc[w]}return null},hc=(A,Q)=>{try{return Q(A)}catch{return A.replace(/(?:%[0-9A-Fa-f]{2})+/g,(B)=>{try{return Q(B)}catch{return B}})}},KIA=(A)=>hc(A,decodeURI),UIA=(A)=>{let Q=A.url,B=Q.indexOf("/",Q.indexOf(":")+4),w=B;for(;w<Q.length;w++){let $=Q.charCodeAt(w);if($===37){let D=Q.indexOf("?",w),Y=Q.indexOf("#",w),I=D===-1?Y===-1?void 0:Y:Y===-1?D:Math.min(D,Y),X=Q.slice(B,I);return KIA(X.includes("%25")?X.replace(/%25/g,"%2525"):X)}else if($===63||$===35)break}return Q.slice(B,w)};var xF0=(A)=>{let Q=UIA(A);return Q.length>1&&Q.at(-1)==="/"?Q.slice(0,-1):Q},GZ=(A,Q,...B)=>{if(B.length)Q=GZ(Q,...B);return`${A?.[0]==="/"?"":"/"}${A}${Q==="/"?"":`${A?.at(-1)==="/"?"":"/"}${Q?.[0]==="/"?Q.slice(1):Q}`}`},gc=(A)=>{if(A.charCodeAt(A.length-1)!==63||!A.includes(":"))return null;let Q=A.split("/"),B=[],w="";return Q.forEach(($)=>{if($!==""&&!/\:/.test($))w+="/"+$;else if(/\:/.test($))if(/\?/.test($)){if(B.length===0&&w==="")B.push("/");else B.push(w);let D=$.replace("?","");w+="/"+D,B.push(w)}else w+="/"+$}),B.filter(($,D,Y)=>Y.indexOf($)===D)},XIA=(A)=>{if(!/[%+]/.test(A))return A;if(A.indexOf("+")!==-1)A=A.replace(/\+/g," ");return A.indexOf("%")!==-1?hc(A,WIA):A},TF0=(A,Q,B)=>{let w;if(!B&&Q&&!/[%+]/.test(Q)){let Y=A.indexOf("?",8);if(Y===-1)return;if(!A.startsWith(Q,Y+1))Y=A.indexOf(`&${Q}`,Y+1);while(Y!==-1){let I=A.charCodeAt(Y+Q.length+1);if(I===61){let X=Y+Q.length+2,H=A.indexOf("&",X);return XIA(A.slice(X,H===-1?void 0:H))}else if(I==38||isNaN(I))return"";Y=A.indexOf(`&${Q}`,Y+1)}if(w=/[%+]/.test(A),!w)return}let $={};w??=/[%+]/.test(A);let D=A.indexOf("?",8);while(D!==-1){let Y=A.indexOf("&",D+1),I=A.indexOf("=",D);if(I>Y&&Y!==-1)I=-1;let X=A.slice(D+1,I===-1?Y===-1?void 0:Y:I);if(w)X=XIA(X);if(D=Y,X==="")continue;let H;if(I===-1)H="";else if(H=A.slice(I+1,Y===-1?void 0:Y),w)H=XIA(H);if(B){if(!($[X]&&Array.isArray($[X])))$[X]=[];$[X].push(H)}else $[X]??=H}return Q?$[Q]:$},vF0=TF0,SF0=(A,Q)=>{return TF0(A,Q,!0)},WIA=decodeURIComponent;var hF0=(A)=>hc(A,WIA),vc=class{raw;#A;#Q;routeIndex=0;path;bodyCache={};constructor(A,Q="/",B=[[]]){this.raw=A,this.path=Q,this.#Q=B,this.#A={}}param(A){return A?this.#B(A):this.#D()}#B(A){let Q=this.#Q[0][this.routeIndex][1][A],B=this.#$(Q);return B&&/\%/.test(B)?hF0(B):B}#D(){let A={},Q=Object.keys(this.#Q[0][this.routeIndex][1]);for(let B of Q){let w=this.#$(this.#Q[0][this.routeIndex][1][B]);if(w!==void 0)A[B]=/\%/.test(w)?hF0(w):w}return A}#$(A){return this.#Q[1]?this.#Q[1][A]:A}query(A){return vF0(this.url,A)}queries(A){return SF0(this.url,A)}header(A){if(A)return this.raw.headers.get(A)??void 0;let Q={};return this.raw.headers.forEach((B,w)=>{Q[w]=B}),Q}async parseBody(A){return this.bodyCache.parsedBody??=await PF0(this,A)}#w=(A)=>{let{bodyCache:Q,raw:B}=this,w=Q[A];if(w)return w;let $=Object.keys(Q)[0];if($)return Q[$].then((D)=>{if($==="json")D=JSON.stringify(D);return new Response(D)[A]()});return Q[A]=B[A]()};json(){return this.#w("text").then((A)=>JSON.parse(A))}text(){return this.#w("text")}arrayBuffer(){return this.#w("arrayBuffer")}blob(){return this.#w("blob")}formData(){return this.#w("formData")}addValidatedData(A,Q){this.#A[A]=Q}valid(A){return this.#A[A]}get url(){return this.raw.url}get method(){return this.raw.method}get[kF0](){return this.#Q}get matchedRoutes(){return this.#Q[0].map(([[,A]])=>A)}get routePath(){return this.#Q[0].map(([[,A]])=>A)[this.routeIndex].path}};var gF0={Stringify:1,BeforeStream:2,Stream:3},yF0=(A,Q)=>{let B=new String(A);return B.isEscaped=!0,B.callbacks=Q,B};var GIA=async(A,Q,B,w,$)=>{if(typeof A==="object"&&!(A instanceof String)){if(!(A instanceof Promise))A=A.toString();if(A instanceof Promise)A=await A}let D=A.callbacks;if(!D?.length)return Promise.resolve(A);if($)$[0]+=A;else $=[A];let Y=Promise.all(D.map((I)=>I({phase:Q,buffer:$,context:w}))).then((I)=>Promise.all(I.filter(Boolean).map((X)=>GIA(X,Q,!1,w,$))).then(()=>$[0]));if(B)return yF0(await Y,D);else return Y};var ra1="text/plain; charset=UTF-8",JIA=(A,Q)=>{return{"Content-Type":A,...Q}},pk=(A,Q)=>new Response(A,Q),mF0=class{#A;#Q;env={};#B;finalized=!1;error;#D;#$;#w;#K;#X;#H;#I;#U;#W;constructor(A,Q){if(this.#A=A,Q)this.#$=Q.executionCtx,this.env=Q.env,this.#H=Q.notFoundHandler,this.#W=Q.path,this.#U=Q.matchResult}get req(){return this.#Q??=new vc(this.#A,this.#W,this.#U),this.#Q}get event(){if(this.#$&&"respondWith"in this.#$)return this.#$;else throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#$)return this.#$;else throw Error("This context has no ExecutionContext")}get res(){return this.#w||=pk(null,{headers:this.#I??=new Headers})}set res(A){if(this.#w&&A){A=pk(A.body,A);for(let[Q,B]of this.#w.headers.entries()){if(Q==="content-type")continue;if(Q==="set-cookie"){let w=this.#w.headers.getSetCookie();A.headers.delete("set-cookie");for(let $ of w)A.headers.append("set-cookie",$)}else A.headers.set(Q,B)}}this.#w=A,this.finalized=!0}render=(...A)=>{return this.#X??=(Q)=>this.html(Q),this.#X(...A)};setLayout=(A)=>this.#K=A;getLayout=()=>this.#K;setRenderer=(A)=>{this.#X=A};header=(A,Q,B)=>{if(this.finalized)this.#w=pk(this.#w.body,this.#w);let w=this.#w?this.#w.headers:this.#I??=new Headers;if(Q===void 0)w.delete(A);else if(B?.append)w.append(A,Q);else w.set(A,Q)};status=(A)=>{this.#D=A};set=(A,Q)=>{this.#B??=new Map,this.#B.set(A,Q)};get=(A)=>{return this.#B?this.#B.get(A):void 0};get var(){if(!this.#B)return{};return Object.fromEntries(this.#B)}#Y(A,Q,B){let w=this.#w?new Headers(this.#w.headers):this.#I??new Headers;if(typeof Q==="object"&&"headers"in Q){let D=Q.headers instanceof Headers?Q.headers:new Headers(Q.headers);for(let[Y,I]of D)if(Y.toLowerCase()==="set-cookie")w.append(Y,I);else w.set(Y,I)}if(B)for(let[D,Y]of Object.entries(B))if(typeof Y==="string")w.set(D,Y);else{w.delete(D);for(let I of Y)w.append(D,I)}let $=typeof Q==="number"?Q:Q?.status??this.#D;return pk(A,{status:$,headers:w})}newResponse=(...A)=>this.#Y(...A);body=(A,Q,B)=>this.#Y(A,Q,B);text=(A,Q,B)=>{return!this.#I&&!this.#D&&!Q&&!B&&!this.finalized?new Response(A):this.#Y(A,Q,JIA(ra1,B))};json=(A,Q,B)=>{return this.#Y(JSON.stringify(A),Q,JIA("application/json",B))};html=(A,Q,B)=>{let w=($)=>this.#Y($,Q,JIA("text/html; charset=UTF-8",B));return typeof A==="object"?GIA(A,gF0.Stringify,!1,{}).then(w):w(A)};redirect=(A,Q)=>{let B=String(A);return this.header("Location",!/[^\x00-\xFF]/.test(B)?B:encodeURI(B)),this.newResponse(null,Q??302)};notFound=()=>{return this.#H??=()=>pk(),this.#H(this)}};var yB="ALL",uF0="all",cF0=["get","post","put","delete","options","patch"],yc="Can not add a route since the matcher is already built.",mc=class extends Error{};var FIA="__COMPOSED_HANDLER";var na1=(A)=>{return A.text("404 Not Found",404)},lF0=(A,Q)=>{if("getResponse"in A){let B=A.getResponse();return Q.newResponse(B.body,B)}return console.error(A),Q.text("Internal Server Error",500)},pF0=class A{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#A="/";routes=[];constructor(Q={}){[...cF0,uF0].forEach((D)=>{this[D]=(Y,...I)=>{if(typeof Y==="string")this.#A=Y;else this.#D(D,this.#A,Y);return I.forEach((X)=>{this.#D(D,this.#A,X)}),this}}),this.on=(D,Y,...I)=>{for(let X of[Y].flat()){this.#A=X;for(let H of[D].flat())I.map((W)=>{this.#D(H.toUpperCase(),this.#A,W)})}return this},this.use=(D,...Y)=>{if(typeof D==="string")this.#A=D;else this.#A="*",Y.unshift(D);return Y.forEach((I)=>{this.#D(yB,this.#A,I)}),this};let{strict:w,...$}=Q;Object.assign(this,$),this.getPath=w??!0?Q.getPath??UIA:xF0}#Q(){let Q=new A({router:this.router,getPath:this.getPath});return Q.errorHandler=this.errorHandler,Q.#B=this.#B,Q.routes=this.routes,Q}#B=na1;errorHandler=lF0;route(Q,B){let w=this.basePath(Q);return B.routes.map(($)=>{let D;if(B.errorHandler===lF0)D=$.handler;else D=async(Y,I)=>(await IIA([],B.errorHandler)(Y,()=>$.handler(Y,I))).res,D[FIA]=$.handler;w.#D($.method,$.path,D)}),this}basePath(Q){let B=this.#Q();return B._basePath=GZ(this._basePath,Q),B}onError=(Q)=>{return this.errorHandler=Q,this};notFound=(Q)=>{return this.#B=Q,this};mount(Q,B,w){let $,D;if(w)if(typeof w==="function")D=w;else if(D=w.optionHandler,w.replaceRequest===!1)$=(X)=>X;else $=w.replaceRequest;let Y=D?(X)=>{let H=D(X);return Array.isArray(H)?H:[H]}:(X)=>{let H=void 0;try{H=X.executionCtx}catch{}return[X.env,H]};$||=(()=>{let X=GZ(this._basePath,Q),H=X==="/"?0:X.length;return(W)=>{let J=new URL(W.url);return J.pathname=J.pathname.slice(H)||"/",new Request(J,W)}})();let I=async(X,H)=>{let W=await B($(X.req.raw),...Y(X));if(W)return W;await H()};return this.#D(yB,GZ(Q,"*"),I),this}#D(Q,B,w){Q=Q.toUpperCase(),B=GZ(this._basePath,B);let $={basePath:this._basePath,path:B,method:Q,handler:w};this.router.add(Q,B,[w,$]),this.routes.push($)}#$(Q,B){if(Q instanceof Error)return this.errorHandler(Q,B);throw Q}#w(Q,B,w,$){if($==="HEAD")return(async()=>new Response(null,await this.#w(Q,B,w,"GET")))();let D=this.getPath(Q,{env:w}),Y=this.router.match($,D),I=new mF0(Q,{path:D,matchResult:Y,env:w,executionCtx:B,notFoundHandler:this.#B});if(Y[0].length===1){let H;try{H=Y[0][0][0][0](I,async()=>{I.res=await this.#B(I)})}catch(W){return this.#$(W,I)}return H instanceof Promise?H.then((W)=>W||(I.finalized?I.res:this.#B(I))).catch((W)=>this.#$(W,I)):H??this.#B(I)}let X=IIA(Y[0],this.errorHandler,this.#B);return(async()=>{try{let H=await X(I);if(!H.finalized)throw Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return H.res}catch(H){return this.#$(H,I)}})()}fetch=(Q,...B)=>{return this.#w(Q,B[1],B[0],Q.method)};request=(Q,B,w,$)=>{if(Q instanceof Request)return this.fetch(B?new Request(Q,B):Q,w,$);return Q=Q.toString(),this.fetch(new Request(/^https?:\/\//.test(Q)?Q:`http://localhost${GZ("/",Q)}`,B),w,$)};fire=()=>{addEventListener("fetch",(Q)=>{Q.respondWith(this.#w(Q.request,Q,void 0,Q.request.method))})}};var dk=[];function uc(A,Q){let B=this.buildAllMatchers(),w=($,D)=>{let Y=B[$]||B[yB],I=Y[2][D];if(I)return I;let X=D.match(Y[0]);if(!X)return[[],dk];let H=X.indexOf("",1);return[Y[1][H],X]};return this.match=w,w(A,Q)}var cc="[^/]+",ik=".*",rk="(?:|/.*)",JZ=Symbol(),oa1=new Set(".\\+*[^]$()");function sa1(A,Q){if(A.length===1)return Q.length===1?A<Q?-1:1:-1;if(Q.length===1)return 1;if(A===ik||A===rk)return 1;else if(Q===ik||Q===rk)return-1;if(A===cc)return 1;else if(Q===cc)return-1;return A.length===Q.length?A<Q?-1:1:Q.length-A.length}var dF0=class A{#A;#Q;#B=Object.create(null);insert(Q,B,w,$,D){if(Q.length===0){if(this.#A!==void 0)throw JZ;if(D)return;this.#A=B;return}let[Y,...I]=Q,X=Y==="*"?I.length===0?["","",ik]:["","",cc]:Y==="/*"?["","",rk]:Y.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),H;if(X){let W=X[1],J=X[2]||cc;if(W&&X[2]){if(J===".*")throw JZ;if(J=J.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(J))throw JZ}if(H=this.#B[J],!H){if(Object.keys(this.#B).some((F)=>F!==ik&&F!==rk))throw JZ;if(D)return;if(H=this.#B[J]=new A,W!=="")H.#Q=$.varIndex++}if(!D&&W!=="")w.push([W,H.#Q])}else if(H=this.#B[Y],!H){if(Object.keys(this.#B).some((W)=>W.length>1&&W!==ik&&W!==rk))throw JZ;if(D)return;H=this.#B[Y]=new A}H.insert(I,B,w,$,D)}buildRegExpStr(){let B=Object.keys(this.#B).sort(sa1).map((w)=>{let $=this.#B[w];return(typeof $.#Q==="number"?`(${w})@${$.#Q}`:oa1.has(w)?`\\${w}`:w)+$.buildRegExpStr()});if(typeof this.#A==="number")B.unshift(`#${this.#A}`);if(B.length===0)return"";if(B.length===1)return B[0];return"(?:"+B.join("|")+")"}};var iF0=class{#A={varIndex:0};#Q=new dF0;insert(A,Q,B){let w=[],$=[];for(let Y=0;;){let I=!1;if(A=A.replace(/\{[^}]+\}/g,(X)=>{let H=`@\\${Y}`;return $[Y]=[H,X],Y++,I=!0,H}),!I)break}let D=A.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let Y=$.length-1;Y>=0;Y--){let[I]=$[Y];for(let X=D.length-1;X>=0;X--)if(D[X].indexOf(I)!==-1){D[X]=D[X].replace(I,$[Y][1]);break}}return this.#Q.insert(D,Q,w,this.#A,B),w}buildRegExp(){let A=this.#Q.buildRegExpStr();if(A==="")return[/^$/,[],[]];let Q=0,B=[],w=[];return A=A.replace(/#(\d+)|@(\d+)|\.\*\$/g,($,D,Y)=>{if(D!==void 0)return B[++Q]=Number(D),"$()";if(Y!==void 0)return w[Number(Y)]=++Q,"";return""}),[new RegExp(`^${A}`),B,w]}};var aa1=[/^$/,[],Object.create(null)],rF0=Object.create(null);function nF0(A){return rF0[A]??=new RegExp(A==="*"?"":`^${A.replace(/\/\*$|([.\\+*[^\]$()])/g,(Q,B)=>B?`\\${B}`:"(?:|/.*)")}$`)}function ta1(){rF0=Object.create(null)}function ea1(A){let Q=new iF0,B=[];if(A.length===0)return aa1;let w=A.map((H)=>[!/\*|\/:/.test(H[0]),...H]).sort(([H,W],[J,F])=>H?1:J?-1:W.length-F.length),$=Object.create(null);for(let H=0,W=-1,J=w.length;H<J;H++){let[F,z,V]=w[H];if(F)$[z]=[V.map(([L])=>[L,Object.create(null)]),dk];else W++;let E;try{E=Q.insert(z,W,F)}catch(L){throw L===JZ?new mc(z):L}if(F)continue;B[W]=V.map(([L,k])=>{let _=Object.create(null);k-=1;for(;k>=0;k--){let[j,r]=E[k];_[j]=r}return[L,_]})}let[D,Y,I]=Q.buildRegExp();for(let H=0,W=B.length;H<W;H++)for(let J=0,F=B[H].length;J<F;J++){let z=B[H][J]?.[1];if(!z)continue;let V=Object.keys(z);for(let E=0,L=V.length;E<L;E++)z[V[E]]=I[z[V[E]]]}let X=[];for(let H in Y)X[H]=B[Y[H]];return[D,X,$]}function nL(A,Q){if(!A)return;for(let B of Object.keys(A).sort((w,$)=>$.length-w.length))if(nF0(B).test(Q))return[...A[B]];return}var lc=class{name="RegExpRouter";#A;#Q;constructor(){this.#A={[yB]:Object.create(null)},this.#Q={[yB]:Object.create(null)}}add(A,Q,B){let w=this.#A,$=this.#Q;if(!w||!$)throw Error(yc);if(!w[A])[w,$].forEach((I)=>{I[A]=Object.create(null),Object.keys(I[yB]).forEach((X)=>{I[A][X]=[...I[yB][X]]})});if(Q==="/*")Q="*";let D=(Q.match(/\/:/g)||[]).length;if(/\*$/.test(Q)){let I=nF0(Q);if(A===yB)Object.keys(w).forEach((X)=>{w[X][Q]||=nL(w[X],Q)||nL(w[yB],Q)||[]});else w[A][Q]||=nL(w[A],Q)||nL(w[yB],Q)||[];Object.keys(w).forEach((X)=>{if(A===yB||A===X)Object.keys(w[X]).forEach((H)=>{I.test(H)&&w[X][H].push([B,D])})}),Object.keys($).forEach((X)=>{if(A===yB||A===X)Object.keys($[X]).forEach((H)=>I.test(H)&&$[X][H].push([B,D]))});return}let Y=gc(Q)||[Q];for(let I=0,X=Y.length;I<X;I++){let H=Y[I];Object.keys($).forEach((W)=>{if(A===yB||A===W)$[W][H]||=[...nL(w[W],H)||nL(w[yB],H)||[]],$[W][H].push([B,D-X+I+1])})}}match=uc;buildAllMatchers(){let A=Object.create(null);return Object.keys(this.#Q).concat(Object.keys(this.#A)).forEach((Q)=>{A[Q]||=this.#B(Q)}),this.#A=this.#Q=void 0,ta1(),A}#B(A){let Q=[],B=A===yB;if([this.#A,this.#Q].forEach((w)=>{let $=w[A]?Object.keys(w[A]).map((D)=>[D,w[A][D]]):[];if($.length!==0)B||=!0,Q.push(...$);else if(A!==yB)Q.push(...Object.keys(w[yB]).map((D)=>[D,w[yB][D]]))}),!B)return null;else return ea1(Q)}};var At1=class{name="PreparedRegExpRouter";#A;#Q;constructor(A,Q){this.#A=A,this.#Q=Q}#B(A,Q){let B=this.#A[A];B[1].forEach((w)=>w&&w.push(Q)),Object.values(B[2]).forEach((w)=>w[0].push(Q))}#D(A,Q,B,w,$){let D=this.#A[A];if(!$)D[2][Q][0].push([B,{}]);else w.forEach((Y)=>{if(typeof Y==="number")D[1][Y].push([B,$]);else D[2][Y||Q][0].push([B,$])})}add(A,Q,B){if(!this.#A[A]){let $=this.#A[yB],D={};for(let Y in $[2])D[Y]=[$[2][Y][0].slice(),dk];this.#A[A]=[$[0],$[1].map((Y)=>Array.isArray(Y)?Y.slice():0),D]}if(Q==="/*"||Q==="*"){let $=[B,{}];if(A===yB)for(let D in this.#A)this.#B(D,$);else this.#B(A,$);return}let w=this.#Q[Q];if(!w)throw Error(`Path ${Q} is not registered`);for(let[$,D]of w)if(A===yB)for(let Y in this.#A)this.#D(Y,Q,B,$,D);else this.#D(A,Q,B,$,D)}buildAllMatchers(){return this.#A}match=uc};var ZIA=class{name="SmartRouter";#A=[];#Q=[];constructor(A){this.#A=A.routers}add(A,Q,B){if(!this.#Q)throw Error(yc);this.#Q.push([A,Q,B])}match(A,Q){if(!this.#Q)throw Error("Fatal error");let B=this.#A,w=this.#Q,$=B.length,D=0,Y;for(;D<$;D++){let I=B[D];try{for(let X=0,H=w.length;X<H;X++)I.add(...w[X]);Y=I.match(A,Q)}catch(X){if(X instanceof mc)continue;throw X}this.match=I.match.bind(I),this.#A=[I],this.#Q=void 0;break}if(D===$)throw Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,Y}get activeRouter(){if(this.#Q||this.#A.length!==1)throw Error("No active router has been determined yet.");return this.#A[0]}};var nk=Object.create(null),Qt1=(A)=>{for(let Q in A)return!0;return!1},oF0=class A{#A;#Q;#B;#D=0;#$=nk;constructor(Q,B,w){if(this.#Q=w||Object.create(null),this.#A=[],Q&&B){let $=Object.create(null);$[Q]={handler:B,possibleKeys:[],score:0},this.#A=[$]}this.#B=[]}insert(Q,B,w){this.#D=++this.#D;let $=this,D=_F0(B),Y=[];for(let I=0,X=D.length;I<X;I++){let H=D[I],W=D[I+1],J=bF0(H,W),F=Array.isArray(J)?J[0]:H;if(F in $.#Q){if($=$.#Q[F],J)Y.push(J[1]);continue}if($.#Q[F]=new A,J)$.#B.push(J),Y.push(J[1]);$=$.#Q[F]}return $.#A.push({[Q]:{handler:w,possibleKeys:Y.filter((I,X,H)=>H.indexOf(I)===X),score:this.#D}}),$}#w(Q,B,w,$,D){for(let Y=0,I=B.#A.length;Y<I;Y++){let X=B.#A[Y],H=X[w]||X[yB],W={};if(H!==void 0){if(H.params=Object.create(null),Q.push(H),$!==nk||D&&D!==nk)for(let J=0,F=H.possibleKeys.length;J<F;J++){let z=H.possibleKeys[J],V=W[H.score];H.params[z]=D?.[z]&&!V?D[z]:$[z]??D?.[z],W[H.score]=!0}}}}search(Q,B){let w=[];this.#$=nk;let D=[this],Y=HIA(B),I=[],X=Y.length,H=null;for(let W=0;W<X;W++){let J=Y[W],F=W===X-1,z=[];for(let E=0,L=D.length;E<L;E++){let k=D[E],_=k.#Q[J];if(_)if(_.#$=k.#$,F){if(_.#Q["*"])this.#w(w,_.#Q["*"],Q,k.#$);this.#w(w,_,Q,k.#$)}else z.push(_);for(let j=0,r=k.#B.length;j<r;j++){let n=k.#B[j],g=k.#$===nk?{}:{...k.#$};if(n==="*"){let c=k.#Q["*"];if(c)this.#w(w,c,Q,k.#$),c.#$=g,z.push(c);continue}let[T,S,h]=n;if(!J&&!(h instanceof RegExp))continue;let t=k.#Q[T];if(h instanceof RegExp){if(H===null){H=Array(X);let IA=B[0]==="/"?1:0;for(let P=0;P<X;P++)H[P]=IA,IA+=Y[P].length+1}let c=B.substring(H[W]),UA=h.exec(c);if(UA){if(g[S]=UA[0],this.#w(w,t,Q,k.#$,g),Qt1(t.#Q)){t.#$=g;let IA=UA[0].match(/\//)?.length??0;(I[IA]||=[]).push(t)}continue}}if(h===!0||h.test(J))if(g[S]=J,F){if(this.#w(w,t,Q,g,k.#$),t.#Q["*"])this.#w(w,t.#Q["*"],Q,g,k.#$)}else t.#$=g,z.push(t)}}let V=I.shift();D=V?z.concat(V):z}if(w.length>1)w.sort((W,J)=>{return W.score-J.score});return[w.map(({handler:W,params:J})=>[W,J])]}};var zIA=class{name="TrieRouter";#A;constructor(){this.#A=new oF0}add(A,Q,B){let w=gc(Q);if(w){for(let $=0,D=w.length;$<D;$++)this.#A.insert(A,w[$],B);return}this.#A.insert(A,Q,B)}match(A,Q){return this.#A.search(A,Q)}};var oL=class extends pF0{constructor(A={}){super(A);this.router=A.router??new ZIA({routers:[new lc,new zIA]})}};import{stat as Yt1}from"fs/promises";import{join as It1}from"path";var sL=/^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;var qIA=(A,Q=wt1)=>{let B=/\.([a-zA-Z0-9]+?)$/,w=A.match(B);if(!w)return;let $=Q[w[1]];if($&&$.startsWith("text"))$+="; charset=utf-8";return $};var Bt1={aac:"audio/aac",avi:"video/x-msvideo",avif:"image/avif",av1:"video/av1",bin:"application/octet-stream",bmp:"image/bmp",css:"text/css",csv:"text/csv",eot:"application/vnd.ms-fontobject",epub:"application/epub+zip",gif:"image/gif",gz:"application/gzip",htm:"text/html",html:"text/html",ico:"image/x-icon",ics:"text/calendar",jpeg:"image/jpeg",jpg:"image/jpeg",js:"text/javascript",json:"application/json",jsonld:"application/ld+json",map:"application/json",mid:"audio/x-midi",midi:"audio/x-midi",mjs:"text/javascript",mp3:"audio/mpeg",mp4:"video/mp4",mpeg:"video/mpeg",oga:"audio/ogg",ogv:"video/ogg",ogx:"application/ogg",opus:"audio/opus",otf:"font/otf",pdf:"application/pdf",png:"image/png",rtf:"application/rtf",svg:"image/svg+xml",tif:"image/tiff",tiff:"image/tiff",ts:"video/mp2t",ttf:"font/ttf",txt:"text/plain",wasm:"application/wasm",webm:"video/webm",weba:"audio/webm",webmanifest:"application/manifest+json",webp:"image/webp",woff:"font/woff",woff2:"font/woff2",xhtml:"application/xhtml+xml",xml:"application/xml",zip:"application/zip","3gp":"video/3gpp","3g2":"video/3gpp2",gltf:"model/gltf+json",glb:"model/gltf-binary"},wt1=Bt1;var sF0=(...A)=>{let Q=A.filter(($)=>$!=="").join("/");Q=Q.replace(/(?<=\/)\/+/g,"");let B=Q.split("/"),w=[];for(let $ of B)if($===".."&&w.length>0&&w.at(-1)!=="..")w.pop();else if($!==".")w.push($);return w.join("/")||"."};var aF0={br:".br",zstd:".zst",gzip:".gz"},$t1=Object.keys(aF0),Dt1="index.html",tF0=(A)=>{let Q=A.root??"./",B=A.path,w=A.join??sF0;return async($,D)=>{if($.finalized)return D();let Y;if(A.path)Y=A.path;else try{if(Y=KIA($.req.path),/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(Y))throw Error()}catch{return await A.onNotFound?.($.req.path,$),D()}let I=w(Q,!B&&A.rewriteRequestPath?A.rewriteRequestPath(Y):Y);if(A.isDir&&await A.isDir(I))I=w(I,Dt1);let X=A.getContent,H=await X(I,$);if(H instanceof Response)return $.newResponse(H.body,H);if(H){let W=A.mimes&&qIA(I,A.mimes)||qIA(I);if($.header("Content-Type",W||"application/octet-stream"),A.precompressed&&(!W||sL.test(W))){let J=new Set($.req.header("Accept-Encoding")?.split(",").map((F)=>F.trim()));for(let F of $t1){if(!J.has(F))continue;let z=await X(I+aF0[F],$);if(z){H=z,$.header("Content-Encoding",F),$.header("Vary","Accept-Encoding",{append:!0});break}}}return await A.onFound?.(I,$),$.body(H)}await A.onNotFound?.(I,$),await D();return}};var NIA=(A)=>{return async function(B,w){return tF0({...A,getContent:async(Y)=>{let I=Bun.file(Y);return await I.exists()?I:null},join:It1,isDir:async(Y)=>{let I;try{I=(await Yt1(Y)).isDirectory()}catch{}return I}})(B,w)}};var VIA="x-hono-disable-ssg",jxQ=(()=>{try{return new Response("SSG is disabled",{status:404,headers:{[VIA]:"true"}})}catch{return null}})();var{write:HTQ}=Bun;var Kt1=class{#A;constructor(A){this.#A=A,this.raw=A.raw,this.url=A.url?new URL(A.url):null,this.protocol=A.protocol??null}send(A,Q){this.#A.send(A,Q??{})}raw;binaryType="arraybuffer";get readyState(){return this.#A.readyState}url;protocol;close(A,Q){this.#A.close(A,Q)}};var eF0=(A)=>{return(...Q)=>{if(typeof Q[0]==="function"){let[B,w]=Q;return async function(D,Y){let I=await B(D),X=await A(D,I,w);if(X)return X;await Y()}}else{let[B,w,$]=Q;return(async()=>{let D=await A(B,w,$);if(!D)throw Error("Failed to upgrade WebSocket");return D})()}}};var pc=(A)=>("server"in A.env)?A.env.server:A.env;var Ut1=eF0((A,Q)=>{let B=pc(A);if(!B)throw TypeError("env has to include the 2nd argument of fetch.");if(B.upgrade(A.req.raw,{data:{events:Q,url:new URL(A.req.url),protocol:A.req.url}}))return new Response(null);return});var Wt1=["gzip","deflate"],Gt1=/(?:^|,)\s*?no-transform\s*?(?:,|$)/i,AZ0=(A)=>{let Q=A?.threshold??1024;return async function(w,$){await $();let D=w.res.headers.get("Content-Length");if(w.res.headers.has("Content-Encoding")||w.res.headers.has("Transfer-Encoding")||w.req.method==="HEAD"||D&&Number(D)<Q||!Jt1(w.res)||!Ft1(w.res))return;let Y=w.req.header("Accept-Encoding"),I=A?.encoding??Wt1.find((H)=>Y?.includes(H));if(!I||!w.res.body)return;let X=new CompressionStream(I);w.res=new Response(w.res.body.pipeThrough(X),w.res),w.res.headers.delete("Content-Length"),w.res.headers.set("Content-Encoding",I)}},Jt1=(A)=>{let Q=A.headers.get("Content-Type");return Q&&sL.test(Q)},Ft1=(A)=>{let Q=A.headers.get("Cache-Control");return!Q||!Gt1.test(Q)};import{Readable as QZ0}from"stream";import{createDeflate as Zt1,createGzip as zt1}from"zlib";var qt1=["gzip","deflate"],Nt1=/(?:^|,)\s*?no-transform\s*?(?:,|$)/i,BZ0=(A)=>{if(typeof CompressionStream<"u")return AZ0(A);let Q=A?.threshold??1024;return async function(w,$){await $();let D=w.res.headers.get("Content-Length");if(w.res.headers.has("Content-Encoding")||w.res.headers.has("Transfer-Encoding")||w.req.method==="HEAD"||D&&Number(D)<Q||!Vt1(w.res)||!Lt1(w.res))return;let Y=w.req.header("Accept-Encoding"),I=A?.encoding??qt1.find((X)=>Y?.includes(X));if(!I||!w.res.body)return;try{let X=I==="gzip"?zt1():Zt1(),H=w.res.body,J=QZ0.fromWeb(H).pipe(X),F=QZ0.toWeb(J);w.res=new Response(F,w.res),w.res.headers.delete("Content-Length"),w.res.headers.set("Content-Encoding",I)}catch(X){console.error("Compression error:",X)}}},Vt1=(A)=>{let Q=A.headers.get("Content-Type");return Q&&sL.test(Q)},Lt1=(A)=>{let Q=A.headers.get("Cache-Control");return!Q||!Nt1.test(Q)};var Mt1=(A,Q)=>{if(!A)return Q;let B=new Uint8Array(new ArrayBuffer(A.byteLength+Q.byteLength));return B.set(new Uint8Array(A),0),B.set(Q,A.byteLength),B},wZ0=async(A,Q)=>{if(!A)return null;let B=void 0,w=A.getReader();for(;;){let{value:$,done:D}=await w.read();if(D)break;B=await Q(Mt1(B,$))}if(!B)return null;return Array.prototype.map.call(new Uint8Array(B),($)=>$.toString(16).padStart(2,"0")).join("")};var Et1=["cache-control","content-location","date","etag","expires","vary"],$Z0=(A)=>A.replace(/^W\//,"");function Ct1(A,Q){return Q!=null&&Q.split(/,\s*/).some((B)=>$Z0(B)===$Z0(A))}function Ot1(A){if(!A){if(crypto&&crypto.subtle)A=(Q)=>crypto.subtle.digest({name:"SHA-1"},Q)}return A}var DZ0=(A)=>{let Q=A?.retainedHeaders??Et1,B=A?.weak??!1,w=Ot1(A?.generateDigest);return async function(D,Y){let I=D.req.header("If-None-Match")??null;await Y();let X=D.res,H=X.headers.get("ETag");if(!H){if(!w)return;let W=await wZ0(X.clone().body,w);if(W===null)return;H=B?`W/"${W}"`:`"${W}"`}if(Ct1(H,I))D.res=new Response(null,{status:304,statusText:"Not Modified",headers:{ETag:H}}),D.res.headers.forEach((W,J)=>{if(Q.indexOf(J.toLowerCase())===-1)D.res.headers.delete(J)});else D.res.headers.set("ETag",H)}};B0();function dc(A,Q){return async(B)=>{let w=B.req.raw,$=w.headers.get("content-type")??"",D=w.headers.get("accept")?.includes("application/json"),Y={};if($.includes("application/json"))Y=await w.json();else if($.includes("form")){let z=await w.formData();for(let[V,E]of z.entries())Y[V]=E}let I=`${A.pluginId}_${A.definition.tool}`,X=await Q.send(`plugin:${A.pluginId}:tool:execute`,{toolName:I,args:Y,interfaceType:"webserver",userId:"anonymous"},"webserver"),H=typeof X==="object"&&"data"in X?X.data:X,W=FO.safeParse(H),J=W.success?W.data:H,F=W.success&&W.data.success===!0;if(D)return B.json(J,F?200:400);if(F&&A.definition.successRedirect)return B.redirect(A.definition.successRedirect);if(!F&&A.definition.errorRedirect)return B.redirect(A.definition.errorRedirect);return B.json(J,F?200:400)}}var YZ0="public, max-age=31536000, immutable";class ic{logger;options;productionServer=null;isPreviewHost(A){if(!A)return!1;let Q=A.replace(/:\d+$/,"").toLowerCase();return/^(?:preview\..+|.+-preview\..+)$/.test(Q)}constructor(A){this.logger=A.logger,this.options={...A,productionDistDir:aL(process.cwd(),A.productionDistDir),sharedImagesDir:aL(process.cwd(),A.sharedImagesDir),...A.previewDistDir&&{previewDistDir:aL(process.cwd(),A.previewDistDir)}}}async start(){if(this.productionServer){this.logger.warn("Webserver already running");return}let A=this.createApp({distDir:this.options.productionDistDir,compress:!0,defaultCache:"public, max-age=3600",immutableExtensions:/\.(js|css|jpg|jpeg|png|gif|ico|woff|woff2)$/,healthEndpoint:!0}),Q=this.options.previewDistDir?this.createApp({distDir:this.options.previewDistDir,compress:!1,defaultCache:"no-cache",immutableExtensions:/\.(jpg|jpeg|png|gif|ico|webp|svg|woff|woff2)$/,healthEndpoint:!1}):void 0;try{this.productionServer=Bun.serve({port:this.options.productionPort,fetch:async(B)=>{let w=await this.serveImageFastPath(B);if(w)return w;if(Q&&this.isPreviewHost(B.headers.get("host")))return Q.fetch(B);return A.fetch(B)}})}catch(B){let w=String(B);if(w.includes("EADDRINUSE")||w.includes("address already in use"))throw Error(`Port ${this.options.productionPort} is already in use. Another brain may be running \u2014 stop it first or configure a different port.`);throw B}this.logger.info(`Production server listening on http://localhost:${this.productionServer.port}`)}async stop(){if(this.productionServer)await this.productionServer.stop(),this.productionServer=null;this.logger.debug("Webserver stopped")}getStatus(){return{running:this.productionServer!==null,productionUrl:this.productionServer?`http://localhost:${this.productionServer.port}`:void 0,previewUrl:this.productionServer&&this.options.previewDistDir?`http://localhost:${this.productionServer.port}`:void 0}}createApp(A){let Q=new oL;if(A.healthEndpoint)Q.get("/health",async(B)=>{if(this.options.getHealthData){let w=await this.options.getHealthData();return B.json({status:"healthy",...w},200)}return B.json({status:"healthy"},200)});if(Q.use("/*",async(B,w)=>{let $=await this.handleDynamicRoute(B,A);if($)return $;return w()}),A.compress)Q.use("/*",BZ0());return Q.use("/*",DZ0()),Q.use("/*",async(B,w)=>{if(await w(),A.immutableExtensions.test(B.req.path))B.header("Cache-Control",YZ0);else B.header("Cache-Control",A.defaultCache)}),Q.use("/*",this.createCleanUrlMiddleware(A.distDir)),Q.use("/*",NIA({root:A.distDir})),Q.notFound(async(B)=>{let w=Bun.file(ft1(A.distDir,"404.html"));if(await w.exists())return B.html(await w.text(),404);return B.text("Not Found",404)}),Q}getCurrentWebRoutes(){return this.options.getWebRoutes?.()??this.options.webRoutes??[]}getCurrentApiRoutes(){return this.options.getApiRoutes?.()??this.options.apiRoutes??[]}async handleDynamicRoute(A,Q){if(!Q.healthEndpoint)return null;let B=A.req.method.toUpperCase(),w=A.req.path,$=this.getCurrentWebRoutes().find((Y)=>{let I=Y.definition.method??"GET";return Y.fullPath===w&&I===B});if($)return $.definition.handler(A.req.raw);let D=this.getCurrentApiRoutes().find((Y)=>{let I=Y.definition.method??"POST";return Y.fullPath===w&&I===B});if(D&&this.options.messageBus)return dc(D,this.options.messageBus)(A);return null}async serveImageFastPath(A){let Q;try{Q=new URL(A.url)}catch{return null}if(!Q.pathname.startsWith("/images/"))return null;let B=Q.pathname.slice(8),w=aL(this.options.sharedImagesDir,B);if(!w.startsWith(this.options.sharedImagesDir))return null;let $=Bun.file(w);if(!await $.exists())return null;return new Response($,{headers:{"Cache-Control":YZ0}})}createCleanUrlMiddleware(A){return async(Q,B)=>{let w=Q.req.path;if(w.includes(".")||w==="/"){await B();return}let $=aL(A,`.${w}`,"index.html");if(!$.startsWith(A)){await B();return}let D=Bun.file($);if(await D.exists())return Q.html(await D.text());let Y=aL(A,`.${w}.html`);if(Y.startsWith(A)){let I=Bun.file(Y);if(await I.exists())return Q.html(await I.text())}await B()}}}import{existsSync as XZ0}from"fs";import{join as HZ0}from"path";GA();var LIA=Z.object({enablePreview:Z.boolean().default(!0).describe("Enable the preview site server when preview assets are configured"),previewDistDir:Z.string().default("./dist/site-preview").describe("Directory for preview site files"),productionDistDir:Z.string().describe("Directory for production site files").default("./dist/site-production"),sharedImagesDir:Z.string().default("./dist/images").describe("Shared directory for optimized images"),previewPort:Z.number().default(4321).describe("Port for preview server"),productionPort:Z.number().describe("Port for production server").default(8080),apiPort:Z.number().describe("Port for API route server (plugin HTTP endpoints)").default(3335)});var MIA=`<!DOCTYPE html>
|
|
1605
1606
|
<html lang="en">
|
|
@@ -1668,7 +1669,7 @@ ${A.entityContent}`,ZF1);X=w+k.imagePrompt}catch(k){this.logger.warn("AI prompt
|
|
|
1668
1669
|
<p>Once built, this page will be replaced with your actual website.</p>
|
|
1669
1670
|
</div>
|
|
1670
1671
|
</body>
|
|
1671
|
-
</html>`;var IZ0={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.
|
|
1672
|
+
</html>`;var IZ0={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.38",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/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/node":"^20.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};class _G extends yI{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",IZ0,A,LIA)}async onRegister(A){if(this.siteUrl=A.siteUrl,this.previewUrl=A.previewUrl,this.siteUrl)A.endpoints.register({label:"Site",url:this.siteUrl,priority:10});if(this.config.enablePreview&&this.previewUrl)A.endpoints.register({label:"Preview",url:this.previewUrl,priority:20});this.serverManager=new ic({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,B=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,w=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,$=[];if(Q){if($.push(`Production: ${B}`),A?.previewUrl)$.push(`Preview: ${w}`)}return{status:Q?"healthy":"error",message:Q?$.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?w:void 0,productionUrl:Q?B:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!XZ0(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(HZ0(this.config.previewDistDir,"index.html"),MIA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!XZ0(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(HZ0(this.config.productionDistDir,"index.html"),MIA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}B0();GA();var KZ0=Z.object({port:Z.number().default(3334),organization:Z.string().optional(),trustedTokens:Z.record(Z.string()).optional(),outboundTokens:Z.record(Z.string()).optional()});B0();function jt1(A,Q){return`${A.name} is ${Q.name}'s ${A.role}. Its purpose is: ${A.purpose}.`}function UZ0(A){let{character:Q,profile:B,version:w,domain:$,organization:D,tools:Y}=A,X=`${A.baseUrl??($?`https://${$}`:"http://localhost:8080")}/a2a`,H=A.skills&&A.skills.length>0?A.skills.map((F)=>({id:F.name.toLowerCase().replace(/\s+/g,"-"),name:F.name,description:F.description,tags:F.tags,examples:F.examples})):Y.map((F)=>({id:F.name,name:F.name,description:F.description,tags:[],examples:[]})),W={name:B.name};if(A.kind)W.kind=A.kind;if(B.description)W.description=B.description;if(D)W.organization=D;let J=[{uri:DS,description:"Anchor (operator) identity for this brain",params:W}];return{name:Q.name,description:jt1(Q,B),url:X,version:w,protocolVersion:"0.2.2",capabilities:{streaming:!0,pushNotifications:!1,extensions:J},skills:H,defaultInputModes:["text/plain"],defaultOutputModes:["text/plain"],...D&&{provider:{organization:D,url:X}},...A.authEnabled&&{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer"}},security:[{bearerAuth:[]}]}}}B0();var EIA=new Set(["completed","failed","canceled","rejected"]);class CIA{tasks=new Map;ttlMs;processingTimeoutMs;constructor(A=3600000,Q=300000){this.ttlMs=A,this.processingTimeoutMs=Q}evictExpired(){let A=Date.now();for(let[Q,B]of this.tasks)if(EIA.has(B.task.status.state)&&A-new Date(B.updatedAt).getTime()>=this.ttlMs)this.tasks.delete(Q)}createTask(A,Q){this.evictExpired();let B=crypto.randomUUID(),w=Q??crypto.randomUUID(),$=new Date().toISOString(),D={kind:"message",messageId:crypto.randomUUID(),role:"user",parts:[{kind:"text",text:A}],contextId:w,taskId:B},I={task:{id:B,contextId:w,kind:"task",status:{state:"submitted",timestamp:$},history:[D]},conversationId:`a2a:${B}`,createdAt:$,updatedAt:$};return this.tasks.set(B,I),I}getTask(A){return this.tasks.get(A)}updateState(A,Q,B){let w=this.tasks.get(A);if(!w)return;let $=new Date().toISOString();if(w.task.status={state:Q,timestamp:$},w.updatedAt=$,Q==="working")w.workingStartedAt=$;if(B){let D={kind:"message",messageId:crypto.randomUUID(),role:"agent",parts:[{kind:"text",text:B}],contextId:w.task.contextId,taskId:A};w.task.status.message=D,w.task.history??=[],w.task.history.push(D)}return w}addArtifact(A,Q,B){let w=this.tasks.get(A);if(!w)return;return w.task.artifacts??=[],w.task.artifacts.push({artifactId:crypto.randomUUID(),name:Q,parts:B}),w.updatedAt=new Date().toISOString(),w}getTaskWithHistory(A,Q){let B=this.tasks.get(A);if(!B)return;if(B.task.status.state==="working"&&B.workingStartedAt&&Date.now()-new Date(B.workingStartedAt).getTime()>=this.processingTimeoutMs)this.updateState(A,"failed","Processing timed out");if(Q===void 0||!B.task.history)return B.task;return{...B.task,history:B.task.history.slice(-Q)}}deleteTask(A){return this.tasks.delete(A)}get size(){return this.tasks.size}}GA();var WZ0=Z.array(Z.object({kind:Z.string(),text:Z.string().optional(),data:Z.record(Z.unknown()).optional()})),kt1=Z.object({message:Z.object({kind:Z.literal("message").optional(),messageId:Z.string().optional(),role:Z.enum(["user","agent"]).optional(),parts:WZ0,contextId:Z.string().optional(),taskId:Z.string().optional()}),configuration:Z.object({historyLength:Z.number().optional()}).optional()}),GZ0=Z.object({id:Z.string(),historyLength:Z.number().optional()});function OIA(A,Q){return{jsonrpc:"2.0",id:A,result:Q}}function qX(A,Q,B){return{jsonrpc:"2.0",id:A,error:{code:Q,message:B}}}var JZ0=Z.object({jsonrpc:Z.string(),id:Z.union([Z.string(),Z.number()]),method:Z.string(),params:Z.record(Z.unknown()).optional()});async function FZ0(A,Q){let{id:B,method:w,params:$}=A;switch(w){case"message/send":return Pt1(B,$??{},Q);case"tasks/get":return bt1(B,$??{},Q);case"tasks/cancel":return xt1(B,$??{},Q);default:return qX(B,-32601,`Method not found: ${w}`)}}async function Pt1(A,Q,B){let w=kt1.safeParse(Q);if(!w.success)return qX(A,-32602,`Invalid params: ${w.error.message}`);let $=w.data.message.parts.filter((W)=>W.kind==="text"&&typeof W.text==="string");if($.length===0)return qX(A,-32602,"Message must contain at least one text part");let D=$.map((W)=>W.text).join(`
|
|
1672
1673
|
`),Y=w.data.message.contextId,I=B.taskManager.createTask(D,Y),X=I.task.id;B.taskManager.updateState(X,"working"),_t1(X,D,I.conversationId,B);let H=B.taskManager.getTask(X);if(!H)return qX(A,-32603,"Internal error: task disappeared");return OIA(A,H.task)}function _t1(A,Q,B,w){w.agentService.chat(Q,B,{userPermissionLevel:w.callerPermissionLevel,interfaceType:"a2a"}).then(($)=>{w.taskManager.updateState(A,"completed",$.text)}).catch(($)=>{let D=$ instanceof Error?$.message:"Unknown error";w.taskManager.updateState(A,"failed",`Error: ${D}`)})}var ZZ0=Z.object({message:Z.object({kind:Z.string(),parts:WZ0,contextId:Z.string().optional()})});function zZ0(A,Q,B){let $=Q.parts.filter((H)=>H.kind==="text"&&typeof H.text==="string").map((H)=>H.text).join(`
|
|
1673
1674
|
`)||"No message text",D=B.taskManager.createTask($,Q.contextId),Y=D.task.id;B.taskManager.updateState(Y,"working");let I=new TextEncoder,X=new ReadableStream({start(H){let W=!1;function J(E){if(W)return;try{H.enqueue(I.encode(`data: ${JSON.stringify(E)}
|
|
1674
1675
|
|
|
@@ -1676,7 +1677,7 @@ ${A.entityContent}`,ZF1);X=w+k.imagePrompt}catch(k){this.logger.warn("AI prompt
|
|
|
1676
1677
|
|
|
1677
1678
|
`);w=D.pop()??"";for(let Y of D){let I=Y.split(`
|
|
1678
1679
|
`).find((E)=>E.startsWith("data: "));if(!I)continue;let H=JSON.parse(I.slice(6)).result;if(!H)continue;if(H.final!==!0)continue;Q.cancel().catch(()=>{});let J=H.status,F=J?.state??"unknown",V=(J?.message?.parts??[]).filter((E)=>E.kind==="text"&&typeof E.text==="string").map((E)=>E.text).join(`
|
|
1679
|
-
`)||"No response text";return{success:!0,data:{state:F,response:V}}}$=await Q.read()}return{success:!1,error:"Stream ended without a terminal event"}}function VZ0(A={}){let Q=A.fetch??globalThis.fetch;return{name:"a2a_call",description:"Call a saved remote A2A agent by its local directory id. Use only a saved agent id such as yeehaa.io. Never pass a display name like Brain, never pass a full URL, and do not use this tool to probe whether an agent exists. If the user gives a URL, an unsaved agent, or an ambiguous name, ask them to add/save or clarify the agent first.",inputSchema:qZ0,visibility:"anchor",handler:async(B)=>{let w=Z.object(qZ0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{agent:$,message:D}=w.data,Y=Tt1($);if(!Y)return{success:!1,error:"Invalid agent id. Use a saved agent id from your directory, not a URL."};if(!A.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let I=await A.entityService.getEntity("agent",Y);if(!I)return{success:!1,error:`Agent ${Y} is not in your directory. Add it first.`};if(I.metadata.status!=="approved")return{success:!1,error:`Agent ${Y} is discovered but not approved yet. Approve it first.`};let X=`https://${Y}`,H=await vt1(X,Q);if(!H)return{success:!1,error:`Could not fetch Agent Card from ${X}`};let W=H.url,J;if(A.outboundTokens)try{let F=new URL(W).hostname;J=A.outboundTokens[F]}catch{}return St1(W,D,Q,J)}}}var fIA={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.37",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 yt1={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","X-Content-Type-Options":"nosniff"};class tL extends yI{agentCard;unsubscribeReady;unsubscribeSyncCompleted;taskManager=new CIA;agentService;permissionContext;app;hasWebserver=!1;constructor(A={}){super("a2a",fIA,A,KZ0)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agentService,this.permissionContext=A.permissions,this.unsubscribeReady=A.messaging.subscribe("system:plugins:ready",()=>{return this.rebuildAgentCard(A),{noop:!0}}),this.unsubscribeSyncCompleted=A.messaging.subscribe("sync:initial:completed",()=>{return this.rebuildAgentCard(A),{success:!0}}),this.hasWebserver)this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async rebuildAgentCard(A){let Q=A.identity.get(),B=A.identity.getProfile(),w=A.tools.listForPermissionLevel("public"),$=this.config.trustedTokens&&Object.keys(this.config.trustedTokens).length>0,D;if(A.entityService.hasEntityType("skill"))try{let Y=await A.entityService.listEntities("skill");if(Y.length>0)D=Y.map((I)=>NN.safeParse(I.metadata)).filter((I)=>I.success).map((I)=>I.data)}catch{}this.agentCard=UZ0({character:Q,profile:B,version:fIA.version,domain:A.domain,organization:this.config.organization,tools:w,skills:D,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),B=this.config.trustedTokens[Q];if(!B||!this.permissionContext)return"public";return this.permissionContext.getUserLevel("a2a",B)}withCors(A){let Q=new Headers(A.headers);for(let[B,w]of Object.entries(yt1))Q.set(B,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new oL;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 B;try{B=await Q.req.json()}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let w=JZ0.safeParse(B);if(!w.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(w.data.method==="message/stream"){let Y=ZZ0.safeParse(w.data.params??{});if(!Y.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Y.error.message}`},id:w.data.id}));let{stream:I}=zZ0(w.data.id,Y.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(new Response(I,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let D=await FZ0(w.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(Q.json(D))}),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[VZ0({outboundTokens:this.config.outboundTokens,entityService:this.getContext().entityService})]}async getInstructions(){return"## Agent-to-agent calls\n- Use `a2a_call` only for agents already saved in the local `agent` directory.\n- Pass only the saved local agent id to `a2a_call` (for example `yeehaa.io`). Never pass a full URL or a display name like `Brain`.\n- If the user asks you to ask, message, or contact a saved approved agent, treat that as an agent-directory request first and call `a2a_call` in the same turn. Do not stop after listing the agent, drafting the question, or searching general content locally.\n- If the user gives a full URL for an agent, do not pass that URL to `a2a_call`. Use a saved local agent id only. If that URL is not already saved in the local directory, tell the user to add it first.\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 short clarification question and do not call any agent yet.\n- After asking that clarification question, end the turn. Do not call `a2a_call` later in the same turn.\n- If the target agent is not in the directory, do not create a wish, reminder, todo, note, fallback task, or any new entity. Tell the user to add it first.\n- In these invalid agent-target cases, do not call any tool unless the user explicitly asks you to add/save the agent.\n- Only use creation tools for an agent if the user explicitly asks you to add or save that agent.\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.unsubscribeReady?.(),this.unsubscribeSyncCompleted?.(),this.logger.info("A2A server stopped")}}}}B0();B0();class RIA{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}prepareBatchOperations(A,Q){if(A.length===0)return{operations:[],exportOperationsCount:0,importOperationsCount:0,totalFiles:0};let B=[],w=this.createImportOperations(A);B.push(...w);let $=w.length;if(Q?.includeCleanup)B.push({type:"directory-cleanup",data:{}});let D=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:$,totalFiles:D}),{operations:B,exportOperationsCount:0,importOperationsCount:$,totalFiles:D}}async queueSyncBatch(A,Q,B,w,$){let D=this.prepareBatchOperations(B,$);if(D.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch(D.operations,{source:Q,rootJobId:w?.rootJobId??j6(),metadata:{progressToken:w?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:w?.pluginId??"directory-sync",interfaceType:w?.interfaceType,channelId:w?.channelId}}),operationCount:D.operations.length,exportOperationsCount:D.exportOperationsCount,importOperationsCount:D.importOperationsCount,totalFiles:D.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,B=[];for(let w=0;w<A.length;w+=Q){let $=A.slice(w,w+Q);B.push({type:"directory-import",data:{batchIndex:Math.floor(w/Q),paths:$,batchSize:$.length}})}return B}}GA();import{resolve as t22,isAbsolute as e22}from"path";import{mkdir as AQ2}from"fs/promises";var mq0=o0(vq0(),1);aD();import{join as NX,dirname as h22,extname as Gl}from"path";import{mkdir as fXA,readFile as Wl,writeFile as Sq0,readdir as g22,stat as hq0,utimes as y22,access as m22}from"fs/promises";var XP=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function gq0(A){let Q=Gl(A).toLowerCase();return XP.includes(Q)}function u22(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 yq0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}async function DM(A){try{return await m22(A),!0}catch{return!1}}class RXA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){let w=(A.startsWith(this.syncPath)?A:NX(this.syncPath,A)).replace(this.syncPath+"/","").split("/"),$,D;if(w.length===1)$="base",D=w;else if(w.length>1&&w[0])$=w[0],D=w.slice(1);else $="base",D=w;let Y;if(D.length>1){let I=D[D.length-1];if(I){let X=Gl(I).toLowerCase(),H=X===".md"||XP.includes(X)?I.slice(0,-X.length):I;D[D.length-1]=H}Y=D.join(":")}else{let I=D[0]??"",X=Gl(I).toLowerCase();Y=X===".md"||XP.includes(X)?I.slice(0,-X.length):I}return{entityType:$,id:Y}}async readEntity(A){let Q=A.startsWith(this.syncPath)?A:NX(this.syncPath,A),B=await hq0(Q),{entityType:w,id:$}=this.parseEntityFromPath(A),D=B.birthtime.getTime()>0?B.birthtime:B.mtime,Y=B.mtime,I;if(gq0(A)){let H=(await Wl(Q)).toString("base64"),W=Gl(A);I=`data:${u22(W)};base64,${H}`}else I=await Wl(Q,"utf-8");return{entityType:w,id:$,content:I,created:D,updated:Y}}async writeEntity(A){let Q=this.getEntityFilePath(A),B=A.entityType==="image",w;if(B){let D=A.content.match(/^data:image\/[a-z+]+;base64,(.+)$/i);w=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64")}else w=this.entityService.serializeEntity(A);if(await DM(Q)){let D=B?await Wl(Q):await Wl(Q,"utf-8"),Y=aB(B?D.toString("base64"):D),I=aB(B?w.toString("base64"):w);if(Y===I)return}if(A.entityType!=="base")await fXA(h22(Q),{recursive:!0});if(B)await Sq0(Q,w);else await Sq0(Q,w,"utf-8");let $=new Date(A.updated);await y22(Q,$,$)}getFilePath(A,Q,B=".md"){let w=A.split(":").filter((X)=>X.length>0),$=Q==="base";if(w.length===1)return $?NX(this.syncPath,`${w[0]}${B}`):NX(this.syncPath,Q,`${w[0]}${B}`);let D=w;if(w[0]===Q)D=w.slice(1);let Y=D[D.length-1],I=D.slice(0,-1);if($)return NX(this.syncPath,...I,`${Y}${B}`);else return NX(this.syncPath,Q,...I,`${Y}${B}`)}getEntityFilePath(A){let Q=".md";if(A.entityType==="image"){let B=A.metadata.format;if(B)Q=yq0(B);else{let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);if(w?.[1])Q=yq0(w[1])}}return this.getFilePath(A.id,A.entityType,Q)}async getAllMarkdownFiles(){return this.findFiles({includeImages:!1})}async getAllSyncFiles(){return this.findFiles({includeImages:!0})}async findFiles(A){let Q=[];if(!await DM(this.syncPath))return Q;let B=async(w,$="",D=!1)=>{let Y=await g22(w,{withFileTypes:!0});for(let I of Y){let X=$?NX($,I.name):I.name;if(I.isFile()&&!I.name.endsWith(".invalid")){if(I.name.endsWith(".md"))Q.push(X);else if(A.includeImages&&D&&gq0(I.name))Q.push(X)}else if(I.isDirectory()&&!I.name.startsWith(".")){if($===""&&!this.entityService.hasEntityType(I.name))continue;let H=NX(w,I.name),W=I.name==="image"&&$==="";await B(H,X,D||W)}}};return await B(this.syncPath),Q}async ensureDirectoryStructure(A){if(!await DM(this.syncPath))await fXA(this.syncPath,{recursive:!0});for(let Q of A)if(Q!=="base")await fXA(NX(this.syncPath,Q),{recursive:!0})}shouldUpdateEntity(A,Q){let B=aB(Q.content);return A.contentHash!==B}async gatherFileStatus(){let A=[],Q={totalFiles:0,byEntityType:{}};if(!await DM(this.syncPath))return{files:A,stats:Q};let B=await this.getAllMarkdownFiles();for(let w of B)try{let $=NX(this.syncPath,w),D=await hq0($),{entityType:Y}=this.parseEntityFromPath(w);A.push({path:w,entityType:Y,modified:D.mtime}),Q.totalFiles++,Q.byEntityType[Y]=(Q.byEntityType[Y]??0)+1}catch{continue}return{files:A,stats:Q}}async syncDirectoryExists(){return DM(this.syncPath)}async fileExists(A){return DM(A)}}function c22(A,Q){if(!A.replace(Q+"/","").startsWith("image/"))return!1;return XP.some((w)=>A.toLowerCase().endsWith(w))}function l22(A,Q){if(A.replace(Q+"/","").split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return c22(A,Q)}class jXA{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=mq0.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(!l22(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let B=Q.replace(this.syncPath+"/","");if(this.pendingChanges.set(B,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,B]of A){let w=`${this.syncPath}/${Q}`;try{if(this.onFileChange)await this.onFileChange(B,w)}catch($){this.logger.error("Error processing file change",{path:Q,event:B,error:$})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}class kXA{logger;entityService;fileOperations;constructor(A,Q,B){this.logger=A,this.entityService=Q,this.fileOperations=B}async importEntitiesWithProgress(A,Q,B,w){this.logger.debug("Importing entities with progress reporting");let $={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},D=A??await this.fileOperations.getAllMarkdownFiles(),Y=D.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let I=0;I<Y;I+=B){let X=D.slice(I,I+B),H=await w(X);$.imported+=H.imported,$.skipped+=H.skipped,$.failed+=H.failed,$.errors.push(...H.errors),$.jobIds.push(...H.jobIds);let W=Math.min(I+B,Y),J=Math.round(W/Y*40);await Q.report({progress:J,message:`Imported ${W}/${Y} files`})}return $}async exportEntitiesWithProgress(A,Q,B){this.logger.debug("Exporting entities with progress reporting");let w=A??this.entityService.getEntityTypes(),$={exported:0,failed:0,errors:[]},D=w.length;await Q.report({progress:50,message:`Starting export of ${D} entity types`});for(let Y=0;Y<D;Y++){let I=w[Y];if(!I)continue;let X=await this.entityService.listEntities(I,{limit:1000});for(let H=0;H<X.length;H+=B){let W=X.slice(H,H+B);for(let z of W)try{await this.fileOperations.writeEntity(z),$.exported++,this.logger.debug("Exported entity",{entityType:I,id:z.id})}catch(V){let E=V instanceof Error?V:Error(`Failed to export entity ${z.id||"unknown"}`);$.failed++,$.errors.push({entityId:z.id||"unknown",entityType:I,error:E.message}),this.logger.error("Failed to export entity",{entityType:I,id:z.id||"unknown",error:E})}let J=(Y+1)/D,F=50+Math.round(J*50);await Q.report({progress:F,message:`Exported ${$.exported} entities`})}}return this.logger.debug("Export completed",$),$}}class PXA{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,B,w,$=!0){if(this.logger=A,this.fileOperations=w,this.deleteOnFileRemoval=$,B)this.handleImport=async(D)=>{let Y=await B({type:"directory-import",data:{paths:[D]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:D})},this.handleDelete=async(D)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:D});return}try{let{entityType:Y,id:I}=this.fileOperations.parseEntityFromPath(D),X=await B({type:"directory-delete",data:{entityId:I,entityType:Y,filePath:D}});this.logger.info("Queued delete job for removed file",{jobId:X,path:D,entityId:I,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:D,error:Y})}};else this.handleImport=async(D)=>{await Q([D])},this.handleDelete=async(D)=>{this.logger.warn("File deleted but no job queue available",{path:D})}}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(B){this.logger.error("Failed to handle file change",{event:A,path:Q,error:B})}}}GA();async function Jl(A,Q,B,w){let{sourceUrl:$}=A,D=await Q.listEntities("image",{filter:{metadata:{sourceUrl:$}},limit:1});if(D[0])return w.debug("Reusing existing image entity",{sourceUrl:$,imageId:D[0].id}),D[0].id;let Y=await B($),{base64:I}=iW(Y),X=CF(I),H=rW(I);if(!X||!H)throw Error("Could not detect image format or dimensions");let W=await Q.createEntity({id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:X,width:H.width,height:H.height,sourceUrl:$}});return w.debug("Created image entity from URL",{sourceUrl:$,imageId:W.entityId}),W.entityId}var uq0=Z.object({title:Z.string(),slug:Z.string().optional(),coverImageUrl:Z.string().url(),coverImageId:Z.string().optional(),coverImageAlt:Z.string().optional()});class _XA{entityService;fetcher;logger;constructor(A,Q,B=R7){this.entityService=A;this.fetcher=B;this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=uD(A)}catch{return null}let{frontmatter:B}=Q,w=uq0.safeParse(B);if(!w.success)return null;if(w.data.coverImageId)return null;let{title:$,slug:D,coverImageUrl:Y,coverImageAlt:I}=w.data;if(!hH(Y))return null;return{sourceUrl:Y,postTitle:$,postSlug:D??e1($),customAlt:I}}async convert(A){let Q;try{Q=uD(A)}catch(H){return this.logger.debug("Parse failed",{error:H}),{content:A,converted:!1}}let{frontmatter:B}=Q,w=uq0.safeParse(B);if(!w.success)return{content:A,converted:!1};if(w.data.coverImageId)return{content:A,converted:!1};let{title:$,slug:D,coverImageUrl:Y,coverImageAlt:I}=w.data;if(!hH(Y))return{content:A,converted:!1};let X={postTitle:$,postSlug:D??e1($),sourceUrl:Y,customAlt:I};try{let H=await this.createImageEntity(X),W={...B};return delete W.coverImageUrl,delete W.coverImageAlt,W.coverImageId=H,{content:C3(W,Q.content),converted:!0,imageId:H}}catch(H){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:L0(H)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:B,sourceUrl:w,customAlt:$}=A,D=`Cover image for ${Q}`;return Jl({id:`${B}-cover`,title:D,alt:$??D,sourceUrl:w},this.entityService,this.fetcher,this.logger)}}GA();class HP{entityService;fetcher;logger;constructor(A,Q,B=R7){this.entityService=A;this.fetcher=B;this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let B=[],w=dT(A);for(let $ of w){if(!hH($.url))continue;if($.url.startsWith("entity://"))continue;let D=this.reconstructMarkdown($);B.push({sourceUrl:$.url,alt:$.alt,originalMarkdown:D,postSlug:Q})}return B}reconstructMarkdown(A){if(A.title)return``;return``}async convert(A,Q){let B=this.detectInlineImages(A,Q);if(B.length===0)return{content:A,converted:!1,convertedCount:0};let w=A,$=0,D=0;for(let Y of B)try{let I=await this.createImageEntity(Y,D++),X=``;w=w.replace(Y.originalMarkdown,X),$++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:I})}catch(I){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:L0(I)})}return{content:w,converted:$>0,convertedCount:$}}async createImageEntity(A,Q){let{sourceUrl:B,alt:w,postSlug:$}=A;return Jl({id:`${$}-inline-${Q}`,title:w||`Inline image ${Q+1} for ${$}`,alt:w||"",sourceUrl:B},this.entityService,this.fetcher,this.logger)}}GA();import{rename as p22,appendFile as d22,readFile as i22,writeFile as r22,access as n22}from"fs/promises";import{join as cq0}from"path";class bXA{logger;syncPath;constructor(A,Q){this.logger=A;this.syncPath=Q}isValidationError(A){if(A instanceof Z.ZodError)return!0;let Q=L0(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,B,w){let $=w(A),D=`${$}.invalid`;try{await p22($,D),B.quarantined++,B.quarantinedFiles.push(A);let Y=cq0(this.syncPath,".import-errors.log"),I=new Date().toISOString(),X=L0(Q),H=`${I} - ${A}: ${X}
|
|
1680
|
+
`)||"No response text";return{success:!0,data:{state:F,response:V}}}$=await Q.read()}return{success:!1,error:"Stream ended without a terminal event"}}function VZ0(A={}){let Q=A.fetch??globalThis.fetch;return{name:"a2a_call",description:"Call a saved remote A2A agent by its local directory id. Use only a saved agent id such as yeehaa.io. Never pass a display name like Brain, never pass a full URL, and do not use this tool to probe whether an agent exists. If the user gives a URL, an unsaved agent, or an ambiguous name, ask them to add/save or clarify the agent first.",inputSchema:qZ0,visibility:"anchor",handler:async(B)=>{let w=Z.object(qZ0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{agent:$,message:D}=w.data,Y=Tt1($);if(!Y)return{success:!1,error:"Invalid agent id. Use a saved agent id from your directory, not a URL."};if(!A.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let I=await A.entityService.getEntity("agent",Y);if(!I)return{success:!1,error:`Agent ${Y} is not in your directory. Add it first.`};if(I.metadata.status!=="approved")return{success:!1,error:`Agent ${Y} is discovered but not approved yet. Approve it first.`};let X=`https://${Y}`,H=await vt1(X,Q);if(!H)return{success:!1,error:`Could not fetch Agent Card from ${X}`};let W=H.url,J;if(A.outboundTokens)try{let F=new URL(W).hostname;J=A.outboundTokens[F]}catch{}return St1(W,D,Q,J)}}}var fIA={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.38",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 yt1={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","X-Content-Type-Options":"nosniff"};class tL extends yI{agentCard;unsubscribeReady;unsubscribeSyncCompleted;taskManager=new CIA;agentService;permissionContext;app;hasWebserver=!1;constructor(A={}){super("a2a",fIA,A,KZ0)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agentService,this.permissionContext=A.permissions,this.unsubscribeReady=A.messaging.subscribe("system:plugins:ready",()=>{return this.rebuildAgentCard(A),{noop:!0}}),this.unsubscribeSyncCompleted=A.messaging.subscribe("sync:initial:completed",()=>{return this.rebuildAgentCard(A),{success:!0}}),this.hasWebserver)this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async rebuildAgentCard(A){let Q=A.identity.get(),B=A.identity.getProfile(),w=A.tools.listForPermissionLevel("public"),$=this.config.trustedTokens&&Object.keys(this.config.trustedTokens).length>0,D;if(A.entityService.hasEntityType("skill"))try{let Y=await A.entityService.listEntities("skill");if(Y.length>0)D=Y.map((I)=>NN.safeParse(I.metadata)).filter((I)=>I.success).map((I)=>I.data)}catch{}this.agentCard=UZ0({character:Q,profile:B,version:fIA.version,domain:A.domain,organization:this.config.organization,tools:w,skills:D,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),B=this.config.trustedTokens[Q];if(!B||!this.permissionContext)return"public";return this.permissionContext.getUserLevel("a2a",B)}withCors(A){let Q=new Headers(A.headers);for(let[B,w]of Object.entries(yt1))Q.set(B,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new oL;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 B;try{B=await Q.req.json()}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let w=JZ0.safeParse(B);if(!w.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(w.data.method==="message/stream"){let Y=ZZ0.safeParse(w.data.params??{});if(!Y.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Y.error.message}`},id:w.data.id}));let{stream:I}=zZ0(w.data.id,Y.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(new Response(I,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let D=await FZ0(w.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$});return this.withCors(Q.json(D))}),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[VZ0({outboundTokens:this.config.outboundTokens,entityService:this.getContext().entityService})]}async getInstructions(){return"## Agent-to-agent calls\n- Use `a2a_call` only for agents already saved in the local `agent` directory.\n- Pass only the saved local agent id to `a2a_call` (for example `yeehaa.io`). Never pass a full URL or a display name like `Brain`.\n- If the user asks you to ask, message, or contact a saved approved agent, treat that as an agent-directory request first and call `a2a_call` in the same turn. Do not stop after listing the agent, drafting the question, or searching general content locally.\n- If the user gives a full URL for an agent, do not pass that URL to `a2a_call`. Use a saved local agent id only. If that URL is not already saved in the local directory, tell the user to add it first.\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 short clarification question and do not call any agent yet.\n- After asking that clarification question, end the turn. Do not call `a2a_call` later in the same turn.\n- If the target agent is not in the directory, do not create a wish, reminder, todo, note, fallback task, or any new entity. Tell the user to add it first.\n- In these invalid agent-target cases, do not call any tool unless the user explicitly asks you to add/save the agent.\n- Only use creation tools for an agent if the user explicitly asks you to add or save that agent.\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.unsubscribeReady?.(),this.unsubscribeSyncCompleted?.(),this.logger.info("A2A server stopped")}}}}B0();B0();class RIA{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}prepareBatchOperations(A,Q){if(A.length===0)return{operations:[],exportOperationsCount:0,importOperationsCount:0,totalFiles:0};let B=[],w=this.createImportOperations(A);B.push(...w);let $=w.length;if(Q?.includeCleanup)B.push({type:"directory-cleanup",data:{}});let D=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:$,totalFiles:D}),{operations:B,exportOperationsCount:0,importOperationsCount:$,totalFiles:D}}async queueSyncBatch(A,Q,B,w,$){let D=this.prepareBatchOperations(B,$);if(D.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch(D.operations,{source:Q,rootJobId:w?.rootJobId??j6(),metadata:{progressToken:w?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:w?.pluginId??"directory-sync",interfaceType:w?.interfaceType,channelId:w?.channelId}}),operationCount:D.operations.length,exportOperationsCount:D.exportOperationsCount,importOperationsCount:D.importOperationsCount,totalFiles:D.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,B=[];for(let w=0;w<A.length;w+=Q){let $=A.slice(w,w+Q);B.push({type:"directory-import",data:{batchIndex:Math.floor(w/Q),paths:$,batchSize:$.length}})}return B}}GA();import{resolve as t22,isAbsolute as e22}from"path";import{mkdir as AQ2}from"fs/promises";var mq0=o0(vq0(),1);aD();import{join as NX,dirname as h22,extname as Gl}from"path";import{mkdir as fXA,readFile as Wl,writeFile as Sq0,readdir as g22,stat as hq0,utimes as y22,access as m22}from"fs/promises";var XP=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function gq0(A){let Q=Gl(A).toLowerCase();return XP.includes(Q)}function u22(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 yq0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}async function DM(A){try{return await m22(A),!0}catch{return!1}}class RXA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){let w=(A.startsWith(this.syncPath)?A:NX(this.syncPath,A)).replace(this.syncPath+"/","").split("/"),$,D;if(w.length===1)$="base",D=w;else if(w.length>1&&w[0])$=w[0],D=w.slice(1);else $="base",D=w;let Y;if(D.length>1){let I=D[D.length-1];if(I){let X=Gl(I).toLowerCase(),H=X===".md"||XP.includes(X)?I.slice(0,-X.length):I;D[D.length-1]=H}Y=D.join(":")}else{let I=D[0]??"",X=Gl(I).toLowerCase();Y=X===".md"||XP.includes(X)?I.slice(0,-X.length):I}return{entityType:$,id:Y}}async readEntity(A){let Q=A.startsWith(this.syncPath)?A:NX(this.syncPath,A),B=await hq0(Q),{entityType:w,id:$}=this.parseEntityFromPath(A),D=B.birthtime.getTime()>0?B.birthtime:B.mtime,Y=B.mtime,I;if(gq0(A)){let H=(await Wl(Q)).toString("base64"),W=Gl(A);I=`data:${u22(W)};base64,${H}`}else I=await Wl(Q,"utf-8");return{entityType:w,id:$,content:I,created:D,updated:Y}}async writeEntity(A){let Q=this.getEntityFilePath(A),B=A.entityType==="image",w;if(B){let D=A.content.match(/^data:image\/[a-z+]+;base64,(.+)$/i);w=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64")}else w=this.entityService.serializeEntity(A);if(await DM(Q)){let D=B?await Wl(Q):await Wl(Q,"utf-8"),Y=aB(B?D.toString("base64"):D),I=aB(B?w.toString("base64"):w);if(Y===I)return}if(A.entityType!=="base")await fXA(h22(Q),{recursive:!0});if(B)await Sq0(Q,w);else await Sq0(Q,w,"utf-8");let $=new Date(A.updated);await y22(Q,$,$)}getFilePath(A,Q,B=".md"){let w=A.split(":").filter((X)=>X.length>0),$=Q==="base";if(w.length===1)return $?NX(this.syncPath,`${w[0]}${B}`):NX(this.syncPath,Q,`${w[0]}${B}`);let D=w;if(w[0]===Q)D=w.slice(1);let Y=D[D.length-1],I=D.slice(0,-1);if($)return NX(this.syncPath,...I,`${Y}${B}`);else return NX(this.syncPath,Q,...I,`${Y}${B}`)}getEntityFilePath(A){let Q=".md";if(A.entityType==="image"){let B=A.metadata.format;if(B)Q=yq0(B);else{let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);if(w?.[1])Q=yq0(w[1])}}return this.getFilePath(A.id,A.entityType,Q)}async getAllMarkdownFiles(){return this.findFiles({includeImages:!1})}async getAllSyncFiles(){return this.findFiles({includeImages:!0})}async findFiles(A){let Q=[];if(!await DM(this.syncPath))return Q;let B=async(w,$="",D=!1)=>{let Y=await g22(w,{withFileTypes:!0});for(let I of Y){let X=$?NX($,I.name):I.name;if(I.isFile()&&!I.name.endsWith(".invalid")){if(I.name.endsWith(".md"))Q.push(X);else if(A.includeImages&&D&&gq0(I.name))Q.push(X)}else if(I.isDirectory()&&!I.name.startsWith(".")){if($===""&&!this.entityService.hasEntityType(I.name))continue;let H=NX(w,I.name),W=I.name==="image"&&$==="";await B(H,X,D||W)}}};return await B(this.syncPath),Q}async ensureDirectoryStructure(A){if(!await DM(this.syncPath))await fXA(this.syncPath,{recursive:!0});for(let Q of A)if(Q!=="base")await fXA(NX(this.syncPath,Q),{recursive:!0})}shouldUpdateEntity(A,Q){let B=aB(Q.content);return A.contentHash!==B}async gatherFileStatus(){let A=[],Q={totalFiles:0,byEntityType:{}};if(!await DM(this.syncPath))return{files:A,stats:Q};let B=await this.getAllMarkdownFiles();for(let w of B)try{let $=NX(this.syncPath,w),D=await hq0($),{entityType:Y}=this.parseEntityFromPath(w);A.push({path:w,entityType:Y,modified:D.mtime}),Q.totalFiles++,Q.byEntityType[Y]=(Q.byEntityType[Y]??0)+1}catch{continue}return{files:A,stats:Q}}async syncDirectoryExists(){return DM(this.syncPath)}async fileExists(A){return DM(A)}}function c22(A,Q){if(!A.replace(Q+"/","").startsWith("image/"))return!1;return XP.some((w)=>A.toLowerCase().endsWith(w))}function l22(A,Q){if(A.replace(Q+"/","").split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return c22(A,Q)}class jXA{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=mq0.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(!l22(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let B=Q.replace(this.syncPath+"/","");if(this.pendingChanges.set(B,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,B]of A){let w=`${this.syncPath}/${Q}`;try{if(this.onFileChange)await this.onFileChange(B,w)}catch($){this.logger.error("Error processing file change",{path:Q,event:B,error:$})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}class kXA{logger;entityService;fileOperations;constructor(A,Q,B){this.logger=A,this.entityService=Q,this.fileOperations=B}async importEntitiesWithProgress(A,Q,B,w){this.logger.debug("Importing entities with progress reporting");let $={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},D=A??await this.fileOperations.getAllMarkdownFiles(),Y=D.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let I=0;I<Y;I+=B){let X=D.slice(I,I+B),H=await w(X);$.imported+=H.imported,$.skipped+=H.skipped,$.failed+=H.failed,$.errors.push(...H.errors),$.jobIds.push(...H.jobIds);let W=Math.min(I+B,Y),J=Math.round(W/Y*40);await Q.report({progress:J,message:`Imported ${W}/${Y} files`})}return $}async exportEntitiesWithProgress(A,Q,B){this.logger.debug("Exporting entities with progress reporting");let w=A??this.entityService.getEntityTypes(),$={exported:0,failed:0,errors:[]},D=w.length;await Q.report({progress:50,message:`Starting export of ${D} entity types`});for(let Y=0;Y<D;Y++){let I=w[Y];if(!I)continue;let X=await this.entityService.listEntities(I,{limit:1000});for(let H=0;H<X.length;H+=B){let W=X.slice(H,H+B);for(let z of W)try{await this.fileOperations.writeEntity(z),$.exported++,this.logger.debug("Exported entity",{entityType:I,id:z.id})}catch(V){let E=V instanceof Error?V:Error(`Failed to export entity ${z.id||"unknown"}`);$.failed++,$.errors.push({entityId:z.id||"unknown",entityType:I,error:E.message}),this.logger.error("Failed to export entity",{entityType:I,id:z.id||"unknown",error:E})}let J=(Y+1)/D,F=50+Math.round(J*50);await Q.report({progress:F,message:`Exported ${$.exported} entities`})}}return this.logger.debug("Export completed",$),$}}class PXA{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,B,w,$=!0){if(this.logger=A,this.fileOperations=w,this.deleteOnFileRemoval=$,B)this.handleImport=async(D)=>{let Y=await B({type:"directory-import",data:{paths:[D]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:D})},this.handleDelete=async(D)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:D});return}try{let{entityType:Y,id:I}=this.fileOperations.parseEntityFromPath(D),X=await B({type:"directory-delete",data:{entityId:I,entityType:Y,filePath:D}});this.logger.info("Queued delete job for removed file",{jobId:X,path:D,entityId:I,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:D,error:Y})}};else this.handleImport=async(D)=>{await Q([D])},this.handleDelete=async(D)=>{this.logger.warn("File deleted but no job queue available",{path:D})}}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(B){this.logger.error("Failed to handle file change",{event:A,path:Q,error:B})}}}GA();async function Jl(A,Q,B,w){let{sourceUrl:$}=A,D=await Q.listEntities("image",{filter:{metadata:{sourceUrl:$}},limit:1});if(D[0])return w.debug("Reusing existing image entity",{sourceUrl:$,imageId:D[0].id}),D[0].id;let Y=await B($),{base64:I}=iW(Y),X=CF(I),H=rW(I);if(!X||!H)throw Error("Could not detect image format or dimensions");let W=await Q.createEntity({id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:X,width:H.width,height:H.height,sourceUrl:$}});return w.debug("Created image entity from URL",{sourceUrl:$,imageId:W.entityId}),W.entityId}var uq0=Z.object({title:Z.string(),slug:Z.string().optional(),coverImageUrl:Z.string().url(),coverImageId:Z.string().optional(),coverImageAlt:Z.string().optional()});class _XA{entityService;fetcher;logger;constructor(A,Q,B=R7){this.entityService=A;this.fetcher=B;this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=uD(A)}catch{return null}let{frontmatter:B}=Q,w=uq0.safeParse(B);if(!w.success)return null;if(w.data.coverImageId)return null;let{title:$,slug:D,coverImageUrl:Y,coverImageAlt:I}=w.data;if(!hH(Y))return null;return{sourceUrl:Y,postTitle:$,postSlug:D??e1($),customAlt:I}}async convert(A){let Q;try{Q=uD(A)}catch(H){return this.logger.debug("Parse failed",{error:H}),{content:A,converted:!1}}let{frontmatter:B}=Q,w=uq0.safeParse(B);if(!w.success)return{content:A,converted:!1};if(w.data.coverImageId)return{content:A,converted:!1};let{title:$,slug:D,coverImageUrl:Y,coverImageAlt:I}=w.data;if(!hH(Y))return{content:A,converted:!1};let X={postTitle:$,postSlug:D??e1($),sourceUrl:Y,customAlt:I};try{let H=await this.createImageEntity(X),W={...B};return delete W.coverImageUrl,delete W.coverImageAlt,W.coverImageId=H,{content:C3(W,Q.content),converted:!0,imageId:H}}catch(H){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:L0(H)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:B,sourceUrl:w,customAlt:$}=A,D=`Cover image for ${Q}`;return Jl({id:`${B}-cover`,title:D,alt:$??D,sourceUrl:w},this.entityService,this.fetcher,this.logger)}}GA();class HP{entityService;fetcher;logger;constructor(A,Q,B=R7){this.entityService=A;this.fetcher=B;this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let B=[],w=dT(A);for(let $ of w){if(!hH($.url))continue;if($.url.startsWith("entity://"))continue;let D=this.reconstructMarkdown($);B.push({sourceUrl:$.url,alt:$.alt,originalMarkdown:D,postSlug:Q})}return B}reconstructMarkdown(A){if(A.title)return``;return``}async convert(A,Q){let B=this.detectInlineImages(A,Q);if(B.length===0)return{content:A,converted:!1,convertedCount:0};let w=A,$=0,D=0;for(let Y of B)try{let I=await this.createImageEntity(Y,D++),X=``;w=w.replace(Y.originalMarkdown,X),$++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:I})}catch(I){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:L0(I)})}return{content:w,converted:$>0,convertedCount:$}}async createImageEntity(A,Q){let{sourceUrl:B,alt:w,postSlug:$}=A;return Jl({id:`${$}-inline-${Q}`,title:w||`Inline image ${Q+1} for ${$}`,alt:w||"",sourceUrl:B},this.entityService,this.fetcher,this.logger)}}GA();import{rename as p22,appendFile as d22,readFile as i22,writeFile as r22,access as n22}from"fs/promises";import{join as cq0}from"path";class bXA{logger;syncPath;constructor(A,Q){this.logger=A;this.syncPath=Q}isValidationError(A){if(A instanceof Z.ZodError)return!0;let Q=L0(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,B,w){let $=w(A),D=`${$}.invalid`;try{await p22($,D),B.quarantined++,B.quarantinedFiles.push(A);let Y=cq0(this.syncPath,".import-errors.log"),I=new Date().toISOString(),X=L0(Q),H=`${I} - ${A}: ${X}
|
|
1680
1681
|
\u2192 ${A}.invalid
|
|
1681
1682
|
|
|
1682
1683
|
`;await d22(Y,H),this.logger.warn("Quarantined invalid entity file",{originalPath:A,quarantinePath:`${A}.invalid`,error:X})}catch(Y){this.logger.error("Failed to quarantine invalid file",{path:A,error:Y}),B.failed++,B.errors.push({path:A,error:"Failed to quarantine invalid file"})}}async markAsRecoveredIfNeeded(A){let Q=cq0(this.syncPath,".import-errors.log");try{await n22(Q)}catch{return}try{let B=await i22(Q,"utf-8");if(B.includes(A)){let $=`${new Date().toISOString()} - [RECOVERED] ${A}
|
|
@@ -1702,7 +1703,7 @@ ${A.entityContent}`,ZF1);X=w+k.imagePrompt}catch(k){this.logger.warn("AI prompt
|
|
|
1702
1703
|
*...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
|
|
1703
1704
|
## Getting Started
|
|
1704
1705
|
`),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(`
|
|
1705
|
-
`)}}B0();class gl extends MB{context;directorySync;constructor(A,Q,B){super(A,{schema:TL0,jobTypeName:"directory-export"});this.context=Q,this.directorySync=B}async process(A,Q,B){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let w=Date.now(),$={exported:0,failed:0,errors:[]};try{let D=A.entityTypes??this.context.entityService.getEntityTypes();this.logger.debug("Starting export",{jobId:Q,entityTypes:D}),await B.report({message:`Starting export of ${D.length} entity types`,progress:0,total:D.length});for(let[Y,I]of D.entries())await this.exportEntityType(I,A.batchSize??100,Q,$),await B.report({message:`Exported ${Y+1}/${D.length} entity types (${$.exported} entities)`,progress:Y+1,total:D.length});return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-w}),$}catch(D){throw this.logger.error("Directory export job failed",{jobId:Q,error:D}),D}}async exportEntityType(A,Q,B,w){let $=0,D=!0;while(D){let Y=await this.context.entityService.listEntities(A,{limit:Q,offset:$});if(Y.length===0){D=!1;break}let I=Y.map(async(X)=>{let H=await this.directorySync.processEntityExport(X);if(H.success)w.exported++;else w.failed++,w.errors.push({entityId:X.id,entityType:A,error:H.error??"Unknown error"});return H});await Promise.all(I),this.logger.debug("Export progress",{jobId:B,entityType:A,processed:$+Y.length,exported:w.exported,failed:w.failed}),$+=Q,D=Y.length===Q}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}B0();GA();aD();class yl extends MB{context;directorySync;constructor(A,Q,B){super(A,{schema:xL0,jobTypeName:"directory-import"});this.context=Q,this.directorySync=B}async process(A,Q,B){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let w=Date.now(),$={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]};try{let D=A.paths??await this.directorySync.getAllMarkdownFiles();this.logger.debug("Starting import",{jobId:Q,totalFiles:D.length}),await B.report({message:`Starting import of ${D.length} files`,progress:0,total:D.length});let Y=A.batchSize??100;for(let I=0;I<D.length;I+=Y){let X=D.slice(I,I+Y);await this.importBatch(X,Q,$,I,D.length);let H=Math.min(I+Y,D.length);await B.report({message:`Imported ${H}/${D.length} files (${$.imported} successful, ${$.failed} failed)`,progress:H,total:D.length})}return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,duration:Date.now()-w}),$}catch(D){throw this.logger.error("Directory import job failed",{jobId:Q,error:D}),D}}async importBatch(A,Q,B,w,$){let D=A.map(async(Y)=>{try{let I=await this.directorySync.fileOps.readEntity(Y);if(!this.context.entityService.getEntityTypes().includes(I.entityType))return B.skipped++,{success:!1,skipped:!0};try{let H=this.context.entityService.deserializeEntity(I.content,I.entityType),W=await this.context.entityService.getEntity(I.entityType,I.id);if(W){let J=new Date(W.updated).getTime(),F=I.updated.getTime(),z=aB(I.content),V=W.contentHash!==z;if(J<F||V){let E={...W,content:I.content,...H,id:I.id,entityType:I.entityType,updated:I.updated.toISOString()};await this.context.entityService.updateEntity(E),B.imported++}else B.skipped++}else{let J={id:I.id,entityType:I.entityType,content:I.content,...H,metadata:H.metadata??{},created:I.created.toISOString(),updated:I.updated.toISOString()};await this.context.entityService.createEntity(J),B.imported++}return{success:!0}}catch{return B.skipped++,{success:!1,skipped:!0}}}catch(I){return B.failed++,B.errors.push({path:Y,error:L0(I)}),{success:!1,error:I}}});await Promise.all(D),this.logger.debug("Import progress",{jobId:Q,processed:w+A.length,total:$,imported:B.imported,skipped:B.skipped,failed:B.failed})}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}B0();class ml extends MB{directorySync;context;constructor(A,Q,B){super(A,{schema:bL0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=B}async process(A,Q,B){let w=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let D={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await B.report({progress:10,message:"Scanning directory for changes"}),D=await this.importWithProgress(A.paths,B),$==="import")await this.waitForImportJobs(D.jobIds,B),await B.report({progress:100,message:`Import complete: ${D.imported} imported`});else await B.report({progress:50,message:`Imported ${D.imported} entities`}),await this.waitForImportJobs(D.jobIds,B),await B.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let X=$==="export"?10:60;await B.report({progress:X,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,B),await B.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${D.imported} imported, ${Y.exported} exported`})}let I=Date.now()-w;return this.logger.info("Directory sync job completed",{jobId:Q,duration:I,imported:D.imported,exported:Y.exported}),{import:D,export:Y,duration:I}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(B){throw this.logger.error("Import phase failed",{error:B}),B}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(B){throw this.logger.error("Export phase failed",{error:B}),B}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:B}=this.context,w=300000,$=500,D=Date.now(),Y=async()=>{let X=(await Promise.all(A.map((W)=>B.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()-D>w){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,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}B0();class ul extends MB{context;constructor(A,Q,B){super(A,{schema:RHA,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,B){let w=RHA.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}),await B.report({progress:0,total:1,message:`Deleting ${w.entityType}:${w.entityId}`});try{let $=await this.context.entityService.deleteEntity(w.entityType,w.entityId);if($)this.logger.info("Successfully deleted entity for removed file",{entityId:w.entityId,entityType:w.entityType});else this.logger.warn("Entity not found in database",{entityId:w.entityId,entityType:w.entityType});return await B.report({progress:1,total:1,message:`Deleted ${w.entityType}:${w.entityId}`}),{deleted:$,entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:w.entityId,entityType:w.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}B0();GA();var P62=Z.object({});class cl extends MB{directorySync;constructor(A,Q){super(A,{schema:P62,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,B){await B.report({progress:0,message:"Removing orphaned entities"});let w=await this.directorySync.removeOrphanedEntities();return await B.report({progress:100,message:`Cleanup complete: ${w.deleted} orphans removed`}),w}}B0();GA();import{readFile as _62,writeFile as b62}from"fs/promises";var x62=Z.object({filePath:Z.string(),sourceUrl:Z.string().url(),postTitle:Z.string(),postSlug:Z.string(),customAlt:Z.string().optional()});class ll extends MB{context;fetcher;constructor(A,Q,B=R7){super(Q,{schema:x62,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=B}async process(A,Q,B){let{filePath:w,sourceUrl:$,postTitle:D,postSlug:Y,customAlt:I}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:w,sourceUrl:$,postSlug:Y});try{await this.reportProgress(B,{progress:J2.INIT,message:`Reading file: ${w}`});let X;try{X=await _62(w,"utf-8")}catch(E){return this.logger.error("Failed to read file",{filePath:w,error:L0(E)}),K6.failure(E)}let H;try{H=uD(X)}catch(E){return this.logger.warn("Failed to parse markdown",{filePath:w,error:L0(E)}),K6.failure(E)}let W=H.frontmatter;if(W.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(B,{progress:J2.FETCH,message:"Checking for existing image"});let J=await this.context.entityService.listEntities("image",{filter:{metadata:{sourceUrl:$}},limit:1}),F;if(J[0])F=J[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:F}),await this.reportProgress(B,{progress:J2.EXTRACT,message:`Reusing existing image: ${F}`});else{await this.reportProgress(B,{progress:J2.PROCESS,message:`Fetching image from ${$}`});let E;try{E=await this.fetcher($)}catch(n){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:L0(n)}),K6.failure(n)}await this.reportProgress(B,{progress:J2.GENERATE,message:"Creating image entity"});let{base64:L}=iW(E),k=CF(L),_=rW(L);if(!k||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),K6.failure(Error("Could not detect image format or dimensions"));F=`${Y}-cover`;let j=`Cover image for ${D}`,r=I??j;await this.context.entityService.createEntity({id:F,entityType:"image",content:E,metadata:{title:j,alt:r,format:k,width:_.width,height:_.height,sourceUrl:$}}),this.logger.debug("Created image entity",{imageId:F,sourceUrl:$}),await this.reportProgress(B,{progress:J2.EXTRACT,message:`Created image: ${F}`})}await this.reportProgress(B,{progress:J2.SAVE,message:"Updating file"});let z={...W};delete z.coverImageUrl,delete z.coverImageAlt,z.coverImageId=F;let V=C3(z,H.content);try{await b62(w,V,"utf-8")}catch(E){return this.logger.error("Failed to write file",{filePath:w,error:L0(E)}),K6.failure(E)}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:w,imageId:F,sourceUrl:$}),{success:!0,imageId:F}}catch(X){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:w,error:L0(X)}),K6.failure(X)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}B0();GA();import{readFile as T62,writeFile as v62}from"fs/promises";class pl extends MB{converter;constructor(A,Q,B=R7){super(Q,{schema:vL0,jobTypeName:"inline-image-convert"});this.converter=new HP(A.entityService,Q,B)}async process(A,Q,B){let{filePath:w,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:w,postSlug:$});try{await this.reportProgress(B,{progress:J2.INIT,message:`Reading file: ${w}`});let D;try{D=await T62(w,"utf-8")}catch(X){let H=L0(X);return this.logger.error("Failed to read file",{filePath:w,error:H}),{success:!1,error:H}}await this.reportProgress(B,{progress:J2.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(D,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:w,count:Y.length}),await this.reportProgress(B,{progress:J2.PROCESS,message:`Converting ${Y.length} images`});let I=await this.converter.convert(D,$);if(!I.converted)return this.logger.debug("No images were converted",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(B,{progress:J2.SAVE,message:"Writing updated file"});try{await v62(w,I.content,"utf-8")}catch(X){let H=L0(X);return this.logger.error("Failed to write file",{filePath:w,error:H}),{success:!1,error:H}}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:w,convertedCount:I.convertedCount}),{success:!0,convertedCount:I.convertedCount}}catch(D){let Y=L0(D);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:w,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function gL0(A,Q,B){let w=($)=>B.child($);A.jobs.registerHandler("directory-sync",new ml(w("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new gl(w("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new yl(w("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new ul(w("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new cl(w("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new ll(A,w("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new pl(A,w("InlineImageConversionJobHandler"))),B.debug("Registered async job handlers")}B0();import{unlink as S62,access as h62}from"fs/promises";function yL0(A,Q,B,w){let{subscribe:$}=A.messaging,{entityService:D}=A;$("entity:created",async(Y)=>{let{entity:I}=Y.payload;try{await Q.fileOps.writeEntity(I),B.debug("Auto-exported created entity",{id:I.id,entityType:I.entityType})}catch(X){B.error("Auto-export FAILED for created entity",{id:I.id,entityType:I.entityType,error:X instanceof Error?X.message:String(X),stack:X instanceof Error?X.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:I,entityId:X}=Y.payload;try{let H=await D.getEntity(I,X);if(!H)return B.debug("Entity not found in DB, skipping export",{entityType:I,entityId:X}),{success:!1};await Q.fileOps.writeEntity(H),B.debug("Auto-exported updated entity",{id:H.id,entityType:H.entityType})}catch(H){B.error("Auto-export FAILED for updated entity",{entityType:I,entityId:X,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:I,entityType:X}=Y.payload,H=Q.fileOps.getFilePath(I,X);if(await h62(H).then(()=>!0,()=>!1))await S62(H),B.debug("Auto-deleted entity file",{id:I,entityType:X,path:H});return{success:!0}}),B.debug("Setup auto-sync for entity events",{entityTypes:w})}function mL0(A,Q,B){Q.setJobQueueCallback(async(w)=>{let $=[{type:w.type,data:w.data}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:j6(),metadata:{operationType:"file_operations",operationTarget:B,pluginId:"directory-sync"}})})}GA();import{access as g62,readdir as uL0,mkdir as y62,copyFile as m62}from"fs/promises";import{exec as u62}from"child_process";import{promisify as c62}from"util";import{join as kHA,resolve as jHA}from"path";var l62=c62(u62);async function dl(A){try{return await g62(A),!0}catch{return!1}}async function p62(A,Q){if(!await dl(A))return!0;if((await uL0(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await d62(A))return Q.debug("Git repository with remote detected - skipping seed content",{path:A}),!1;return!0}async function d62(A){let Q=kHA(A,".git");if(!await dl(Q))return!1;try{let{stdout:B}=await l62("git remote",{cwd:A});return B.trim().length>0}catch{return!1}}async function cL0(A,Q){let B=await uL0(A,{withFileTypes:!0});for(let w of B){let $=kHA(A,w.name),D=kHA(Q,w.name);if(w.isDirectory()){if(!await dl(D))await y62(D,{recursive:!0});await cL0($,D)}else await m62($,D)}}async function lL0(A,Q,B){let w=jHA(process.cwd(),A);B=B?jHA(B):jHA(process.cwd(),"seed-content");let $=await p62(w,Q);if($&&await dl(B))Q.debug("Copying seed content to brain-data directory"),await cL0(B,w),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")}async function i62(A,Q,B,w=300000){let D=Date.now();while(Date.now()-D<w){let Y=await A.jobs.getBatchStatus(Q);if(Y&&(Y.status==="completed"||Y.status==="failed")){B.debug("Batch completed",{batchId:Q,status:Y.status,completed:Y.completedOperations,failed:Y.failedOperations});return}await new Promise((I)=>setTimeout(I,500))}B.warn(`Timeout waiting for batch ${Q} after ${w}ms`)}function pL0(A,Q,B,w,$,D){let Y=!1,I=async()=>{if(Y)return;Y=!0;let X=Q();if(B.seedContent){let H=B.syncPath??A.dataDir;await lL0(H,$,B.seedContentPath)}try{if(D){$.debug("Git enabled \u2014 pulling before import");let W=await D.pull();if(W.files.length>0)$.info("Pulled changes from remote",{filesChanged:W.files.length})}$.debug("Starting initial sync");let H=await X.queueSyncBatch(A,"initial-sync",void 0,{includeCleanup:!0});if(!H){$.debug("Initial sync: no files to import"),await A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0});return}$.debug("Initial sync: queued imports",{importOperations:H.importOperationsCount,totalFiles:H.totalFiles}),i62(A,H.batchId,$).then(()=>A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0}),(W)=>{$.error("Initial sync batch failed",W),A.messaging.send("sync:initial:completed",{success:!1,error:L0(W)},{broadcast:!0})})}catch(H){$.error("Initial sync failed",H),await A.messaging.send("sync:initial:completed",{success:!1,error:L0(H)},{broadcast:!0})}};A.messaging.subscribe("system:plugins:ready",async()=>{return $.debug("system:plugins:ready received, starting initial sync"),await I(),{success:!0}})}GA();function dL0(A,Q,B,w){let $=new k3(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(I){w.error("Git auto-commit failed",{error:I})}})},B),D=["entity:created","entity:updated","entity:deleted"],Y=[];for(let I of D){let X=A.subscribe(I,async()=>{return $.trigger(),{success:!0}});Y.push(X)}return()=>{$.dispose();for(let I of Y)I()}}function iL0(A,Q,B,w,$){if(w<=0)return()=>{};let D=w*60*1000,Y=!1,I=async()=>{if(Y)return;Y=!0;try{let{files:H}=await A.withLock(()=>A.pull());if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});let W=await Q.queueSyncBatch(B,"periodic-sync");if(W)$.debug("Periodic sync: queued imports",{importOperations:W.importOperationsCount,totalFiles:W.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{Y=!1}},X=setInterval(()=>{I()},D);return $.info("Started periodic git sync",{intervalMinutes:w}),()=>{clearInterval(X)}}function rL0(A,Q,B,w,$){let{subscribe:D}=A.messaging;D("entity:export:request",async(Y)=>{try{return{success:!0,data:await Q().exportEntities(Y.payload.entityTypes)}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Export failed"}}}),D("entity:import:request",async(Y)=>{try{let I=Q(),X=Y.payload.paths,H=await I.importEntities(X);if(X&&X.length>0)await I.removeOrphanedEntities();return{success:!0,data:H}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Import failed"}}}),D("sync:status:request",async()=>{try{let I=await Q().getStatus();return{success:!0,data:{syncPath:I.syncPath,isInitialized:I.exists,watchEnabled:I.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),D("sync:configure:request",async(Y)=>{try{return await B({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Configuration failed"}}}),D("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),w.debug("Registered message handlers")}B0();GA();B0();GA();function nL0(A,Q){return yQ(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(B)=>{let w=`${B.entityType}/${B.id}.md`;try{if(B.sha){let D=await Q.show(B.sha,w);return O5({sha:B.sha,entityType:B.entityType,id:B.id,content:D},`Content at ${B.sha.slice(0,7)}`)}let $=await Q.log(w,B.limit);if($.length===0)return O5({commits:[]},`No history found for ${B.entityType}/${B.id}`);return O5({commits:$,entityType:B.entityType,id:B.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return Ew($ instanceof Error?$.message:"History lookup failed")}})}function oL0(A,Q,B,w){let $=[yQ(B,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(D,Y)=>{try{let I=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${B}`,X={interfaceType:Y.interfaceType,channelId:Y.channelId},H=!1;if(w)await w.withLock(()=>w.pull()),H=!0;let W=await A.queueSyncBatch(Q,I,X);if(!W)return O5({gitPulled:H},"No files to sync");return O5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:H},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files${H?" (pulled from git)":""}`)}catch(I){return Ew(I instanceof Error?I.message:"Sync failed")}},{cli:{name:"sync"}}),yQ(B,"status","Get sync and git repository status \u2014 last sync time, watching state, pending git changes. Use this for status questions, not for actually syncing or backing up.",Z.object({}),async()=>{try{let D=await A.getStatus(),Y={syncPath:D.syncPath,lastSync:D.lastSync?.toISOString(),watching:D.watching};if(w){let I=await w.getStatus();Y.git={isRepo:I.isRepo,branch:I.branch,hasChanges:I.hasChanges,ahead:I.ahead,behind:I.behind,remote:I.remote}}return O5(Y)}catch(D){return Ew(D instanceof Error?D.message:"Status check failed")}},{visibility:"public"})];if(w)$.push(nL0(B,w));return $}var sL0={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.37",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/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^3.5.3","simple-git":"^3.21.0"},devDependencies:{"@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},peerDependencies:{}};class PHA extends tB{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",sL0,A,_L0)}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:B}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:VP,basePrompt:"",formatter:new hl,requiredPermission:"anchor"}});let w=this.config.syncPath??A.dataDir;this.directorySync=new KP({syncPath:w,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:B,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:w})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(yL0(A,$,this.logger,this.config.entityTypes),this.config.autoSync)mL0(A,$,this.config.syncPath??A.dataDir);let D=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!D)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(D&&this.config.git){let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new fHA({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),this.gitCleanups.push(dL0(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(iL0(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)pL0(A,()=>this.requireDirectorySync(),this.config,this.id,this.logger,this.gitSync);rL0(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return oL0(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 KP({...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){gL0(A,this.requireDirectorySync(),this.logger)}}function LZ(A={}){return new PHA(A)}B0();B0();GA();GA();var aL0=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional()}),layouts:Z.record(Z.any()),themeCSS:Z.string().optional()}),uyQ=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});import{render as L_0}from"preact-render-to-string";import{h as rZ}from"preact";class _HA{headProps=null;defaultTitle;constructor(A){this.defaultTitle=A}setHeadProps(A){this.headProps??=A}getHeadProps(){return this.headProps}reset(){this.headProps=null}generateHeadHTML(){let A=[];if(A.push('<meta charset="UTF-8">'),A.push('<meta name="viewport" content="width=device-width, initial-scale=1.0">'),A.push('<meta http-equiv="X-UA-Compatible" content="IE=edge">'),A.push('<link rel="icon" type="image/svg+xml" href="/favicon.svg">'),A.push('<link rel="icon" type="image/png" href="/favicon.png">'),A.push('<link rel="stylesheet" href="/styles/main.css">'),!this.headProps)return A.push(`<title>${this.escapeHtml(this.defaultTitle)}</title>`),A.join(`
|
|
1706
|
+
`)}}B0();class gl extends MB{context;directorySync;constructor(A,Q,B){super(A,{schema:TL0,jobTypeName:"directory-export"});this.context=Q,this.directorySync=B}async process(A,Q,B){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let w=Date.now(),$={exported:0,failed:0,errors:[]};try{let D=A.entityTypes??this.context.entityService.getEntityTypes();this.logger.debug("Starting export",{jobId:Q,entityTypes:D}),await B.report({message:`Starting export of ${D.length} entity types`,progress:0,total:D.length});for(let[Y,I]of D.entries())await this.exportEntityType(I,A.batchSize??100,Q,$),await B.report({message:`Exported ${Y+1}/${D.length} entity types (${$.exported} entities)`,progress:Y+1,total:D.length});return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-w}),$}catch(D){throw this.logger.error("Directory export job failed",{jobId:Q,error:D}),D}}async exportEntityType(A,Q,B,w){let $=0,D=!0;while(D){let Y=await this.context.entityService.listEntities(A,{limit:Q,offset:$});if(Y.length===0){D=!1;break}let I=Y.map(async(X)=>{let H=await this.directorySync.processEntityExport(X);if(H.success)w.exported++;else w.failed++,w.errors.push({entityId:X.id,entityType:A,error:H.error??"Unknown error"});return H});await Promise.all(I),this.logger.debug("Export progress",{jobId:B,entityType:A,processed:$+Y.length,exported:w.exported,failed:w.failed}),$+=Q,D=Y.length===Q}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}B0();GA();aD();class yl extends MB{context;directorySync;constructor(A,Q,B){super(A,{schema:xL0,jobTypeName:"directory-import"});this.context=Q,this.directorySync=B}async process(A,Q,B){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let w=Date.now(),$={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]};try{let D=A.paths??await this.directorySync.getAllMarkdownFiles();this.logger.debug("Starting import",{jobId:Q,totalFiles:D.length}),await B.report({message:`Starting import of ${D.length} files`,progress:0,total:D.length});let Y=A.batchSize??100;for(let I=0;I<D.length;I+=Y){let X=D.slice(I,I+Y);await this.importBatch(X,Q,$,I,D.length);let H=Math.min(I+Y,D.length);await B.report({message:`Imported ${H}/${D.length} files (${$.imported} successful, ${$.failed} failed)`,progress:H,total:D.length})}return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,duration:Date.now()-w}),$}catch(D){throw this.logger.error("Directory import job failed",{jobId:Q,error:D}),D}}async importBatch(A,Q,B,w,$){let D=A.map(async(Y)=>{try{let I=await this.directorySync.fileOps.readEntity(Y);if(!this.context.entityService.getEntityTypes().includes(I.entityType))return B.skipped++,{success:!1,skipped:!0};try{let H=this.context.entityService.deserializeEntity(I.content,I.entityType),W=await this.context.entityService.getEntity(I.entityType,I.id);if(W){let J=new Date(W.updated).getTime(),F=I.updated.getTime(),z=aB(I.content),V=W.contentHash!==z;if(J<F||V){let E={...W,content:I.content,...H,id:I.id,entityType:I.entityType,updated:I.updated.toISOString()};await this.context.entityService.updateEntity(E),B.imported++}else B.skipped++}else{let J={id:I.id,entityType:I.entityType,content:I.content,...H,metadata:H.metadata??{},created:I.created.toISOString(),updated:I.updated.toISOString()};await this.context.entityService.createEntity(J),B.imported++}return{success:!0}}catch{return B.skipped++,{success:!1,skipped:!0}}}catch(I){return B.failed++,B.errors.push({path:Y,error:L0(I)}),{success:!1,error:I}}});await Promise.all(D),this.logger.debug("Import progress",{jobId:Q,processed:w+A.length,total:$,imported:B.imported,skipped:B.skipped,failed:B.failed})}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}B0();class ml extends MB{directorySync;context;constructor(A,Q,B){super(A,{schema:bL0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=B}async process(A,Q,B){let w=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let D={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await B.report({progress:10,message:"Scanning directory for changes"}),D=await this.importWithProgress(A.paths,B),$==="import")await this.waitForImportJobs(D.jobIds,B),await B.report({progress:100,message:`Import complete: ${D.imported} imported`});else await B.report({progress:50,message:`Imported ${D.imported} entities`}),await this.waitForImportJobs(D.jobIds,B),await B.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let X=$==="export"?10:60;await B.report({progress:X,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,B),await B.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${D.imported} imported, ${Y.exported} exported`})}let I=Date.now()-w;return this.logger.info("Directory sync job completed",{jobId:Q,duration:I,imported:D.imported,exported:Y.exported}),{import:D,export:Y,duration:I}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(B){throw this.logger.error("Import phase failed",{error:B}),B}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(B){throw this.logger.error("Export phase failed",{error:B}),B}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:B}=this.context,w=300000,$=500,D=Date.now(),Y=async()=>{let X=(await Promise.all(A.map((W)=>B.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()-D>w){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,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}B0();class ul extends MB{context;constructor(A,Q,B){super(A,{schema:RHA,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,B){let w=RHA.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}),await B.report({progress:0,total:1,message:`Deleting ${w.entityType}:${w.entityId}`});try{let $=await this.context.entityService.deleteEntity(w.entityType,w.entityId);if($)this.logger.info("Successfully deleted entity for removed file",{entityId:w.entityId,entityType:w.entityType});else this.logger.warn("Entity not found in database",{entityId:w.entityId,entityType:w.entityType});return await B.report({progress:1,total:1,message:`Deleted ${w.entityType}:${w.entityId}`}),{deleted:$,entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:w.entityId,entityType:w.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}B0();GA();var P62=Z.object({});class cl extends MB{directorySync;constructor(A,Q){super(A,{schema:P62,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,B){await B.report({progress:0,message:"Removing orphaned entities"});let w=await this.directorySync.removeOrphanedEntities();return await B.report({progress:100,message:`Cleanup complete: ${w.deleted} orphans removed`}),w}}B0();GA();import{readFile as _62,writeFile as b62}from"fs/promises";var x62=Z.object({filePath:Z.string(),sourceUrl:Z.string().url(),postTitle:Z.string(),postSlug:Z.string(),customAlt:Z.string().optional()});class ll extends MB{context;fetcher;constructor(A,Q,B=R7){super(Q,{schema:x62,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=B}async process(A,Q,B){let{filePath:w,sourceUrl:$,postTitle:D,postSlug:Y,customAlt:I}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:w,sourceUrl:$,postSlug:Y});try{await this.reportProgress(B,{progress:J2.INIT,message:`Reading file: ${w}`});let X;try{X=await _62(w,"utf-8")}catch(E){return this.logger.error("Failed to read file",{filePath:w,error:L0(E)}),K6.failure(E)}let H;try{H=uD(X)}catch(E){return this.logger.warn("Failed to parse markdown",{filePath:w,error:L0(E)}),K6.failure(E)}let W=H.frontmatter;if(W.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(B,{progress:J2.FETCH,message:"Checking for existing image"});let J=await this.context.entityService.listEntities("image",{filter:{metadata:{sourceUrl:$}},limit:1}),F;if(J[0])F=J[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:F}),await this.reportProgress(B,{progress:J2.EXTRACT,message:`Reusing existing image: ${F}`});else{await this.reportProgress(B,{progress:J2.PROCESS,message:`Fetching image from ${$}`});let E;try{E=await this.fetcher($)}catch(n){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:L0(n)}),K6.failure(n)}await this.reportProgress(B,{progress:J2.GENERATE,message:"Creating image entity"});let{base64:L}=iW(E),k=CF(L),_=rW(L);if(!k||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),K6.failure(Error("Could not detect image format or dimensions"));F=`${Y}-cover`;let j=`Cover image for ${D}`,r=I??j;await this.context.entityService.createEntity({id:F,entityType:"image",content:E,metadata:{title:j,alt:r,format:k,width:_.width,height:_.height,sourceUrl:$}}),this.logger.debug("Created image entity",{imageId:F,sourceUrl:$}),await this.reportProgress(B,{progress:J2.EXTRACT,message:`Created image: ${F}`})}await this.reportProgress(B,{progress:J2.SAVE,message:"Updating file"});let z={...W};delete z.coverImageUrl,delete z.coverImageAlt,z.coverImageId=F;let V=C3(z,H.content);try{await b62(w,V,"utf-8")}catch(E){return this.logger.error("Failed to write file",{filePath:w,error:L0(E)}),K6.failure(E)}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:w,imageId:F,sourceUrl:$}),{success:!0,imageId:F}}catch(X){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:w,error:L0(X)}),K6.failure(X)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}B0();GA();import{readFile as T62,writeFile as v62}from"fs/promises";class pl extends MB{converter;constructor(A,Q,B=R7){super(Q,{schema:vL0,jobTypeName:"inline-image-convert"});this.converter=new HP(A.entityService,Q,B)}async process(A,Q,B){let{filePath:w,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:w,postSlug:$});try{await this.reportProgress(B,{progress:J2.INIT,message:`Reading file: ${w}`});let D;try{D=await T62(w,"utf-8")}catch(X){let H=L0(X);return this.logger.error("Failed to read file",{filePath:w,error:H}),{success:!1,error:H}}await this.reportProgress(B,{progress:J2.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(D,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:w,count:Y.length}),await this.reportProgress(B,{progress:J2.PROCESS,message:`Converting ${Y.length} images`});let I=await this.converter.convert(D,$);if(!I.converted)return this.logger.debug("No images were converted",{filePath:w}),await this.reportProgress(B,{progress:J2.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(B,{progress:J2.SAVE,message:"Writing updated file"});try{await v62(w,I.content,"utf-8")}catch(X){let H=L0(X);return this.logger.error("Failed to write file",{filePath:w,error:H}),{success:!1,error:H}}return await this.reportProgress(B,{progress:J2.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:w,convertedCount:I.convertedCount}),{success:!0,convertedCount:I.convertedCount}}catch(D){let Y=L0(D);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:w,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function gL0(A,Q,B){let w=($)=>B.child($);A.jobs.registerHandler("directory-sync",new ml(w("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new gl(w("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new yl(w("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new ul(w("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new cl(w("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new ll(A,w("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new pl(A,w("InlineImageConversionJobHandler"))),B.debug("Registered async job handlers")}B0();import{unlink as S62,access as h62}from"fs/promises";function yL0(A,Q,B,w){let{subscribe:$}=A.messaging,{entityService:D}=A;$("entity:created",async(Y)=>{let{entity:I}=Y.payload;try{await Q.fileOps.writeEntity(I),B.debug("Auto-exported created entity",{id:I.id,entityType:I.entityType})}catch(X){B.error("Auto-export FAILED for created entity",{id:I.id,entityType:I.entityType,error:X instanceof Error?X.message:String(X),stack:X instanceof Error?X.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:I,entityId:X}=Y.payload;try{let H=await D.getEntity(I,X);if(!H)return B.debug("Entity not found in DB, skipping export",{entityType:I,entityId:X}),{success:!1};await Q.fileOps.writeEntity(H),B.debug("Auto-exported updated entity",{id:H.id,entityType:H.entityType})}catch(H){B.error("Auto-export FAILED for updated entity",{entityType:I,entityId:X,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:I,entityType:X}=Y.payload,H=Q.fileOps.getFilePath(I,X);if(await h62(H).then(()=>!0,()=>!1))await S62(H),B.debug("Auto-deleted entity file",{id:I,entityType:X,path:H});return{success:!0}}),B.debug("Setup auto-sync for entity events",{entityTypes:w})}function mL0(A,Q,B){Q.setJobQueueCallback(async(w)=>{let $=[{type:w.type,data:w.data}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:j6(),metadata:{operationType:"file_operations",operationTarget:B,pluginId:"directory-sync"}})})}GA();import{access as g62,readdir as uL0,mkdir as y62,copyFile as m62}from"fs/promises";import{exec as u62}from"child_process";import{promisify as c62}from"util";import{join as kHA,resolve as jHA}from"path";var l62=c62(u62);async function dl(A){try{return await g62(A),!0}catch{return!1}}async function p62(A,Q){if(!await dl(A))return!0;if((await uL0(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await d62(A))return Q.debug("Git repository with remote detected - skipping seed content",{path:A}),!1;return!0}async function d62(A){let Q=kHA(A,".git");if(!await dl(Q))return!1;try{let{stdout:B}=await l62("git remote",{cwd:A});return B.trim().length>0}catch{return!1}}async function cL0(A,Q){let B=await uL0(A,{withFileTypes:!0});for(let w of B){let $=kHA(A,w.name),D=kHA(Q,w.name);if(w.isDirectory()){if(!await dl(D))await y62(D,{recursive:!0});await cL0($,D)}else await m62($,D)}}async function lL0(A,Q,B){let w=jHA(process.cwd(),A);B=B?jHA(B):jHA(process.cwd(),"seed-content");let $=await p62(w,Q);if($&&await dl(B))Q.debug("Copying seed content to brain-data directory"),await cL0(B,w),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")}async function i62(A,Q,B,w=300000){let D=Date.now();while(Date.now()-D<w){let Y=await A.jobs.getBatchStatus(Q);if(Y&&(Y.status==="completed"||Y.status==="failed")){B.debug("Batch completed",{batchId:Q,status:Y.status,completed:Y.completedOperations,failed:Y.failedOperations});return}await new Promise((I)=>setTimeout(I,500))}B.warn(`Timeout waiting for batch ${Q} after ${w}ms`)}function pL0(A,Q,B,w,$,D){let Y=!1,I=async()=>{if(Y)return;Y=!0;let X=Q();if(B.seedContent){let H=B.syncPath??A.dataDir;await lL0(H,$,B.seedContentPath)}try{if(D){$.debug("Git enabled \u2014 pulling before import");let W=await D.pull();if(W.files.length>0)$.info("Pulled changes from remote",{filesChanged:W.files.length})}$.debug("Starting initial sync");let H=await X.queueSyncBatch(A,"initial-sync",void 0,{includeCleanup:!0});if(!H){$.debug("Initial sync: no files to import"),await A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0});return}$.debug("Initial sync: queued imports",{importOperations:H.importOperationsCount,totalFiles:H.totalFiles}),i62(A,H.batchId,$).then(()=>A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0}),(W)=>{$.error("Initial sync batch failed",W),A.messaging.send("sync:initial:completed",{success:!1,error:L0(W)},{broadcast:!0})})}catch(H){$.error("Initial sync failed",H),await A.messaging.send("sync:initial:completed",{success:!1,error:L0(H)},{broadcast:!0})}};A.messaging.subscribe("system:plugins:ready",async()=>{return $.debug("system:plugins:ready received, starting initial sync"),await I(),{success:!0}})}GA();function dL0(A,Q,B,w){let $=new k3(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(I){w.error("Git auto-commit failed",{error:I})}})},B),D=["entity:created","entity:updated","entity:deleted"],Y=[];for(let I of D){let X=A.subscribe(I,async()=>{return $.trigger(),{success:!0}});Y.push(X)}return()=>{$.dispose();for(let I of Y)I()}}function iL0(A,Q,B,w,$){if(w<=0)return()=>{};let D=w*60*1000,Y=!1,I=async()=>{if(Y)return;Y=!0;try{let{files:H}=await A.withLock(()=>A.pull());if(H.length>0)$.info("Periodic sync: pulled changes",{filesChanged:H.length});let W=await Q.queueSyncBatch(B,"periodic-sync");if(W)$.debug("Periodic sync: queued imports",{importOperations:W.importOperationsCount,totalFiles:W.totalFiles})}catch(H){$.error("Periodic git sync failed",{error:H})}finally{Y=!1}},X=setInterval(()=>{I()},D);return $.info("Started periodic git sync",{intervalMinutes:w}),()=>{clearInterval(X)}}function rL0(A,Q,B,w,$){let{subscribe:D}=A.messaging;D("entity:export:request",async(Y)=>{try{return{success:!0,data:await Q().exportEntities(Y.payload.entityTypes)}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Export failed"}}}),D("entity:import:request",async(Y)=>{try{let I=Q(),X=Y.payload.paths,H=await I.importEntities(X);if(X&&X.length>0)await I.removeOrphanedEntities();return{success:!0,data:H}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Import failed"}}}),D("sync:status:request",async()=>{try{let I=await Q().getStatus();return{success:!0,data:{syncPath:I.syncPath,isInitialized:I.exists,watchEnabled:I.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),D("sync:configure:request",async(Y)=>{try{return await B({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(I){return{success:!1,error:I instanceof Error?I.message:"Configuration failed"}}}),D("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),w.debug("Registered message handlers")}B0();GA();B0();GA();function nL0(A,Q){return yQ(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(B)=>{let w=`${B.entityType}/${B.id}.md`;try{if(B.sha){let D=await Q.show(B.sha,w);return O5({sha:B.sha,entityType:B.entityType,id:B.id,content:D},`Content at ${B.sha.slice(0,7)}`)}let $=await Q.log(w,B.limit);if($.length===0)return O5({commits:[]},`No history found for ${B.entityType}/${B.id}`);return O5({commits:$,entityType:B.entityType,id:B.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return Ew($ instanceof Error?$.message:"History lookup failed")}})}function oL0(A,Q,B,w){let $=[yQ(B,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(D,Y)=>{try{let I=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${B}`,X={interfaceType:Y.interfaceType,channelId:Y.channelId},H=!1;if(w)await w.withLock(()=>w.pull()),H=!0;let W=await A.queueSyncBatch(Q,I,X);if(!W)return O5({gitPulled:H},"No files to sync");return O5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:H},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files${H?" (pulled from git)":""}`)}catch(I){return Ew(I instanceof Error?I.message:"Sync failed")}},{cli:{name:"sync"}}),yQ(B,"status","Get sync and git repository status \u2014 last sync time, watching state, pending git changes. Use this for status questions, not for actually syncing or backing up.",Z.object({}),async()=>{try{let D=await A.getStatus(),Y={syncPath:D.syncPath,lastSync:D.lastSync?.toISOString(),watching:D.watching};if(w){let I=await w.getStatus();Y.git={isRepo:I.isRepo,branch:I.branch,hasChanges:I.hasChanges,ahead:I.ahead,behind:I.behind,remote:I.remote}}return O5(Y)}catch(D){return Ew(D instanceof Error?D.message:"Status check failed")}},{visibility:"public"})];if(w)$.push(nL0(B,w));return $}var sL0={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.38",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/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^3.5.3","simple-git":"^3.21.0"},devDependencies:{"@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"},peerDependencies:{}};class PHA extends tB{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",sL0,A,_L0)}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:B}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:VP,basePrompt:"",formatter:new hl,requiredPermission:"anchor"}});let w=this.config.syncPath??A.dataDir;this.directorySync=new KP({syncPath:w,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:B,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:w})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(yL0(A,$,this.logger,this.config.entityTypes),this.config.autoSync)mL0(A,$,this.config.syncPath??A.dataDir);let D=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!D)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(D&&this.config.git){let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new fHA({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),this.gitCleanups.push(dL0(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(iL0(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)pL0(A,()=>this.requireDirectorySync(),this.config,this.id,this.logger,this.gitSync);rL0(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return oL0(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 KP({...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){gL0(A,this.requireDirectorySync(),this.logger)}}function LZ(A={}){return new PHA(A)}B0();B0();GA();GA();var aL0=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional()}),layouts:Z.record(Z.any()),themeCSS:Z.string().optional()}),uyQ=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});import{render as L_0}from"preact-render-to-string";import{h as rZ}from"preact";class _HA{headProps=null;defaultTitle;constructor(A){this.defaultTitle=A}setHeadProps(A){this.headProps??=A}getHeadProps(){return this.headProps}reset(){this.headProps=null}generateHeadHTML(){let A=[];if(A.push('<meta charset="UTF-8">'),A.push('<meta name="viewport" content="width=device-width, initial-scale=1.0">'),A.push('<meta http-equiv="X-UA-Compatible" content="IE=edge">'),A.push('<link rel="icon" type="image/svg+xml" href="/favicon.svg">'),A.push('<link rel="icon" type="image/png" href="/favicon.png">'),A.push('<link rel="stylesheet" href="/styles/main.css">'),!this.headProps)return A.push(`<title>${this.escapeHtml(this.defaultTitle)}</title>`),A.join(`
|
|
1706
1707
|
`);let{title:Q,description:B,ogImage:w,ogType:$,twitterCard:D,canonicalUrl:Y}=this.headProps;if(A.push(`<title>${this.escapeHtml(Q)}</title>`),B)A.push(`<meta name="description" content="${this.escapeHtml(B)}">`);if(A.push(`<meta property="og:title" content="${this.escapeHtml(Q)}">`),B)A.push(`<meta property="og:description" content="${this.escapeHtml(B)}">`);if(A.push(`<meta property="og:type" content="${$??"website"}">`),w)A.push(`<meta property="og:image" content="${this.escapeHtml(w)}">`);if(A.push(`<meta name="twitter:card" content="${D??"summary_large_image"}">`),A.push(`<meta name="twitter:title" content="${this.escapeHtml(Q)}">`),B)A.push(`<meta name="twitter:description" content="${this.escapeHtml(B)}">`);if(w)A.push(`<meta name="twitter:image" content="${this.escapeHtml(w)}">`);if(Y)A.push(`<link rel="canonical" href="${this.escapeHtml(Y)}">`);return A.join(`
|
|
1707
1708
|
`)}escapeHtml(A){let Q={"&":"&","<":"<",">":">",'"':""","'":"'"};return A.replace(/[&<>"']/g,(B)=>Q[B]??B)}}function tL0(A){var Q,B,w="";if(typeof A=="string"||typeof A=="number")w+=A;else if(typeof A=="object")if(Array.isArray(A)){var $=A.length;for(Q=0;Q<$;Q++)A[Q]&&(B=tL0(A[Q]))&&(w&&(w+=" "),w+=B)}else for(B in A)A[B]&&(w&&(w+=" "),w+=B);return w}function il(){for(var A,Q,B=0,w="",$=arguments.length;B<$;B++)(A=arguments[B])&&(Q=tL0(A))&&(w&&(w+=" "),w+=Q);return w}var n62=(A)=>{let Q=s62(A),{conflictingClassGroups:B,conflictingClassGroupModifiers:w}=A;return{getClassGroupId:(Y)=>{let I=Y.split("-");if(I[0]===""&&I.length!==1)I.shift();return wM0(I,Q)||o62(Y)},getConflictingClassGroupIds:(Y,I)=>{let X=B[Y]||[];if(I&&w[Y])return[...X,...w[Y]];return X}}},wM0=(A,Q)=>{if(A.length===0)return Q.classGroupId;let B=A[0],w=Q.nextPart.get(B),$=w?wM0(A.slice(1),w):void 0;if($)return $;if(Q.validators.length===0)return;let D=A.join("-");return Q.validators.find(({validator:Y})=>Y(D))?.classGroupId},eL0=/^\[(.+)\]$/,o62=(A)=>{if(eL0.test(A)){let Q=eL0.exec(A)[1],B=Q?.substring(0,Q.indexOf(":"));if(B)return"arbitrary.."+B}},s62=(A)=>{let{theme:Q,prefix:B}=A,w={nextPart:new Map,validators:[]};return t62(Object.entries(A.classGroups),B).forEach(([D,Y])=>{xHA(Y,w,D,Q)}),w},xHA=(A,Q,B,w)=>{A.forEach(($)=>{if(typeof $==="string"){let D=$===""?Q:AM0(Q,$);D.classGroupId=B;return}if(typeof $==="function"){if(a62($)){xHA($(w),Q,B,w);return}Q.validators.push({validator:$,classGroupId:B});return}Object.entries($).forEach(([D,Y])=>{xHA(Y,AM0(Q,D),B,w)})})},AM0=(A,Q)=>{let B=A;return Q.split("-").forEach((w)=>{if(!B.nextPart.has(w))B.nextPart.set(w,{nextPart:new Map,validators:[]});B=B.nextPart.get(w)}),B},a62=(A)=>A.isThemeGetter,t62=(A,Q)=>{if(!Q)return A;return A.map(([B,w])=>{let $=w.map((D)=>{if(typeof D==="string")return Q+D;if(typeof D==="object")return Object.fromEntries(Object.entries(D).map(([Y,I])=>[Q+Y,I]));return D});return[B,$]})},e62=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,B=new Map,w=new Map,$=(D,Y)=>{if(B.set(D,Y),Q++,Q>A)Q=0,w=B,B=new Map};return{get(D){let Y=B.get(D);if(Y!==void 0)return Y;if((Y=w.get(D))!==void 0)return $(D,Y),Y},set(D,Y){if(B.has(D))B.set(D,Y);else $(D,Y)}}};var A52=(A)=>{let{separator:Q,experimentalParseClassName:B}=A,w=Q.length===1,$=Q[0],D=Q.length,Y=(I)=>{let X=[],H=0,W=0,J;for(let L=0;L<I.length;L++){let k=I[L];if(H===0){if(k===$&&(w||I.slice(L,L+D)===Q)){X.push(I.slice(W,L)),W=L+D;continue}if(k==="/"){J=L;continue}}if(k==="[")H++;else if(k==="]")H--}let F=X.length===0?I:I.substring(W),z=F.startsWith("!"),V=z?F.substring(1):F,E=J&&J>W?J-W:void 0;return{modifiers:X,hasImportantModifier:z,baseClassName:V,maybePostfixModifierPosition:E}};if(B)return(I)=>B({className:I,parseClassName:Y});return Y},Q52=(A)=>{if(A.length<=1)return A;let Q=[],B=[];return A.forEach((w)=>{if(w[0]==="[")Q.push(...B.sort(),w),B=[];else B.push(w)}),Q.push(...B.sort()),Q},B52=(A)=>({cache:e62(A.cacheSize),parseClassName:A52(A),...n62(A)}),w52=/\s+/,$52=(A,Q)=>{let{parseClassName:B,getClassGroupId:w,getConflictingClassGroupIds:$}=Q,D=[],Y=A.trim().split(w52),I="";for(let X=Y.length-1;X>=0;X-=1){let H=Y[X],{modifiers:W,hasImportantModifier:J,baseClassName:F,maybePostfixModifierPosition:z}=B(H),V=Boolean(z),E=w(V?F.substring(0,z):F);if(!E){if(!V){I=H+(I.length>0?" "+I:I);continue}if(E=w(F),!E){I=H+(I.length>0?" "+I:I);continue}V=!1}let L=Q52(W).join(":"),k=J?L+"!":L,_=k+E;if(D.includes(_))continue;D.push(_);let j=$(E,V);for(let r=0;r<j.length;++r){let n=j[r];D.push(k+n)}I=H+(I.length>0?" "+I:I)}return I};function D52(){let A=0,Q,B,w="";while(A<arguments.length)if(Q=arguments[A++]){if(B=$M0(Q))w&&(w+=" "),w+=B}return w}var $M0=(A)=>{if(typeof A==="string")return A;let Q,B="";for(let w=0;w<A.length;w++)if(A[w]){if(Q=$M0(A[w]))B&&(B+=" "),B+=Q}return B};function QM0(A,...Q){let B,w,$,D=Y;function Y(X){let H=Q.reduce((W,J)=>J(W),A());return B=B52(H),w=B.cache.get,$=B.cache.set,D=I,I(X)}function I(X){let H=w(X);if(H)return H;let W=$52(X,B);return $(X,W),W}return function(){return D(D52.apply(null,arguments))}}var L8=(A)=>{let Q=(B)=>B[A]||[];return Q.isThemeGetter=!0,Q},DM0=/^\[(?:([a-z-]+):)?(.+)\]$/i,Y52=/^\d+\/\d+$/,I52=new Set(["px","full","screen"]),X52=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,H52=/\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$/,K52=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,U52=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,W52=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,PK=(A)=>UM(A)||I52.has(A)||Y52.test(A),TG=(A)=>WM(A,"length",V52),UM=(A)=>Boolean(A)&&!Number.isNaN(Number(A)),bHA=(A)=>WM(A,"number",UM),LP=(A)=>Boolean(A)&&Number.isInteger(Number(A)),G52=(A)=>A.endsWith("%")&&UM(A.slice(0,-1)),IQ=(A)=>DM0.test(A),vG=(A)=>X52.test(A),J52=new Set(["length","size","percentage"]),F52=(A)=>WM(A,J52,YM0),Z52=(A)=>WM(A,"position",YM0),z52=new Set(["image","url"]),q52=(A)=>WM(A,z52,M52),N52=(A)=>WM(A,"",L52),MP=()=>!0,WM=(A,Q,B)=>{let w=DM0.exec(A);if(w){if(w[1])return typeof Q==="string"?w[1]===Q:Q.has(w[1]);return B(w[2])}return!1},V52=(A)=>H52.test(A)&&!K52.test(A),YM0=()=>!1,L52=(A)=>U52.test(A),M52=(A)=>W52.test(A);var BM0=()=>{let A=L8("colors"),Q=L8("spacing"),B=L8("blur"),w=L8("brightness"),$=L8("borderColor"),D=L8("borderRadius"),Y=L8("borderSpacing"),I=L8("borderWidth"),X=L8("contrast"),H=L8("grayscale"),W=L8("hueRotate"),J=L8("invert"),F=L8("gap"),z=L8("gradientColorStops"),V=L8("gradientColorStopPositions"),E=L8("inset"),L=L8("margin"),k=L8("opacity"),_=L8("padding"),j=L8("saturate"),r=L8("scale"),n=L8("sepia"),g=L8("skew"),T=L8("space"),S=L8("translate"),h=()=>["auto","contain","none"],t=()=>["auto","hidden","clip","visible","scroll"],c=()=>["auto",IQ,Q],UA=()=>[IQ,Q],IA=()=>["",PK,TG],P=()=>["auto",UM,IQ],R=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],b=()=>["solid","dashed","dotted","double","none"],s=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],d=()=>["start","end","center","between","around","evenly","stretch"],e=()=>["","0",IQ],i=()=>["auto","avoid","all","avoid-page","page","left","right","column"],KA=()=>[UM,IQ];return{cacheSize:500,separator:":",theme:{colors:[MP],spacing:[PK,TG],blur:["none","",vG,IQ],brightness:KA(),borderColor:[A],borderRadius:["none","","full",vG,IQ],borderSpacing:UA(),borderWidth:IA(),contrast:KA(),grayscale:e(),hueRotate:KA(),invert:e(),gap:UA(),gradientColorStops:[A],gradientColorStopPositions:[G52,TG],inset:c(),margin:c(),opacity:KA(),padding:UA(),saturate:KA(),scale:KA(),sepia:e(),skew:KA(),space:UA(),translate:UA()},classGroups:{aspect:[{aspect:["auto","square","video",IQ]}],container:["container"],columns:[{columns:[vG]}],"break-after":[{"break-after":i()}],"break-before":[{"break-before":i()}],"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:[...R(),IQ]}],overflow:[{overflow:t()}],"overflow-x":[{"overflow-x":t()}],"overflow-y":[{"overflow-y":t()}],overscroll:[{overscroll:h()}],"overscroll-x":[{"overscroll-x":h()}],"overscroll-y":[{"overscroll-y":h()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[E]}],"inset-x":[{"inset-x":[E]}],"inset-y":[{"inset-y":[E]}],start:[{start:[E]}],end:[{end:[E]}],top:[{top:[E]}],right:[{right:[E]}],bottom:[{bottom:[E]}],left:[{left:[E]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",LP,IQ]}],basis:[{basis:c()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",IQ]}],grow:[{grow:e()}],shrink:[{shrink:e()}],order:[{order:["first","last","none",LP,IQ]}],"grid-cols":[{"grid-cols":[MP]}],"col-start-end":[{col:["auto",{span:["full",LP,IQ]},IQ]}],"col-start":[{"col-start":P()}],"col-end":[{"col-end":P()}],"grid-rows":[{"grid-rows":[MP]}],"row-start-end":[{row:["auto",{span:[LP,IQ]},IQ]}],"row-start":[{"row-start":P()}],"row-end":[{"row-end":P()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",IQ]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",IQ]}],gap:[{gap:[F]}],"gap-x":[{"gap-x":[F]}],"gap-y":[{"gap-y":[F]}],"justify-content":[{justify:["normal",...d()]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal",...d(),"baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[...d(),"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":[T]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[T]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",IQ,Q]}],"min-w":[{"min-w":[IQ,Q,"min","max","fit"]}],"max-w":[{"max-w":[IQ,Q,"none","full","min","max","fit","prose",{screen:[vG]},vG]}],h:[{h:[IQ,Q,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[IQ,Q,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[IQ,Q,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[IQ,Q,"auto","min","max","fit"]}],"font-size":[{text:["base",vG,TG]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",bHA]}],"font-family":[{font:[MP]}],"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",IQ]}],"line-clamp":[{"line-clamp":["none",UM,bHA]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",PK,IQ]}],"list-image":[{"list-image":["none",IQ]}],"list-style-type":[{list:["none","disc","decimal",IQ]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[A]}],"placeholder-opacity":[{"placeholder-opacity":[k]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[A]}],"text-opacity":[{"text-opacity":[k]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...b(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",PK,TG]}],"underline-offset":[{"underline-offset":["auto",PK,IQ]}],"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:UA()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",IQ]}],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",IQ]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[k]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...R(),Z52]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",F52]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},q52]}],"bg-color":[{bg:[A]}],"gradient-from-pos":[{from:[V]}],"gradient-via-pos":[{via:[V]}],"gradient-to-pos":[{to:[V]}],"gradient-from":[{from:[z]}],"gradient-via":[{via:[z]}],"gradient-to":[{to:[z]}],rounded:[{rounded:[D]}],"rounded-s":[{"rounded-s":[D]}],"rounded-e":[{"rounded-e":[D]}],"rounded-t":[{"rounded-t":[D]}],"rounded-r":[{"rounded-r":[D]}],"rounded-b":[{"rounded-b":[D]}],"rounded-l":[{"rounded-l":[D]}],"rounded-ss":[{"rounded-ss":[D]}],"rounded-se":[{"rounded-se":[D]}],"rounded-ee":[{"rounded-ee":[D]}],"rounded-es":[{"rounded-es":[D]}],"rounded-tl":[{"rounded-tl":[D]}],"rounded-tr":[{"rounded-tr":[D]}],"rounded-br":[{"rounded-br":[D]}],"rounded-bl":[{"rounded-bl":[D]}],"border-w":[{border:[I]}],"border-w-x":[{"border-x":[I]}],"border-w-y":[{"border-y":[I]}],"border-w-s":[{"border-s":[I]}],"border-w-e":[{"border-e":[I]}],"border-w-t":[{"border-t":[I]}],"border-w-r":[{"border-r":[I]}],"border-w-b":[{"border-b":[I]}],"border-w-l":[{"border-l":[I]}],"border-opacity":[{"border-opacity":[k]}],"border-style":[{border:[...b(),"hidden"]}],"divide-x":[{"divide-x":[I]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[I]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[k]}],"divide-style":[{divide:b()}],"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:["",...b()]}],"outline-offset":[{"outline-offset":[PK,IQ]}],"outline-w":[{outline:[PK,TG]}],"outline-color":[{outline:[A]}],"ring-w":[{ring:IA()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[A]}],"ring-opacity":[{"ring-opacity":[k]}],"ring-offset-w":[{"ring-offset":[PK,TG]}],"ring-offset-color":[{"ring-offset":[A]}],shadow:[{shadow:["","inner","none",vG,N52]}],"shadow-color":[{shadow:[MP]}],opacity:[{opacity:[k]}],"mix-blend":[{"mix-blend":[...s(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":s()}],filter:[{filter:["","none"]}],blur:[{blur:[B]}],brightness:[{brightness:[w]}],contrast:[{contrast:[X]}],"drop-shadow":[{"drop-shadow":["","none",vG,IQ]}],grayscale:[{grayscale:[H]}],"hue-rotate":[{"hue-rotate":[W]}],invert:[{invert:[J]}],saturate:[{saturate:[j]}],sepia:[{sepia:[n]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[B]}],"backdrop-brightness":[{"backdrop-brightness":[w]}],"backdrop-contrast":[{"backdrop-contrast":[X]}],"backdrop-grayscale":[{"backdrop-grayscale":[H]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[W]}],"backdrop-invert":[{"backdrop-invert":[J]}],"backdrop-opacity":[{"backdrop-opacity":[k]}],"backdrop-saturate":[{"backdrop-saturate":[j]}],"backdrop-sepia":[{"backdrop-sepia":[n]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[Y]}],"border-spacing-x":[{"border-spacing-x":[Y]}],"border-spacing-y":[{"border-spacing-y":[Y]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",IQ]}],duration:[{duration:KA()}],ease:[{ease:["linear","in","out","in-out",IQ]}],delay:[{delay:KA()}],animate:[{animate:["none","spin","ping","pulse","bounce",IQ]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[r]}],"scale-x":[{"scale-x":[r]}],"scale-y":[{"scale-y":[r]}],rotate:[{rotate:[LP,IQ]}],"translate-x":[{"translate-x":[S]}],"translate-y":[{"translate-y":[S]}],"skew-x":[{"skew-x":[g]}],"skew-y":[{"skew-y":[g]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",IQ]}],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",IQ]}],"caret-color":[{caret:[A]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":UA()}],"scroll-mx":[{"scroll-mx":UA()}],"scroll-my":[{"scroll-my":UA()}],"scroll-ms":[{"scroll-ms":UA()}],"scroll-me":[{"scroll-me":UA()}],"scroll-mt":[{"scroll-mt":UA()}],"scroll-mr":[{"scroll-mr":UA()}],"scroll-mb":[{"scroll-mb":UA()}],"scroll-ml":[{"scroll-ml":UA()}],"scroll-p":[{"scroll-p":UA()}],"scroll-px":[{"scroll-px":UA()}],"scroll-py":[{"scroll-py":UA()}],"scroll-ps":[{"scroll-ps":UA()}],"scroll-pe":[{"scroll-pe":UA()}],"scroll-pt":[{"scroll-pt":UA()}],"scroll-pr":[{"scroll-pr":UA()}],"scroll-pb":[{"scroll-pb":UA()}],"scroll-pl":[{"scroll-pl":UA()}],"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",IQ]}],fill:[{fill:[A,"none"]}],"stroke-w":[{stroke:[PK,TG,bHA]}],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"]}}},E52=(A,{cacheSize:Q,prefix:B,separator:w,experimentalParseClassName:$,extend:D={},override:Y={}})=>{EP(A,"cacheSize",Q),EP(A,"prefix",B),EP(A,"separator",w),EP(A,"experimentalParseClassName",$);for(let I in Y)C52(A[I],Y[I]);for(let I in D)O52(A[I],D[I]);return A},EP=(A,Q,B)=>{if(B!==void 0)A[Q]=B},C52=(A,Q)=>{if(Q)for(let B in Q)EP(A,B,Q[B])},O52=(A,Q)=>{if(Q)for(let B in Q){let w=Q[B];if(w!==void 0)A[B]=(A[B]||[]).concat(w)}},IM0=(A,...Q)=>typeof A==="function"?QM0(BM0,A,...Q):QM0(()=>E52(BM0(),A),...Q);var f52=IM0({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 g1(...A){return f52(il(A))}var XM0=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,HM0=il,mB=(A,Q)=>(B)=>{var w;if((Q===null||Q===void 0?void 0:Q.variants)==null)return HM0(A,B===null||B===void 0?void 0:B.class,B===null||B===void 0?void 0:B.className);let{variants:$,defaultVariants:D}=Q,Y=Object.keys($).map((H)=>{let W=B===null||B===void 0?void 0:B[H],J=D===null||D===void 0?void 0:D[H];if(W===null)return null;let F=XM0(W)||XM0(J);return $[H][F]}),I=B&&Object.entries(B).reduce((H,W)=>{let[J,F]=W;if(F===void 0)return H;return H[J]=F,H},{}),X=Q===null||Q===void 0?void 0:(w=Q.compoundVariants)===null||w===void 0?void 0:w.reduce((H,W)=>{let{class:J,className:F,...z}=W;return Object.entries(z).every((V)=>{let[E,L]=V;return Array.isArray(L)?L.includes({...D,...I}[E]):{...D,...I}[E]===L})?[...H,J,F]:H},[]);return HM0(A,Y,X,B===null||B===void 0?void 0:B.class,B===null||B===void 0?void 0:B.className)};import{jsxDEV as THA}from"preact/jsx-dev-runtime";var KM0=mB("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 vHA({variant:A,title:Q,children:B,className:w}){return THA("div",{className:g1(KM0({variant:A}),w),role:"alert",children:[Q&&THA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),THA("div",{className:g1(Q&&"mt-1","text-sm text-current opacity-75"),children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as R52}from"preact/jsx-dev-runtime";var UM0=mB("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 MZ({variant:A,size:Q,className:B,children:w,ssrOnClick:$,type:D="button",...Y}){return R52("button",{type:D,className:g1(UM0({variant:A,size:Q}),B),...Y,...$&&{onclick:$},children:w},void 0,!1,void 0,this)}import{jsxDEV as j52}from"preact/jsx-dev-runtime";var WM0=mB("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 J5({href:A,children:Q,variant:B,size:w,external:$=!1,className:D,"aria-label":Y}){let I=$?{target:"_blank",rel:"noopener noreferrer"}:{};return j52("a",{href:A,className:g1(WM0({variant:B,size:w}),D),"aria-label":Y,...I,children:Q},void 0,!1,void 0,this)}import{jsxDEV as rl}from"preact/jsx-dev-runtime";var GM0=mB("rounded-full transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2",{variants:{variant:{default:"bg-theme-muted/50 hover:bg-theme-muted text-theme",light:"bg-theme-subtle hover:bg-theme-muted text-theme",dark:"bg-theme-dark hover:bg-theme-muted text-theme-inverse",footer:"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"}}),k52={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function GM({variant:A,size:Q,className:B}){let w=k52[Q??"md"];return rl("button",{onclick:"toggleTheme()",type:"button",className:g1(GM0({variant:A,size:Q}),B),"aria-label":"Toggle dark mode",children:rl("svg",{className:g1(w,"transition-colors"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[rl("path",{className:"sun-icon",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,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),rl("path",{className:"moon-icon",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z",transform:"rotate(45 12 12)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as SHA}from"preact/jsx-dev-runtime";var JM0=mB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function nl({items:A,className:Q,linkClassName:B="hover:text-accent transition-colors",orientation:w,children:$}){if(A.length===0&&!$)return null;let D=[...A].sort((Y,I)=>Y.priority-I.priority);return SHA("ul",{className:g1(JM0({orientation:w}),Q),children:[D.map((Y)=>SHA("li",{children:SHA("a",{href:Y.href,className:B,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as qmQ}from"preact/jsx-dev-runtime";import{jsxDEV as LmQ}from"preact/jsx-dev-runtime";GA();GA();import{createContext as P52,h as _52}from"preact";import{useContext as b52}from"preact/hooks";var FM0=P52(null);function ol({imageRenderer:A,children:Q}){return _52(FM0.Provider,{value:A??null},Q)}function ZM0(){return b52(FM0)}function EZ(){let A=ZM0();return(Q)=>lT(Q,A?{imageRenderer:A}:void 0)}import{jsxDEV as _K}from"preact/jsx-dev-runtime";var hHA=({markdown:A})=>{let Q=EZ(),w=A.split(/^---$/gm).map((Y)=>Y.trim()).map((Y)=>{let{attributes:I,markdown:X}=Uv(Y),H=Wv(X),W;if(H)W=`<div class="slide-columns">${H.map((F)=>`<div class="slide-column">${KO(Q(F.trim()))}</div>`).join("")}</div>`;else W=KO(Q(X));return{attributes:I,htmlContent:W}}),$=w.some((Y)=>Y.htmlContent.includes('class="mermaid"')),D=w.map(({attributes:Y,htmlContent:I},X)=>_K("section",{...Y,dangerouslySetInnerHTML:{__html:I}},X,!1,void 0,this));return _K("section",{className:"presentation-section",children:[_K("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),_K("div",{className:"reveal",children:_K("div",{className:"slides",children:D},void 0,!1,void 0,this)},void 0,!1,void 0,this),_K("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),$&&_K("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),_K("script",{dangerouslySetInnerHTML:{__html:`
|
|
1708
1709
|
window.addEventListener('DOMContentLoaded', () => {
|
|
@@ -2420,7 +2421,7 @@ ${Q.join(`
|
|
|
2420
2421
|
`+$:B,Y=OX(this.outputDir,"styles","main.css");await this.cssProcessor.process(D,Y,this.workingDir,this.outputDir,this.logger);let I=await gw.readFile(Y,"utf-8"),X=w.length>0?w:Q;if(X.length>0){let H=X.join(`
|
|
2421
2422
|
`)+`
|
|
2422
2423
|
|
|
2423
|
-
`+I;await gw.writeFile(Y,H,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=OX(process.cwd(),"public");try{await gw.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await gw.readdir(A,{withFileTypes:!0});for(let B of Q){let w=OX(A,B.name),$=OX(this.outputDir,B.name);if(B.isDirectory())await this.copyDirectory(w,$);else await gw.copyFile(w,$),this.logger.debug(`Copied static asset: ${B.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([B,w])=>{let $=B.startsWith("/")?B.slice(1):B,D=OX(this.outputDir,$);await gw.mkdir(sW2(D),{recursive:!0}),await gw.writeFile(D,w,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await gw.mkdir(Q,{recursive:!0});let B=await gw.readdir(A,{withFileTypes:!0});for(let w of B){let $=OX(A,w.name),D=OX(Q,w.name);if(w.isDirectory())await this.copyDirectory($,D);else await gw.copyFile($,D)}}}function zWA(A){return new M_0(A)}function aW2(A,Q){let B=new Map;for(let w of A.sections){let $=Q.getViewTemplate(w.template);if(!$?.runtimeScripts)continue;for(let D of $.runtimeScripts)if(!B.has(D.src))B.set(D.src,D)}return[...B.values()].map((w)=>{let $=[`src="${w.src}"`];if(w.defer)$.push("defer");if(w.module)$.push('type="module"');return`<script ${$.join(" ")}></script>`})}import{join as CZ2}from"path";GA();class qWA{context;routeRegistry;entityDisplay;constructor(A,Q,B){this.context=A;this.routeRegistry=Q;this.entityDisplay=B}async generateEntityRoutes(){let A=this.context.logger.child("DynamicRouteGenerator"),Q=this.routeRegistry.list(),B=0;for(let $ of Q)if($.sourceEntityType)this.routeRegistry.unregister($.path),B++;if(B>0)A.debug(`Cleared ${B} dynamic routes before regeneration`);let w=this.context.entityService.getEntityTypes();A.debug(`Found ${w.length} entity types`,{entityTypes:w});for(let $ of w)await this.generateRoutesForEntityType($)}async generateRoutesForEntityType(A){let Q=this.context.logger.child("DynamicRouteGenerator"),{listTemplateName:B,detailTemplateName:w}=this.findTemplatesForEntityType(A);if(!B&&!w){Q.debug(`No matching templates found for entity type: ${A}`);return}if(Q.debug(`Generating routes for entity type: ${A}`,{listTemplate:B,detailTemplate:w}),B){let{pluralName:$,label:D,layout:Y,paginate:I,pageSize:X,navigation:H}=this.getEntityDisplayConfig(A);if(I)await this.generatePaginatedRoutes(A,B,$,D,Y,X,H,Q);else{let W={id:`${A}-index`,path:`/${$}`,title:D,description:`Browse all ${$}`,...Y&&{layout:Y},navigation:{show:H.show,label:D,slot:H.slot,priority:H.priority},sections:[{id:"list",template:B,dataQuery:{entityType:A,query:{limit:100}}}],sourceEntityType:A};try{this.routeRegistry.register(W),Q.debug(`Registered index route for ${A}`,{path:W.path})}catch(J){Q.warn(`Failed to register index route for ${A}`,{error:J})}}}if(w)try{let $=await this.context.entityService.listEntities(A,{limit:1000});Q.debug(`Found ${$.length} ${A} entities to generate routes for`);let{pluralName:D,layout:Y}=this.getEntityDisplayConfig(A);for(let X of $){let H="slug"in X.metadata?X.metadata.slug:X.id,W={id:`${A}-${X.id}`,path:`/${D}/${H}`,title:`${this.capitalize(A)}: ${H}`,description:`View ${A} details`,...Y&&{layout:Y},sections:[{id:"detail",template:w,dataQuery:{entityType:A,query:{id:H}}}],sourceEntityType:A};try{this.routeRegistry.register(W)}catch(J){Q.warn(`Failed to register detail route for ${A}/${X.id}`,{error:J})}}let I=B?$.length+1:$.length;Q.debug(`Successfully registered ${I} routes for ${A}`)}catch($){Q.error(`Failed to list entities for type: ${A}`,{error:$})}}async generatePaginatedRoutes(A,Q,B,w,$,D,Y,I){let H=(await this.context.entityService.listEntities(A,{limit:1000})).length,W=Math.max(1,Math.ceil(H/D));I.debug(`Generating ${W} paginated routes for ${A}`,{totalItems:H,pageSize:D});for(let J=1;J<=W;J++){let F=J===1,z=F?`/${B}`:`/${B}/page/${J}`,V={id:`${A}-index${F?"":`-page-${J}`}`,path:z,title:F?w:`${w} - Page ${J}`,description:`Browse all ${B}${F?"":` - Page ${J}`}`,...$&&{layout:$},navigation:F?{show:Y.show,label:w,slot:Y.slot,priority:Y.priority}:void 0,sections:[{id:"list",template:Q,dataQuery:{entityType:A,query:{page:J,pageSize:D,baseUrl:`/${B}`}}}],sourceEntityType:A};try{this.routeRegistry.register(V),I.debug(`Registered paginated route for ${A}`,{path:V.path,page:J})}catch(E){I.warn(`Failed to register paginated route for ${A} page ${J}`,{error:E})}}}findTemplatesForEntityType(A){let Q=this.context.views.list(),B,w,$=`${A}-list`,D=`${A}-detail`;for(let I of Q){let X=I.name;if(X.endsWith($)){let H=X.slice(0,-$.length);if(H===""||H.endsWith(":"))B=X}if(X.endsWith(D)){let H=X.slice(0,-D.length);if(H===""||H.endsWith(":"))w=X}}let Y={};if(B)Y.listTemplateName=B;if(w)Y.detailTemplateName=w;return Y}getEntityDisplayConfig(A){let Q=this.entityDisplay?.[A],B=10,w=!0,$=!0,D="primary",Y=40;if(Q){let X=Q.pluralName??C$(Q.label.toLowerCase()),H=this.capitalize(C$(Q.label.toLowerCase()));return{pluralName:X,label:H,...Q.layout&&{layout:Q.layout},paginate:Q.paginate??!0,pageSize:Q.pageSize??10,navigation:{show:Q.navigation?.show??!0,slot:Q.navigation?.slot??"primary",priority:Q.navigation?.priority??40}}}let I=C$(A);return{pluralName:I,label:this.capitalize(I),paginate:!0,pageSize:10,navigation:{show:!0,slot:"primary",priority:40}}}capitalize(A){return A.split(" ").map((Q)=>Q.charAt(0).toUpperCase()+Q.slice(1)).join(" ")}}B0();GA();B0();var E_0=Z.object({}),j_=U2.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:E_0}),k_=Z.object({heading:Z.string().describe("Main CTA heading text"),buttonText:Z.string().describe("Call-to-action button text"),buttonLink:Z.string().describe("URL or anchor for the CTA button")}),fX=Z.object({title:Z.string().describe("The site's title"),description:Z.string().describe("The site's description"),copyright:Z.string().optional().describe("Copyright notice text"),logo:Z.boolean().optional().describe("Whether to display logo instead of title text in header"),themeMode:Z.enum(["light","dark"]).optional().describe("Default theme mode"),cta:k_.optional().describe("Call-to-action configuration")});B0();class uY extends E2{constructor(){super({entityType:"site-info",schema:j_,frontmatterSchema:fX,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=fX.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}toMarkdown(A){return A.content}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",Q)}}class RX{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,B){return RX.instance??=new RX(A,Q,B),RX.instance}static resetInstance(){RX.instance=null}static createFresh(A,Q,B){return new RX(A,Q,B)}constructor(A,Q,B){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new uY;let w=RX.getDefaultSiteInfo();this.defaultSiteInfo={...w,...B}}async initialize(){try{if(!await this.entityService.getEntity("site-info","site-info")){this.logger.info("No site info found, creating default site info");let Q=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({id:"site-info",entityType:"site-info",content:Q,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("site-info","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 tW2=new uY;class hd{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,B){let{entityService:w}=B,$;try{let I=await w.getEntity("site-info","site-info");$=I?tW2.parseSiteInfoBody(I.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let D;try{let I=await w.getEntity("anchor-profile","anchor-profile");if(I)D=I.metadata.socialLinks}catch{}let Y={...$,socialLinks:D,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var C_0={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.37",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/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 AG2=new uY;class NWA extends HQ{entityType="site-info";schema=j_;adapter=AG2;defaultSiteInfo;constructor(A){super("site-info",C_0);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new hd(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=RX.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function nZ(A){return new NWA(A)}var QG2=new uY;async function rK(A){let B=(await A.listEntities("site-info",{limit:1}))[0];if(!B)throw Error("Site info not found \u2014 create a site-info entity");return QG2.parseSiteInfoBody(B.content)}GA();var BG2=fX.extend({navigation:Z.object({primary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()})),secondary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}))}),copyright:Z.string(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});async function O_0(A,Q,B){let w;try{w=await rK(A)}catch{w={title:"Brain",description:"A knowledge management system"}}let $=Q.getProfile(),D=B.getNavigationItems("primary"),Y=B.getNavigationItems("secondary");return{...w,socialLinks:$.socialLinks,navigation:{primary:D,secondary:Y},copyright:w.copyright??"Powered by Rizom"}}GA();GA();import{promises as ox0}from"fs";import{join as EZ2}from"path";import{createHash as qZ2}from"crypto";import{promises as iWA}from"fs";import{join as dx0}from"path";var ix0=null;async function NZ2(){return ix0??=Promise.resolve().then(() => o0(px0(),1)).then((A)=>A.default),ix0}var VZ2=[480,960,1920],LZ2=80,MZ2="(max-width: 640px) 480px, (max-width: 1280px) 960px, 1920px";class rWA{imagesDir;logger;constructor(A,Q){this.imagesDir=A;this.logger=Q.child("ImageOptimizer")}async optimize(A,Q){try{let B=await NZ2(),w=qZ2("sha256").update(A).digest("hex").slice(0,16),$=await B(A).metadata();if(!$.width||!$.height)return this.logger.warn("Could not determine image dimensions",{originalUrl:Q}),null;let{width:D,height:Y}=$,I=[];for(let J of VZ2){if(J>D)continue;let F=`${w}-${J}w.webp`,z=dx0(this.imagesDir,F),V=`/images/${F}`;if(await iWA.access(z).then(()=>!0).catch(()=>!1)){this.logger.debug("Cache hit, skipping optimization",{fileName:F}),I.push({width:J,url:V});continue}await B(A).resize(J,null,{withoutEnlargement:!0}).webp({quality:LZ2}).toFile(z),I.push({width:J,url:V}),this.logger.debug("Created WebP variant",{fileName:F,width:J})}if(I.length===0)return null;let X=I[I.length-1];if(!X)return null;let H=I.find((J)=>J.width===960)??X,W=Math.round(Y*(H.width/D));return{src:H.url,srcset:I.map((J)=>`${J.url} ${J.width}w`).join(", "),sizes:MZ2,width:H.width,height:W}}catch(B){return this.logger.warn("Image optimization failed, using original",{originalUrl:Q,error:B instanceof Error?B.message:String(B)}),null}}async optimizeAll(){let A={},Q;try{Q=await iWA.readdir(this.imagesDir,{withFileTypes:!0})}catch{return this.logger.debug("Images directory does not exist, nothing to optimize"),A}let B=Q.filter((w)=>w.isFile()&&/\.(png|jpe?g)$/i.test(w.name));if(B.length===0)return this.logger.debug("No PNG/JPEG images found to optimize"),A;this.logger.debug(`Optimizing ${B.length} images`);for(let w of B){let $=dx0(this.imagesDir,w.name),D=`/images/${w.name}`;try{let Y=await iWA.readFile($),I=await this.optimize(Y,D);if(I)A[D]=I}catch(Y){this.logger.warn("Failed to optimize image",{file:w.name,error:Y instanceof Error?Y.message:String(Y)})}}return this.logger.debug(`Optimized ${Object.keys(A).length}/${B.length} images`),A}}function rx0(A,Q){if(A.format)return A.format;return Q.match(/^data:image\/([^;]+);/)?.[1]??"png"}function nx0(A){return A.match(/^data:image\/[^;]+;base64,(.+)$/)?.[1]??null}function iM(A){return A.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}class nWA{entityService;logger;imageMap={};imagesDir;optimizer;constructor(A,Q,B){this.entityService=A;this.logger=Q.child("ImageBuildService"),this.imagesDir=B,this.optimizer=new rWA(this.imagesDir,this.logger)}async resolveAll(A){let Q=[...new Set(A)];if(Q.length===0)return;await ox0.mkdir(this.imagesDir,{recursive:!0});let B=O3(4);await Promise.all(Q.map((w)=>B(async()=>{try{await this.resolveImage(w)}catch($){this.logger.warn("Failed to resolve image",{imageId:w,error:$ instanceof Error?$.message:String($)})}}))),this.logger.debug(`Resolved ${Object.keys(this.imageMap).length}/${Q.length} images`)}async resolveImage(A){let Q=await this.entityService.getEntity("image",A);if(!Q?.content){this.logger.warn("Image entity not found or has no content",{imageId:A});return}let B=nx0(Q.content);if(!B){this.logger.warn("Could not extract base64 from image",{imageId:A});return}let w=Buffer.from(B,"base64"),$=rx0(Q.metadata,Q.content),D=`${A}.${$}`,Y=EZ2(this.imagesDir,D);await ox0.writeFile(Y,w);let I=`/images/${D}`,X=await this.optimizer.optimize(w,I);if(X)this.imageMap[A]={src:X.src,srcset:X.srcset,sizes:X.sizes,width:X.width,height:X.height};else this.imageMap[A]={src:I,width:Q.metadata.width??0,height:Q.metadata.height??0};this.logger.debug("Resolved image",{imageId:A,optimized:Boolean(X)})}get(A){return this.imageMap[A]}getMap(){return this.imageMap}createImageRenderer(){let A=this.imageMap;return(Q,B,w)=>{let $=/^entity:\/\/image\/(.+)$/.exec(Q);if(!$?.[1])return;let D=A[$[1]];if(!D)return;let Y=[`src="${iM(D.src)}"`,`alt="${iM(w)}"`];if(D.srcset)Y.push(`srcset="${iM(D.srcset)}"`);if(D.sizes)Y.push(`sizes="${iM(D.sizes)}"`);if(D.width)Y.push(`width="${D.width}"`);if(D.height)Y.push(`height="${D.height}"`);if(B)Y.push(`title="${iM(B)}"`);return Y.push('loading="lazy"'),Y.push('decoding="async"'),`<img ${Y.join(" ")}>`}}}var OZ2=U2.extend({metadata:Z.object({slug:Z.string()}).passthrough()});class A4{static instance=null;static defaultStaticSiteBuilderFactory=zWA;logger;context;staticSiteBuilderFactory;routeRegistry;profileService;entityDisplay;imageBuildService=null;static setDefaultStaticSiteBuilderFactory(A){A4.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,B,w,$){return A4.instance??=new A4(A,A4.defaultStaticSiteBuilderFactory,Q,B,w,$),A4.instance}static resetInstance(){A4.instance=null}static createFresh(A,Q,B,w,$,D){return new A4(A,$??A4.defaultStaticSiteBuilderFactory,Q,B,w,D)}constructor(A,Q,B,w,$,D){this.logger=A,this.context=B,this.staticSiteBuilderFactory=Q,this.routeRegistry=w,this.profileService=$,this.entityDisplay=D,f7.getInstance().configure(D)}async getSiteInfo(){return O_0(this.context.entityService,this.profileService,this.routeRegistry)}async build(A,Q){let B=aL0.parse(A),w=Lw.from(Q),$=[],D=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await new qWA(this.context,this.routeRegistry,this.entityDisplay).generateEntityRoutes();let I=B.workingDir??CZ2(B.outputDir,".preact-work"),X=this.staticSiteBuilderFactory({logger:this.logger.child("StaticSiteBuilder"),workingDir:I,outputDir:B.outputDir});if(B.cleanBeforeBuild)await X.clean();let H=this.routeRegistry.list();if(H.length===0)D.push("No routes registered for site build");await w?.report({message:`Building ${H.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100}),this.imageBuildService=new nWA(this.context.entityService,this.logger,B.sharedImagesDir);let W=await this.collectAllImageIds();if(W.length>0)await this.imageBuildService.resolveAll(W);let J=B.siteConfig,F={routes:H,pluginContext:this.context,siteConfig:{title:J.title,description:J.description,...J.url&&{url:J.url},...J.copyright&&{copyright:J.copyright},...J.themeMode&&{themeMode:J.themeMode},...J.analyticsScript&&{analyticsScript:J.analyticsScript}},headScripts:A.headScripts,...A.staticAssets&&{staticAssets:A.staticAssets},getContent:async(k,_)=>{let j=B.environment==="production";return this.getContentForSection(_,k,j)},getViewTemplate:(k)=>{return this.context.views.get(k)},layouts:B.layouts,getSiteInfo:async()=>{return this.getSiteInfo()},...B.themeCSS!==void 0&&{themeCSS:B.themeCSS},...A.slots&&{slots:A.slots},imageBuildService:this.imageBuildService},z=0,V=H.length+4;await X.build(F,(k)=>{z++;let _=85+Math.round(z/V*10);w?.report({message:k,progress:_,total:100}).catch(()=>{})}),await w?.report({message:"Site build complete",progress:100,total:100});let E=H.length+1,L={success:$.length===0,outputDir:B.outputDir,filesGenerated:E,routesBuilt:H.length};if($.length>0)L.errors=$;if(D.length>0)L.warnings=D;return L}catch(Y){let I=Error("Site build process failed");return this.logger.error("Site build failed",{error:I,originalError:Y}),$.push(I.message),{success:!1,outputDir:B.outputDir,filesGenerated:0,routesBuilt:0,errors:$}}}async getContentForSection(A,Q,B){if(!A.template)return A.content??null;let w=A.template,$=f7.getInstance();if(A.dataQuery){let Y={dataParams:A.dataQuery,fallback:A.content,publishedOnly:B},I=await this.context.templates.resolve(w,Y);if(I)return this.enrichWithUrls(I,$);return null}let D=await this.context.templates.resolve(w,{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content});if(D)return this.enrichWithUrls(D,$);return null}async enrichWithUrls(A,Q){if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((j)=>this.enrichWithUrls(j,Q)));if(typeof A!=="object")return A;let B=A,w={},$=Object.entries(B),D=await Promise.all($.map(([,j])=>this.enrichWithUrls(j,Q)));for(let j=0;j<$.length;j++){let r=$[j];if(r)w[r[0]]=D[j]}let Y=OZ2.safeParse(B);if(!Y.success)return w;let I=Y.data,X=I.entityType,H=I.metadata.slug,W=this.entityDisplay?.[X],J=W?W.label:X.charAt(0).toUpperCase()+X.slice(1),F=W?W.pluralName??W.label.toLowerCase()+"s":C$(X),z=`/${F}`,V=F.charAt(0).toUpperCase()+F.slice(1),E=$j(I),L=E?this.imageBuildService?.get(E):void 0,k={};if(L)k={coverImageUrl:L.src,coverImageWidth:L.width,coverImageHeight:L.height,...L.srcset&&{coverImageSrcset:L.srcset,coverImageSizes:L.sizes}};else{let j=await Dj(I,this.context.entityService);if(j)k={coverImageUrl:j.url,coverImageWidth:j.width,coverImageHeight:j.height}}return{...w,...I,url:Q.generateUrl(X,H),typeLabel:J,listUrl:z,listLabel:V,...k}}async collectAllImageIds(){let A=new Set;try{let Q=this.context.entityService.getEntityTypes();for(let B of Q){if(B==="image")continue;let w=await this.context.entityService.listEntities(B);for(let $ of w){let D=$j($);if(D)A.add(D)}}}catch(Q){this.logger.warn("Failed to collect image IDs for pre-resolution",{error:Q instanceof Error?Q.message:String(Q)})}return[...A]}}B0();GA();class oWA{logger;routes=new Map;constructor(A){this.logger=A}register(A){for(let Q of SH(A)){let B=FN.parse(Q);if(this.routes.has(B.path)){let w=this.routes.get(B.path);this.logger.debug(`Overriding route "${B.path}" (was registered by plugin "${w?.pluginId}")`)}this.routes.set(B.path,B)}}unregister(A){SH(A).forEach((Q)=>this.routes.delete(Q))}unregisterByPlugin(A){for(let[Q,B]of this.routes.entries())if(B.pluginId===A)this.routes.delete(Q)}get(A){return this.routes.get(A)}list(A){let Q=Array.from(this.routes.values()).filter((B)=>!B.external);if(A?.pluginId)Q=Q.filter((B)=>B.pluginId===A.pluginId);return Q}listByPlugin(A){return this.list({pluginId:A})}clear(){this.routes.clear()}size(){return this.routes.size}getNavigationItems(A){let Q=[];for(let[B,w]of this.routes.entries())if(w.navigation?.show&&w.navigation.slot===A)Q.push({label:w.navigation.label??w.title,href:B,priority:w.navigation.priority});return Q.sort((B,w)=>B.priority-w.priority)}}class Qi{slots=new Map;register(A,Q){let B={...Q,priority:Q.priority??50},w=this.slots.get(A)??[];w.push(B),this.slots.set(A,w)}getSlot(A){return[...this.slots.get(A)??[]].sort((B,w)=>w.priority-B.priority)}hasSlot(A){let Q=this.slots.get(A);return Q!==void 0&&Q.length>0}unregister(A,Q){let B=this.slots.get(A);if(!B)return;let w=B.filter(($)=>$.pluginId!==Q);if(w.length>0)this.slots.set(A,w);else this.slots.delete(A)}unregisterAll(A){for(let[Q,B]of this.slots){let w=B.filter(($)=>$.pluginId!==A);if(w.length>0)this.slots.set(Q,w);else this.slots.delete(Q)}}getSlotNames(){return Array.from(this.slots.keys())}clear(){this.slots.clear()}}GA();class sWA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,B,w){this.config=A;this.context=Q;this.pluginId=B;this.logger=w}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),B=this.debounces.get(Q);if(!B)B=new k3(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,B);B.trigger()}setupAutoRebuild(){let A=new Set(["base"]),Q=async(w)=>{let{entityType:$}=w.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},B=["entity:created","entity:updated","entity:deleted"];for(let w of B)this.unsubscribeFunctions.push(this.context.messaging.subscribe(w,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("site-build",{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},null,{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}),this.logger.debug("Site rebuild enqueued")}catch(B){this.logger.error("Failed to enqueue site rebuild",{error:B})}}}B0();function fZ2(A,Q){return A.map((B)=>({...B,template:B.template.includes(":")?B.template:`${Q}:${B.template}`}))}function Bi(A,Q,B){for(let w of A)B.register({...w,pluginId:Q,sections:w.sections?fZ2(w.sections,Q):[]})}function sx0(A,Q,B){A.messaging.subscribe("plugin:site-builder:route:register",async(w)=>{try{let $=xe.parse(w.payload),{routes:D,pluginId:Y}=$;return Bi(D,Y,Q),{success:!0}}catch($){return B.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(w)=>{try{let $=Te.parse(w.payload),{paths:D,pluginId:Y}=$;if(D)for(let I of D)Q.unregister(I);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return B.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(w)=>{try{let $=ve.parse(w.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return B.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(w)=>{try{let $=Se.parse(w.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return B.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()}})}GA();import{promises as h_}from"fs";import{join as g_}from"path";function ax0(A,Q){if(Q==="preview")return`User-agent: *
|
|
2424
|
+
`+I;await gw.writeFile(Y,H,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=OX(process.cwd(),"public");try{await gw.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await gw.readdir(A,{withFileTypes:!0});for(let B of Q){let w=OX(A,B.name),$=OX(this.outputDir,B.name);if(B.isDirectory())await this.copyDirectory(w,$);else await gw.copyFile(w,$),this.logger.debug(`Copied static asset: ${B.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([B,w])=>{let $=B.startsWith("/")?B.slice(1):B,D=OX(this.outputDir,$);await gw.mkdir(sW2(D),{recursive:!0}),await gw.writeFile(D,w,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await gw.mkdir(Q,{recursive:!0});let B=await gw.readdir(A,{withFileTypes:!0});for(let w of B){let $=OX(A,w.name),D=OX(Q,w.name);if(w.isDirectory())await this.copyDirectory($,D);else await gw.copyFile($,D)}}}function zWA(A){return new M_0(A)}function aW2(A,Q){let B=new Map;for(let w of A.sections){let $=Q.getViewTemplate(w.template);if(!$?.runtimeScripts)continue;for(let D of $.runtimeScripts)if(!B.has(D.src))B.set(D.src,D)}return[...B.values()].map((w)=>{let $=[`src="${w.src}"`];if(w.defer)$.push("defer");if(w.module)$.push('type="module"');return`<script ${$.join(" ")}></script>`})}import{join as CZ2}from"path";GA();class qWA{context;routeRegistry;entityDisplay;constructor(A,Q,B){this.context=A;this.routeRegistry=Q;this.entityDisplay=B}async generateEntityRoutes(){let A=this.context.logger.child("DynamicRouteGenerator"),Q=this.routeRegistry.list(),B=0;for(let $ of Q)if($.sourceEntityType)this.routeRegistry.unregister($.path),B++;if(B>0)A.debug(`Cleared ${B} dynamic routes before regeneration`);let w=this.context.entityService.getEntityTypes();A.debug(`Found ${w.length} entity types`,{entityTypes:w});for(let $ of w)await this.generateRoutesForEntityType($)}async generateRoutesForEntityType(A){let Q=this.context.logger.child("DynamicRouteGenerator"),{listTemplateName:B,detailTemplateName:w}=this.findTemplatesForEntityType(A);if(!B&&!w){Q.debug(`No matching templates found for entity type: ${A}`);return}if(Q.debug(`Generating routes for entity type: ${A}`,{listTemplate:B,detailTemplate:w}),B){let{pluralName:$,label:D,layout:Y,paginate:I,pageSize:X,navigation:H}=this.getEntityDisplayConfig(A);if(I)await this.generatePaginatedRoutes(A,B,$,D,Y,X,H,Q);else{let W={id:`${A}-index`,path:`/${$}`,title:D,description:`Browse all ${$}`,...Y&&{layout:Y},navigation:{show:H.show,label:D,slot:H.slot,priority:H.priority},sections:[{id:"list",template:B,dataQuery:{entityType:A,query:{limit:100}}}],sourceEntityType:A};try{this.routeRegistry.register(W),Q.debug(`Registered index route for ${A}`,{path:W.path})}catch(J){Q.warn(`Failed to register index route for ${A}`,{error:J})}}}if(w)try{let $=await this.context.entityService.listEntities(A,{limit:1000});Q.debug(`Found ${$.length} ${A} entities to generate routes for`);let{pluralName:D,layout:Y}=this.getEntityDisplayConfig(A);for(let X of $){let H="slug"in X.metadata?X.metadata.slug:X.id,W={id:`${A}-${X.id}`,path:`/${D}/${H}`,title:`${this.capitalize(A)}: ${H}`,description:`View ${A} details`,...Y&&{layout:Y},sections:[{id:"detail",template:w,dataQuery:{entityType:A,query:{id:H}}}],sourceEntityType:A};try{this.routeRegistry.register(W)}catch(J){Q.warn(`Failed to register detail route for ${A}/${X.id}`,{error:J})}}let I=B?$.length+1:$.length;Q.debug(`Successfully registered ${I} routes for ${A}`)}catch($){Q.error(`Failed to list entities for type: ${A}`,{error:$})}}async generatePaginatedRoutes(A,Q,B,w,$,D,Y,I){let H=(await this.context.entityService.listEntities(A,{limit:1000})).length,W=Math.max(1,Math.ceil(H/D));I.debug(`Generating ${W} paginated routes for ${A}`,{totalItems:H,pageSize:D});for(let J=1;J<=W;J++){let F=J===1,z=F?`/${B}`:`/${B}/page/${J}`,V={id:`${A}-index${F?"":`-page-${J}`}`,path:z,title:F?w:`${w} - Page ${J}`,description:`Browse all ${B}${F?"":` - Page ${J}`}`,...$&&{layout:$},navigation:F?{show:Y.show,label:w,slot:Y.slot,priority:Y.priority}:void 0,sections:[{id:"list",template:Q,dataQuery:{entityType:A,query:{page:J,pageSize:D,baseUrl:`/${B}`}}}],sourceEntityType:A};try{this.routeRegistry.register(V),I.debug(`Registered paginated route for ${A}`,{path:V.path,page:J})}catch(E){I.warn(`Failed to register paginated route for ${A} page ${J}`,{error:E})}}}findTemplatesForEntityType(A){let Q=this.context.views.list(),B,w,$=`${A}-list`,D=`${A}-detail`;for(let I of Q){let X=I.name;if(X.endsWith($)){let H=X.slice(0,-$.length);if(H===""||H.endsWith(":"))B=X}if(X.endsWith(D)){let H=X.slice(0,-D.length);if(H===""||H.endsWith(":"))w=X}}let Y={};if(B)Y.listTemplateName=B;if(w)Y.detailTemplateName=w;return Y}getEntityDisplayConfig(A){let Q=this.entityDisplay?.[A],B=10,w=!0,$=!0,D="primary",Y=40;if(Q){let X=Q.pluralName??C$(Q.label.toLowerCase()),H=this.capitalize(C$(Q.label.toLowerCase()));return{pluralName:X,label:H,...Q.layout&&{layout:Q.layout},paginate:Q.paginate??!0,pageSize:Q.pageSize??10,navigation:{show:Q.navigation?.show??!0,slot:Q.navigation?.slot??"primary",priority:Q.navigation?.priority??40}}}let I=C$(A);return{pluralName:I,label:this.capitalize(I),paginate:!0,pageSize:10,navigation:{show:!0,slot:"primary",priority:40}}}capitalize(A){return A.split(" ").map((Q)=>Q.charAt(0).toUpperCase()+Q.slice(1)).join(" ")}}B0();GA();B0();var E_0=Z.object({}),j_=U2.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:E_0}),k_=Z.object({heading:Z.string().describe("Main CTA heading text"),buttonText:Z.string().describe("Call-to-action button text"),buttonLink:Z.string().describe("URL or anchor for the CTA button")}),fX=Z.object({title:Z.string().describe("The site's title"),description:Z.string().describe("The site's description"),copyright:Z.string().optional().describe("Copyright notice text"),logo:Z.boolean().optional().describe("Whether to display logo instead of title text in header"),themeMode:Z.enum(["light","dark"]).optional().describe("Default theme mode"),cta:k_.optional().describe("Call-to-action configuration")});B0();class uY extends E2{constructor(){super({entityType:"site-info",schema:j_,frontmatterSchema:fX,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=fX.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}toMarkdown(A){return A.content}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",Q)}}class RX{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,B){return RX.instance??=new RX(A,Q,B),RX.instance}static resetInstance(){RX.instance=null}static createFresh(A,Q,B){return new RX(A,Q,B)}constructor(A,Q,B){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new uY;let w=RX.getDefaultSiteInfo();this.defaultSiteInfo={...w,...B}}async initialize(){try{if(!await this.entityService.getEntity("site-info","site-info")){this.logger.info("No site info found, creating default site info");let Q=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({id:"site-info",entityType:"site-info",content:Q,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("site-info","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 tW2=new uY;class hd{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,B){let{entityService:w}=B,$;try{let I=await w.getEntity("site-info","site-info");$=I?tW2.parseSiteInfoBody(I.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let D;try{let I=await w.getEntity("anchor-profile","anchor-profile");if(I)D=I.metadata.socialLinks}catch{}let Y={...$,socialLinks:D,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var C_0={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.38",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/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 AG2=new uY;class NWA extends HQ{entityType="site-info";schema=j_;adapter=AG2;defaultSiteInfo;constructor(A){super("site-info",C_0);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new hd(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=RX.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function nZ(A){return new NWA(A)}var QG2=new uY;async function rK(A){let B=(await A.listEntities("site-info",{limit:1}))[0];if(!B)throw Error("Site info not found \u2014 create a site-info entity");return QG2.parseSiteInfoBody(B.content)}GA();var BG2=fX.extend({navigation:Z.object({primary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()})),secondary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}))}),copyright:Z.string(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});async function O_0(A,Q,B){let w;try{w=await rK(A)}catch{w={title:"Brain",description:"A knowledge management system"}}let $=Q.getProfile(),D=B.getNavigationItems("primary"),Y=B.getNavigationItems("secondary");return{...w,socialLinks:$.socialLinks,navigation:{primary:D,secondary:Y},copyright:w.copyright??"Powered by Rizom"}}GA();GA();import{promises as ox0}from"fs";import{join as EZ2}from"path";import{createHash as qZ2}from"crypto";import{promises as iWA}from"fs";import{join as dx0}from"path";var ix0=null;async function NZ2(){return ix0??=Promise.resolve().then(() => o0(px0(),1)).then((A)=>A.default),ix0}var VZ2=[480,960,1920],LZ2=80,MZ2="(max-width: 640px) 480px, (max-width: 1280px) 960px, 1920px";class rWA{imagesDir;logger;constructor(A,Q){this.imagesDir=A;this.logger=Q.child("ImageOptimizer")}async optimize(A,Q){try{let B=await NZ2(),w=qZ2("sha256").update(A).digest("hex").slice(0,16),$=await B(A).metadata();if(!$.width||!$.height)return this.logger.warn("Could not determine image dimensions",{originalUrl:Q}),null;let{width:D,height:Y}=$,I=[];for(let J of VZ2){if(J>D)continue;let F=`${w}-${J}w.webp`,z=dx0(this.imagesDir,F),V=`/images/${F}`;if(await iWA.access(z).then(()=>!0).catch(()=>!1)){this.logger.debug("Cache hit, skipping optimization",{fileName:F}),I.push({width:J,url:V});continue}await B(A).resize(J,null,{withoutEnlargement:!0}).webp({quality:LZ2}).toFile(z),I.push({width:J,url:V}),this.logger.debug("Created WebP variant",{fileName:F,width:J})}if(I.length===0)return null;let X=I[I.length-1];if(!X)return null;let H=I.find((J)=>J.width===960)??X,W=Math.round(Y*(H.width/D));return{src:H.url,srcset:I.map((J)=>`${J.url} ${J.width}w`).join(", "),sizes:MZ2,width:H.width,height:W}}catch(B){return this.logger.warn("Image optimization failed, using original",{originalUrl:Q,error:B instanceof Error?B.message:String(B)}),null}}async optimizeAll(){let A={},Q;try{Q=await iWA.readdir(this.imagesDir,{withFileTypes:!0})}catch{return this.logger.debug("Images directory does not exist, nothing to optimize"),A}let B=Q.filter((w)=>w.isFile()&&/\.(png|jpe?g)$/i.test(w.name));if(B.length===0)return this.logger.debug("No PNG/JPEG images found to optimize"),A;this.logger.debug(`Optimizing ${B.length} images`);for(let w of B){let $=dx0(this.imagesDir,w.name),D=`/images/${w.name}`;try{let Y=await iWA.readFile($),I=await this.optimize(Y,D);if(I)A[D]=I}catch(Y){this.logger.warn("Failed to optimize image",{file:w.name,error:Y instanceof Error?Y.message:String(Y)})}}return this.logger.debug(`Optimized ${Object.keys(A).length}/${B.length} images`),A}}function rx0(A,Q){if(A.format)return A.format;return Q.match(/^data:image\/([^;]+);/)?.[1]??"png"}function nx0(A){return A.match(/^data:image\/[^;]+;base64,(.+)$/)?.[1]??null}function iM(A){return A.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}class nWA{entityService;logger;imageMap={};imagesDir;optimizer;constructor(A,Q,B){this.entityService=A;this.logger=Q.child("ImageBuildService"),this.imagesDir=B,this.optimizer=new rWA(this.imagesDir,this.logger)}async resolveAll(A){let Q=[...new Set(A)];if(Q.length===0)return;await ox0.mkdir(this.imagesDir,{recursive:!0});let B=O3(4);await Promise.all(Q.map((w)=>B(async()=>{try{await this.resolveImage(w)}catch($){this.logger.warn("Failed to resolve image",{imageId:w,error:$ instanceof Error?$.message:String($)})}}))),this.logger.debug(`Resolved ${Object.keys(this.imageMap).length}/${Q.length} images`)}async resolveImage(A){let Q=await this.entityService.getEntity("image",A);if(!Q?.content){this.logger.warn("Image entity not found or has no content",{imageId:A});return}let B=nx0(Q.content);if(!B){this.logger.warn("Could not extract base64 from image",{imageId:A});return}let w=Buffer.from(B,"base64"),$=rx0(Q.metadata,Q.content),D=`${A}.${$}`,Y=EZ2(this.imagesDir,D);await ox0.writeFile(Y,w);let I=`/images/${D}`,X=await this.optimizer.optimize(w,I);if(X)this.imageMap[A]={src:X.src,srcset:X.srcset,sizes:X.sizes,width:X.width,height:X.height};else this.imageMap[A]={src:I,width:Q.metadata.width??0,height:Q.metadata.height??0};this.logger.debug("Resolved image",{imageId:A,optimized:Boolean(X)})}get(A){return this.imageMap[A]}getMap(){return this.imageMap}createImageRenderer(){let A=this.imageMap;return(Q,B,w)=>{let $=/^entity:\/\/image\/(.+)$/.exec(Q);if(!$?.[1])return;let D=A[$[1]];if(!D)return;let Y=[`src="${iM(D.src)}"`,`alt="${iM(w)}"`];if(D.srcset)Y.push(`srcset="${iM(D.srcset)}"`);if(D.sizes)Y.push(`sizes="${iM(D.sizes)}"`);if(D.width)Y.push(`width="${D.width}"`);if(D.height)Y.push(`height="${D.height}"`);if(B)Y.push(`title="${iM(B)}"`);return Y.push('loading="lazy"'),Y.push('decoding="async"'),`<img ${Y.join(" ")}>`}}}var OZ2=U2.extend({metadata:Z.object({slug:Z.string()}).passthrough()});class A4{static instance=null;static defaultStaticSiteBuilderFactory=zWA;logger;context;staticSiteBuilderFactory;routeRegistry;profileService;entityDisplay;imageBuildService=null;static setDefaultStaticSiteBuilderFactory(A){A4.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,B,w,$){return A4.instance??=new A4(A,A4.defaultStaticSiteBuilderFactory,Q,B,w,$),A4.instance}static resetInstance(){A4.instance=null}static createFresh(A,Q,B,w,$,D){return new A4(A,$??A4.defaultStaticSiteBuilderFactory,Q,B,w,D)}constructor(A,Q,B,w,$,D){this.logger=A,this.context=B,this.staticSiteBuilderFactory=Q,this.routeRegistry=w,this.profileService=$,this.entityDisplay=D,f7.getInstance().configure(D)}async getSiteInfo(){return O_0(this.context.entityService,this.profileService,this.routeRegistry)}async build(A,Q){let B=aL0.parse(A),w=Lw.from(Q),$=[],D=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await new qWA(this.context,this.routeRegistry,this.entityDisplay).generateEntityRoutes();let I=B.workingDir??CZ2(B.outputDir,".preact-work"),X=this.staticSiteBuilderFactory({logger:this.logger.child("StaticSiteBuilder"),workingDir:I,outputDir:B.outputDir});if(B.cleanBeforeBuild)await X.clean();let H=this.routeRegistry.list();if(H.length===0)D.push("No routes registered for site build");await w?.report({message:`Building ${H.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100}),this.imageBuildService=new nWA(this.context.entityService,this.logger,B.sharedImagesDir);let W=await this.collectAllImageIds();if(W.length>0)await this.imageBuildService.resolveAll(W);let J=B.siteConfig,F={routes:H,pluginContext:this.context,siteConfig:{title:J.title,description:J.description,...J.url&&{url:J.url},...J.copyright&&{copyright:J.copyright},...J.themeMode&&{themeMode:J.themeMode},...J.analyticsScript&&{analyticsScript:J.analyticsScript}},headScripts:A.headScripts,...A.staticAssets&&{staticAssets:A.staticAssets},getContent:async(k,_)=>{let j=B.environment==="production";return this.getContentForSection(_,k,j)},getViewTemplate:(k)=>{return this.context.views.get(k)},layouts:B.layouts,getSiteInfo:async()=>{return this.getSiteInfo()},...B.themeCSS!==void 0&&{themeCSS:B.themeCSS},...A.slots&&{slots:A.slots},imageBuildService:this.imageBuildService},z=0,V=H.length+4;await X.build(F,(k)=>{z++;let _=85+Math.round(z/V*10);w?.report({message:k,progress:_,total:100}).catch(()=>{})}),await w?.report({message:"Site build complete",progress:100,total:100});let E=H.length+1,L={success:$.length===0,outputDir:B.outputDir,filesGenerated:E,routesBuilt:H.length};if($.length>0)L.errors=$;if(D.length>0)L.warnings=D;return L}catch(Y){let I=Error("Site build process failed");return this.logger.error("Site build failed",{error:I,originalError:Y}),$.push(I.message),{success:!1,outputDir:B.outputDir,filesGenerated:0,routesBuilt:0,errors:$}}}async getContentForSection(A,Q,B){if(!A.template)return A.content??null;let w=A.template,$=f7.getInstance();if(A.dataQuery){let Y={dataParams:A.dataQuery,fallback:A.content,publishedOnly:B},I=await this.context.templates.resolve(w,Y);if(I)return this.enrichWithUrls(I,$);return null}let D=await this.context.templates.resolve(w,{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content});if(D)return this.enrichWithUrls(D,$);return null}async enrichWithUrls(A,Q){if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((j)=>this.enrichWithUrls(j,Q)));if(typeof A!=="object")return A;let B=A,w={},$=Object.entries(B),D=await Promise.all($.map(([,j])=>this.enrichWithUrls(j,Q)));for(let j=0;j<$.length;j++){let r=$[j];if(r)w[r[0]]=D[j]}let Y=OZ2.safeParse(B);if(!Y.success)return w;let I=Y.data,X=I.entityType,H=I.metadata.slug,W=this.entityDisplay?.[X],J=W?W.label:X.charAt(0).toUpperCase()+X.slice(1),F=W?W.pluralName??W.label.toLowerCase()+"s":C$(X),z=`/${F}`,V=F.charAt(0).toUpperCase()+F.slice(1),E=$j(I),L=E?this.imageBuildService?.get(E):void 0,k={};if(L)k={coverImageUrl:L.src,coverImageWidth:L.width,coverImageHeight:L.height,...L.srcset&&{coverImageSrcset:L.srcset,coverImageSizes:L.sizes}};else{let j=await Dj(I,this.context.entityService);if(j)k={coverImageUrl:j.url,coverImageWidth:j.width,coverImageHeight:j.height}}return{...w,...I,url:Q.generateUrl(X,H),typeLabel:J,listUrl:z,listLabel:V,...k}}async collectAllImageIds(){let A=new Set;try{let Q=this.context.entityService.getEntityTypes();for(let B of Q){if(B==="image")continue;let w=await this.context.entityService.listEntities(B);for(let $ of w){let D=$j($);if(D)A.add(D)}}}catch(Q){this.logger.warn("Failed to collect image IDs for pre-resolution",{error:Q instanceof Error?Q.message:String(Q)})}return[...A]}}B0();GA();class oWA{logger;routes=new Map;constructor(A){this.logger=A}register(A){for(let Q of SH(A)){let B=FN.parse(Q);if(this.routes.has(B.path)){let w=this.routes.get(B.path);this.logger.debug(`Overriding route "${B.path}" (was registered by plugin "${w?.pluginId}")`)}this.routes.set(B.path,B)}}unregister(A){SH(A).forEach((Q)=>this.routes.delete(Q))}unregisterByPlugin(A){for(let[Q,B]of this.routes.entries())if(B.pluginId===A)this.routes.delete(Q)}get(A){return this.routes.get(A)}list(A){let Q=Array.from(this.routes.values()).filter((B)=>!B.external);if(A?.pluginId)Q=Q.filter((B)=>B.pluginId===A.pluginId);return Q}listByPlugin(A){return this.list({pluginId:A})}clear(){this.routes.clear()}size(){return this.routes.size}getNavigationItems(A){let Q=[];for(let[B,w]of this.routes.entries())if(w.navigation?.show&&w.navigation.slot===A)Q.push({label:w.navigation.label??w.title,href:B,priority:w.navigation.priority});return Q.sort((B,w)=>B.priority-w.priority)}}class Qi{slots=new Map;register(A,Q){let B={...Q,priority:Q.priority??50},w=this.slots.get(A)??[];w.push(B),this.slots.set(A,w)}getSlot(A){return[...this.slots.get(A)??[]].sort((B,w)=>w.priority-B.priority)}hasSlot(A){let Q=this.slots.get(A);return Q!==void 0&&Q.length>0}unregister(A,Q){let B=this.slots.get(A);if(!B)return;let w=B.filter(($)=>$.pluginId!==Q);if(w.length>0)this.slots.set(A,w);else this.slots.delete(A)}unregisterAll(A){for(let[Q,B]of this.slots){let w=B.filter(($)=>$.pluginId!==A);if(w.length>0)this.slots.set(Q,w);else this.slots.delete(Q)}}getSlotNames(){return Array.from(this.slots.keys())}clear(){this.slots.clear()}}GA();class sWA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,B,w){this.config=A;this.context=Q;this.pluginId=B;this.logger=w}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),B=this.debounces.get(Q);if(!B)B=new k3(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,B);B.trigger()}setupAutoRebuild(){let A=new Set(["base"]),Q=async(w)=>{let{entityType:$}=w.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},B=["entity:created","entity:updated","entity:deleted"];for(let w of B)this.unsubscribeFunctions.push(this.context.messaging.subscribe(w,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("site-build",{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},null,{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}),this.logger.debug("Site rebuild enqueued")}catch(B){this.logger.error("Failed to enqueue site rebuild",{error:B})}}}B0();function fZ2(A,Q){return A.map((B)=>({...B,template:B.template.includes(":")?B.template:`${Q}:${B.template}`}))}function Bi(A,Q,B){for(let w of A)B.register({...w,pluginId:Q,sections:w.sections?fZ2(w.sections,Q):[]})}function sx0(A,Q,B){A.messaging.subscribe("plugin:site-builder:route:register",async(w)=>{try{let $=xe.parse(w.payload),{routes:D,pluginId:Y}=$;return Bi(D,Y,Q),{success:!0}}catch($){return B.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(w)=>{try{let $=Te.parse(w.payload),{paths:D,pluginId:Y}=$;if(D)for(let I of D)Q.unregister(I);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return B.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(w)=>{try{let $=ve.parse(w.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return B.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(w)=>{try{let $=Se.parse(w.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return B.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()}})}GA();import{promises as h_}from"fs";import{join as g_}from"path";function ax0(A,Q){if(Q==="preview")return`User-agent: *
|
|
2424
2425
|
Disallow: /
|
|
2425
2426
|
|
|
2426
2427
|
Sitemap: ${A}/sitemap.xml
|
|
@@ -2449,7 +2450,7 @@ ${A.map((D)=>({url:`${Q}${D.path}`,lastmod:B,changefreq:D.path==="/"?"daily":"we
|
|
|
2449
2450
|
<script src="https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js"></script>
|
|
2450
2451
|
</body>
|
|
2451
2452
|
</html>
|
|
2452
|
-
`;async function PZ2(A,Q,B){let w=A.siteConfig.url??"https://example.com",$=Q.list(),D=ax0(w,A.environment);await h_.writeFile(g_(A.outputDir,"robots.txt"),D,"utf-8"),B.info(`Generated robots.txt for ${A.environment} environment`);let Y=tx0($,w);await h_.writeFile(g_(A.outputDir,"sitemap.xml"),Y,"utf-8"),B.info(`Generated sitemap.xml with ${$.length} URLs`)}async function _Z2(A,Q,B,w){if(!B.cms)return;let $=await Q.messaging.send("git-sync:get-repo-info",{});if("noop"in $||!$.success||!$.data?.repo){w.warn("CMS enabled but git-sync repo info unavailable \u2014 skipping CMS generation");return}let D=Q.entityService.getEntityTypes(),Y=S_({repo:$.data.repo,branch:$.data.branch,...Q.siteUrl&&{baseUrl:Q.siteUrl},entityTypes:D,getFrontmatterSchema:(X)=>Q.entities.getEffectiveFrontmatterSchema(X),getAdapter:(X)=>Q.entities.getAdapter(X),...B.entityDisplay&&{entityDisplay:B.entityDisplay}}),I=g_(A.outputDir,"admin");await h_.mkdir(I,{recursive:!0}),await h_.writeFile(g_(I,"config.yml"),O4(Y),"utf-8"),await h_.writeFile(g_(I,"index.html"),tWA,"utf-8"),w.info("Generated CMS admin page and config.yml")}function AT0(A){let{context:Q,routeRegistry:B,config:w,logger:$}=A;Q.messaging.subscribe("site:build:completed",async(D)=>{try{let Y=D.payload;return $.info(`Received site:build:completed event for ${Y.environment} environment - generating SEO files`),await PZ2(Y,B,$),await _Z2(Y,Q,w,$),{success:!0}}catch(Y){return $.error("Failed to generate SEO files",Y),{success:!1}}})}B0();GA();var QT0=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),analyticsScript:Z.string().optional()}).optional()});GA();class eWA extends MB{sendMessage;cfg;constructor(A,Q,B){super(A,{schema:QT0,jobTypeName:"site-build"});this.sendMessage=Q;this.cfg=B}async process(A,Q,B){let w=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:w,outputDir:A.outputDir}),await B.report({progress:0,total:100,message:`Starting site build for ${w} environment`});let D=B.createSub({scale:{start:10,end:90}}),Y=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:w,cleanBeforeBuild:!0,siteConfig:A.siteConfig??this.cfg.defaultSiteConfig,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},D.toCallback());if(await B.report({progress:100,total:100,message:`Site build completed: ${Y.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:w,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${w} environment`);let I=w==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage("site:build:completed",{outputDir:A.outputDir,environment:w,routesBuilt:Y.routesBuilt,siteConfig:{...A.siteConfig??this.cfg.defaultSiteConfig,url:I},generateEntityUrl:(X,H)=>f7.getInstance().generateUrl(X,H)},{broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:w,...Y.errors&&{errors:Y.errors},...Y.warnings&&{warnings:Y.warnings}}}catch(D){throw this.logger.error("Site build job failed",D),D}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}GA();B0();var bZ2=Z.object({slot:Z.enum(JN).optional().default("primary"),limit:Z.number().optional()});class AGA{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,B){let w=bZ2.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:w});let $=this.routeRegistry.getNavigationItems(w.slot),D=w.limit?$.slice(0,w.limit):$,Y=D.map((X)=>({label:X.label,href:X.href}));this.logger.debug("NavigationDataSource returning",{slot:w.slot,itemCount:D.length,items:Y});let I={navigation:Y};return Q.parse(I)}}B0();GA();var xZ2=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function BT0(A,Q){return[yQ(A,"build-site","Build a static site from registered routes",xZ2,async(B)=>{return Q(B.environment),{success:!0,message:`Site build requested${B.environment?` for ${B.environment}`:""} (debounced)`,data:{}}},{cli:{name:"build"}})]}GA();B0();var wT0=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:fX.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(FN).optional().describe("Routes to register"),layouts:Z.record(Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(JN).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string()).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."),cms:Z.object({}).optional().describe("Sveltia CMS configuration (enables /admin/ CMS, requires git-sync plugin)")});var $T0={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.37",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/cms-config":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@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",sharp:"^0.34.5",tailwindcss:"^4.1.11"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/sharp":"^0.32.0",eslint:"^8.56.0",typescript:"^5.3.3"}};class QGA extends tB{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",$T0,{...A,layouts:Q},wT0);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new oWA(A.logger),this._slotRegistry=new Qi,A.messaging.subscribe("plugin:site-builder:slot:register",async(Q)=>{let{slotName:B,pluginId:w,render:$,priority:D}=Q.payload;return this._slotRegistry?.register(B,{pluginId:w,render:$,...D!==void 0&&{priority:D}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(Q)=>{let{pluginId:B,script:w}=Q.payload;return this.headScripts.set(B,w),{success:!0}}),A.entities.registerDataSource(new AGA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=b7.getInstance(A.entityService,A.logger),A.messaging.subscribe("sync:initial:completed",async()=>{return await this.profileService?.initialize(),this.logger.info("AnchorProfileService initialized"),{success:!0}}),sx0(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Bi(this.config.routes,this.id,this.routeRegistry);if(this.siteBuilder=A4.getInstance(A.logger.child("SiteBuilder"),A,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new eWA(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 sWA(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();if(this.config.cms)this._routeRegistry.register({id:"cms-admin",path:"/admin/",title:"Admin",external:!0,navigation:{show:!1,slot:"secondary",label:"Admin",priority:100}});A.messaging.subscribe("entity:updated",async(Q)=>{if(Q.payload.entityType==="site-info"){let w=await this.getInstructions();if(w)A.registerInstructions(w)}return{success:!0}}),AT0({context:A,routeRegistry:this._routeRegistry,config:this.config,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 BT0(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Info",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q;try{Q=await rK(A.entityService)}catch{Q={title:"Brain",description:""}}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((B)=>({id:B.id,path:B.path,title:B.title,description:B.description,sections:B.sections.map((w)=>({id:w.id,template:w.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((B)=>({name:B.name,description:B.description,hasWebRenderer:!!B.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext();try{let Q=await rK(A.entityService);return`## Your Site
|
|
2453
|
+
`;async function PZ2(A,Q,B){let w=A.siteConfig.url??"https://example.com",$=Q.list(),D=ax0(w,A.environment);await h_.writeFile(g_(A.outputDir,"robots.txt"),D,"utf-8"),B.info(`Generated robots.txt for ${A.environment} environment`);let Y=tx0($,w);await h_.writeFile(g_(A.outputDir,"sitemap.xml"),Y,"utf-8"),B.info(`Generated sitemap.xml with ${$.length} URLs`)}async function _Z2(A,Q,B,w){if(!B.cms)return;let $=await Q.messaging.send("git-sync:get-repo-info",{});if("noop"in $||!$.success||!$.data?.repo){w.warn("CMS enabled but git-sync repo info unavailable \u2014 skipping CMS generation");return}let D=Q.entityService.getEntityTypes(),Y=S_({repo:$.data.repo,branch:$.data.branch,...Q.siteUrl&&{baseUrl:Q.siteUrl},entityTypes:D,getFrontmatterSchema:(X)=>Q.entities.getEffectiveFrontmatterSchema(X),getAdapter:(X)=>Q.entities.getAdapter(X),...B.entityDisplay&&{entityDisplay:B.entityDisplay}}),I=g_(A.outputDir,"admin");await h_.mkdir(I,{recursive:!0}),await h_.writeFile(g_(I,"config.yml"),O4(Y),"utf-8"),await h_.writeFile(g_(I,"index.html"),tWA,"utf-8"),w.info("Generated CMS admin page and config.yml")}function AT0(A){let{context:Q,routeRegistry:B,config:w,logger:$}=A;Q.messaging.subscribe("site:build:completed",async(D)=>{try{let Y=D.payload;return $.info(`Received site:build:completed event for ${Y.environment} environment - generating SEO files`),await PZ2(Y,B,$),await _Z2(Y,Q,w,$),{success:!0}}catch(Y){return $.error("Failed to generate SEO files",Y),{success:!1}}})}B0();GA();var QT0=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),analyticsScript:Z.string().optional()}).optional()});GA();class eWA extends MB{sendMessage;cfg;constructor(A,Q,B){super(A,{schema:QT0,jobTypeName:"site-build"});this.sendMessage=Q;this.cfg=B}async process(A,Q,B){let w=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:w,outputDir:A.outputDir}),await B.report({progress:0,total:100,message:`Starting site build for ${w} environment`});let D=B.createSub({scale:{start:10,end:90}}),Y=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:w,cleanBeforeBuild:!0,siteConfig:A.siteConfig??this.cfg.defaultSiteConfig,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},D.toCallback());if(await B.report({progress:100,total:100,message:`Site build completed: ${Y.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:w,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${w} environment`);let I=w==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage("site:build:completed",{outputDir:A.outputDir,environment:w,routesBuilt:Y.routesBuilt,siteConfig:{...A.siteConfig??this.cfg.defaultSiteConfig,url:I},generateEntityUrl:(X,H)=>f7.getInstance().generateUrl(X,H)},{broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:w,...Y.errors&&{errors:Y.errors},...Y.warnings&&{warnings:Y.warnings}}}catch(D){throw this.logger.error("Site build job failed",D),D}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}GA();B0();var bZ2=Z.object({slot:Z.enum(JN).optional().default("primary"),limit:Z.number().optional()});class AGA{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,B){let w=bZ2.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:w});let $=this.routeRegistry.getNavigationItems(w.slot),D=w.limit?$.slice(0,w.limit):$,Y=D.map((X)=>({label:X.label,href:X.href}));this.logger.debug("NavigationDataSource returning",{slot:w.slot,itemCount:D.length,items:Y});let I={navigation:Y};return Q.parse(I)}}B0();GA();var xZ2=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function BT0(A,Q){return[yQ(A,"build-site","Build a static site from registered routes",xZ2,async(B)=>{return Q(B.environment),{success:!0,message:`Site build requested${B.environment?` for ${B.environment}`:""} (debounced)`,data:{}}},{cli:{name:"build"}})]}GA();B0();var wT0=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:fX.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(FN).optional().describe("Routes to register"),layouts:Z.record(Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(JN).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string()).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."),cms:Z.object({}).optional().describe("Sveltia CMS configuration (enables /admin/ CMS, requires git-sync plugin)")});var $T0={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.38",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/cms-config":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@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",sharp:"^0.34.5",tailwindcss:"^4.1.11"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.1.14","@types/sharp":"^0.32.0",eslint:"^8.56.0",typescript:"^5.3.3"}};class QGA extends tB{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",$T0,{...A,layouts:Q},wT0);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new oWA(A.logger),this._slotRegistry=new Qi,A.messaging.subscribe("plugin:site-builder:slot:register",async(Q)=>{let{slotName:B,pluginId:w,render:$,priority:D}=Q.payload;return this._slotRegistry?.register(B,{pluginId:w,render:$,...D!==void 0&&{priority:D}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(Q)=>{let{pluginId:B,script:w}=Q.payload;return this.headScripts.set(B,w),{success:!0}}),A.entities.registerDataSource(new AGA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=b7.getInstance(A.entityService,A.logger),A.messaging.subscribe("sync:initial:completed",async()=>{return await this.profileService?.initialize(),this.logger.info("AnchorProfileService initialized"),{success:!0}}),sx0(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Bi(this.config.routes,this.id,this.routeRegistry);if(this.siteBuilder=A4.getInstance(A.logger.child("SiteBuilder"),A,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new eWA(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 sWA(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();if(this.config.cms)this._routeRegistry.register({id:"cms-admin",path:"/admin/",title:"Admin",external:!0,navigation:{show:!1,slot:"secondary",label:"Admin",priority:100}});A.messaging.subscribe("entity:updated",async(Q)=>{if(Q.payload.entityType==="site-info"){let w=await this.getInstructions();if(w)A.registerInstructions(w)}return{success:!0}}),AT0({context:A,routeRegistry:this._routeRegistry,config:this.config,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 BT0(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Info",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q;try{Q=await rK(A.entityService)}catch{Q={title:"Brain",description:""}}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((B)=>({id:B.id,path:B.path,title:B.title,description:B.description,sections:B.sections.map((w)=>({id:w.id,template:w.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((B)=>({name:B.name,description:B.description,hasWebRenderer:!!B.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext();try{let Q=await rK(A.entityService);return`## Your Site
|
|
2453
2454
|
${[`**Title:** ${Q.title}`,`**Description:** ${Q.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
|
|
2454
2455
|
`)}`}catch{return}}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),A4.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function Az(A={}){return new QGA(A)}GA();var vZ2=fX.extend({navigation:Z.object({primary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()})),secondary:Z.array(Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}))}),copyright:Z.string(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});import{h as SZ2,Fragment as hZ2}from"preact";function BGA({name:A,slots:Q}){if(!Q?.hasSlot(A))return null;let w=Q.getSlot(A).map(($)=>$.render());return SZ2(hZ2,{},...w)}B0();vX();u_();GA();var wGA=Z.object({defaultPrompt:Z.string().default("Write a blog post about my recent work and insights"),paginate:Z.boolean().default(!0),pageSize:Z.number().default(10)});B0();GA();var mZ2=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),content:Z.string().optional(),excerpt:Z.string().optional(),coverImageId:Z.string().optional(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional(),skipAi:Z.boolean().optional()}),xtQ=j7.extend({title:Z.string().optional(),slug:Z.string().optional()});class $GA extends Q9{constructor(A,Q){super(A,Q,{schema:mZ2,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:B,coverImageId:w,seriesName:$,seriesIndex:D,skipAi:Y}=A,{title:I,content:X,excerpt:H}=A;if(Y){if(!I)this.failEarly("Title is required when skipAi is true");X=X??`## Introduction
|
|
2455
2456
|
|
|
@@ -2496,7 +2497,7 @@ The excerpt should be clear, concise, and compelling.`});GA();s8();vX();import{j
|
|
|
2496
2497
|
Note: This is part of a series called "${B.seriesName}".`:""}`;return A.ai.generate({prompt:w,templateName:"blog:generation"})}),A.eval.registerHandler("generateExcerpt",async(Q)=>{let B=Qz2.parse(Q);return A.ai.generate({prompt:`Title: ${B.title}
|
|
2497
2498
|
|
|
2498
2499
|
Content:
|
|
2499
|
-
${B.content}`,templateName:"blog:excerpt"})})}var NT0={name:"@brains/blog",private:!0,version:"0.2.0-alpha.
|
|
2500
|
+
${B.content}`,templateName:"blog:excerpt"})})}var NT0={name:"@brains/blog",private:!0,version:"0.2.0-alpha.38",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/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 XGA extends HQ{entityType=Qz.entityType;schema=rM;adapter=Qz;constructor(A={}){super("blog",NT0,A,wGA)}getEntityTypeConfig(){return{weight:2}}createGenerationHandler(A){return new $GA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return GT0()}getDataSources(){return[new YGA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (MT0(),LT0));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),await JT0(A,this.logger),FT0(A,this.logger),zT0(A,this.logger),qT0(A),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}}function HGA(A={}){return new XGA(A)}vX();u_();B0();GA();P6();var DD=Z.object({title:Z.string(),slug:Z.string(),coverImageId:Z.string().optional()}),ET0=DD.pick({title:!0,slug:!0}),sM=U2.extend({metadata:ET0}),Ii=sM.extend({frontmatter:DD}),Xi=Ii.extend({description:Z.string().optional(),postCount:Z.number(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),CT0=Z.object({description:Z.string().optional()});function Bz(A){return new dB(CT0,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}P6();class KGA extends E2{constructor(){super({entityType:"series",schema:sM,frontmatterSchema:DD,supportsCoverImage:!0,bodyFormatter:Bz("")})}toMarkdown(A){let Q,B={};try{Q=this.parseFrontMatter(A.content,DD).coverImageId,B=Bz(A.metadata.title).parse(this.extractBody(A.content))}catch{}let w={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},D=Bz(A.metadata.title).format(B);return this.buildMarkdown(D,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,DD);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,DD);return Bz(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var aM=new KGA;B0();GA();aD();class UGA{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("series",{limit:1000}),B=new Map(Q.map(($)=>[$.id,$])),w=new Set;for(let $ of A){let D=e1($);w.add(D);let Y=B.get(D),I=Y?.content??this.createSeriesContent($),X=aB(I);if(Y?.contentHash===X)continue;let H={id:D,entityType:"series",content:I,contentHash:X,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:$,slug:e1($)}};await this.entityService.upsertEntity(H),this.logger.debug(`Upserted series: ${$}`)}for(let $ of Q)if(!w.has($.id))await this.entityService.deleteEntity("series",$.id),this.logger.debug(`Deleted orphaned series: ${$.id}`)}async handleEntityChange(A,Q){let B=this.getSeriesName(A);if(B)await this.ensureSeriesExists(B);if(Q&&Q!==B)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}getSeriesName(A){let B=A.metadata.seriesName;return typeof B==="string"?B:void 0}async ensureSeriesExists(A){let Q=e1(A);if(await this.entityService.getEntity("series",Q))return;let w=this.createSeriesContent(A),$={id:Q,entityType:"series",content:w,contentHash:aB(w),created:new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:A,slug:e1(A)}};await this.entityService.upsertEntity($),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=e1(A);if(!await this.entityService.getEntity("series",Q))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity("series",Q),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let B of Q){if(B==="series")continue;if((await this.entityService.listEntities(B,{filter:{metadata:{seriesName:A}},limit:1})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let B of Q){if(B==="series")continue;let w=await this.entityService.listEntities(B,{limit:1000});for(let $ of w){let D=this.getSeriesName($);if(D)A.add(D)}}return A}createSeriesContent(A){let Q={title:A,slug:e1(A)};return o5("",Q)}}B0();GA();var $z2=Z.object({entityType:Z.literal("series"),query:Z.object({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional()}).passthrough()}),Dz2=Z.object({type:Z.enum(["list","detail"]),seriesName:Z.string().optional()});function Yz2(A){let Q=Dz2.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let B=$z2.safeParse(A);if(B.success){let{query:w}=B.data;if(w.id)return{type:"detail",seriesSlug:w.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function OT0(A){let Q=F2(A.content,DD);return Ii.parse({...A,frontmatter:Q.metadata})}class WGA{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,B){let w=Yz2(A),$=B.entityService;if(w.type==="list")return this.fetchSeriesList(Q,$);if(w.seriesName)return this.fetchSeriesDetail(w.seriesName,Q,$);if(w.seriesSlug)return this.fetchSeriesDetailBySlug(w.seriesSlug,Q,$);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let B=await Q.listEntities("series",{limit:1000}),w=await this.countEntitiesPerSeries(Q),$=B.map((D)=>{let Y=OT0(D),I=aM.parseBody(D.content);return{...Y,description:I.description,postCount:w.get(D.metadata.title)??0}});return this.logger.debug(`Found ${$.length} series entities`),A.parse({series:$})}async fetchSeriesDetail(A,Q,B,w){if(!w)w=(await B.listEntities("series",{filter:{metadata:{title:A}}}))[0];if(!w)throw Error(`Series not found: ${A}`);let $=OT0(w),D=aM.parseBody(w.content),Y=await this.getSeriesMembers(A,B);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...$,description:D.description,postCount:Y.length},description:D.description})}async fetchSeriesDetailBySlug(A,Q,B){let $=(await B.listEntities("series",{filter:{metadata:{slug:A}}}))[0];if(!$)return this.logger.warn(`Series not found with slug: ${A}`),Q.parse({seriesName:A,posts:[]});return this.fetchSeriesDetail($.metadata.title,Q,B,$)}async countEntitiesPerSeries(A){let Q=new Map,B=A.getEntityTypes();for(let w of B){if(w==="series")continue;let $=await A.listEntities(w,{limit:1000});for(let D of $){let Y=this.getSeriesName(D);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let B=[],w=Q.getEntityTypes();for(let $ of w){if($==="series")continue;let D=await Q.listEntities($,{filter:{metadata:{seriesName:A}}});B.push(...D)}return B.sort(($,D)=>{let Y=$.metadata.seriesIndex,I=D.metadata.seriesIndex;return(typeof Y==="number"?Y:999)-(typeof I==="number"?I:999)}),B}getSeriesName(A){let B=A.metadata.seriesName;return typeof B==="string"?B:void 0}}B0();GA();aD();var Iz2=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),seriesId:Z.string().optional()});class Hi{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 B=await this.context.entityService.getEntity("series",Q);if(!B)return{success:!1,error:`Series not found: ${Q}`};let w=await this.gatherMemberSummaries(B.metadata.title);if(w.length===0)return{success:!1,error:`No members found in series: ${B.metadata.title}`};let $=A.prompt??`Series name: ${B.metadata.title}
|
|
2500
2501
|
|
|
2501
2502
|
Content in this series:
|
|
2502
2503
|
${w.join(`
|
|
@@ -2508,7 +2509,7 @@ Your task is to write a series description (2-3 sentences) that:
|
|
|
2508
2509
|
3. Is engaging and makes readers want to explore the content
|
|
2509
2510
|
4. Works well as a series overview on a website
|
|
2510
2511
|
|
|
2511
|
-
Be concise and focus on what makes this series unique and valuable.`});var bT0={name:"@brains/series",private:!0,version:"0.2.0-alpha.
|
|
2512
|
+
Be concise and focus on what makes this series unique and valuable.`});var bT0={name:"@brains/series",private:!0,version:"0.2.0-alpha.38",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/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"}};class GGA extends HQ{entityType="series";schema=sM;adapter=aM;manager;constructor(){super("series",bT0)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Hi(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...PT0(),description:_T0}}getDataSources(){return[new WGA(this.logger.child("SeriesDataSource"))]}async onRegister(A){this.manager=new UGA(A.entityService,this.logger.child("SeriesManager"));let Q=this.manager;for(let B of["entity:created","entity:updated"])A.messaging.subscribe(B,async(w)=>{try{let $=w.payload;if($.entityType==="series")return{success:!0};if($.entity){if(Q.getSeriesName($.entity))await Q.handleEntityChange($.entity)}return{success:!0}}catch($){return this.logger.error("Failed to handle entity event for series",{error:$}),{success:!1,error:"Series derivation failed"}}});A.messaging.subscribe("entity:deleted",async(B)=>{try{if(B.payload.entityType==="series")return{success:!0};return await Q.handleEntityDeleted(),{success:!0}}catch(w){return this.logger.error("Failed to handle entity deletion for series",{error:w}),{success:!1,error:"Series cleanup failed"}}}),A.messaging.subscribe("sync:initial:completed",async()=>{try{return this.logger.info("Initial sync completed, syncing series"),await Q.syncAllSeries(),{success:!0}}catch(B){return this.logger.error("Failed to sync series after initial sync",{error:B}),{success:!1,error:"Series sync failed"}}})}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}async derive(A,Q,B){await this.requireManager().handleEntityChange(A)}async deriveAll(A){await this.requireManager().syncAllSeries();let Q=new Hi(this.logger.child("SeriesGenerationHandler"),A),B=await A.entityService.listEntities("series",{limit:1000});for(let w of B)try{if(!this.adapter.parseBody(w.content).description)this.logger.info(`Generating description for series: ${w.metadata.title}`),await Q.process({seriesId:w.id})}catch($){this.logger.error(`Failed to generate description for series: ${w.id}`,{error:$})}}}function JGA(){return new GGA}B0();GA();B0();GA();GA();B0();var Wz2=Z.enum(["draft","queued","published"]),wJ=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:Wz2,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional()}),Gz2=wJ.pick({title:!0,description:!0,status:!0,publishedAt:!0,coverImageId:!0}).extend({slug:Z.string()}),Ki=U2.extend({entityType:Z.literal("deck"),metadata:Gz2}),Ui=Ki.extend({frontmatter:wJ,body:Z.string()}),p_=Ui.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class FGA extends E2{constructor(){super({entityType:"deck",schema:Ki,frontmatterSchema:wJ,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);try{let B=this.parseFrontMatter(A.content,wJ),w={...B,slug:B.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontmatter(A),B=this.extractBody(A);this.validateSlideStructure(B);let w=Q.slug??e1(Q.title),$=Q.status;return{entityType:"deck",content:A,metadata:{slug:w,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)}}var d_=new FGA;GA();s8();var Jz2=Z.object({markdown:Z.string().describe("Markdown content with slide separators (---)")}),ZGA=M1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:Jz2,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:hHA,fullscreen:!0}});s8();GA();var zGA=Z.object({decks:Z.array(Ui)}),qGA=Z.object({decks:Z.array(p_),pageTitle:Z.string().optional()});import{jsxDEV as NGA}from"preact/jsx-dev-runtime";var VGA=({decks:A,pageTitle:Q})=>{let B=A.map((w)=>({id:w.id,url:w.url,title:w.frontmatter.title,date:w.frontmatter.publishedAt??w.created,description:w.frontmatter.description}));return NGA("div",{className:"deck-list bg-theme",children:NGA("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:NGA(xK,{title:Q??"Presentations",items:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};GA();class Wi extends dB{constructor(){super(zGA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var LGA=M1({name:"deck-list",description:"List view of all presentation decks",schema:qGA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new Wi,layout:{component:VGA}});GA();B0();var Fz2=Z.object({title:Z.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:Z.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:Z.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),xT0=M1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:Fz2,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
|
|
2512
2513
|
|
|
2513
2514
|
Your task is to generate a complete slide deck based on the user's prompt.
|
|
2514
2515
|
|
|
@@ -2576,7 +2577,7 @@ Add your conclusion here`,X=X??`Presentation: ${Y}`,await this.reportProgress(Q,
|
|
|
2576
2577
|
Note: This presentation is for "${$}".`:""}`,k=await this.context.ai.generate({prompt:L,templateName:"decks:generation"});Y=Y??k.title,I=I??k.content,X=X??k.description,await this.reportProgress(Q,{progress:50,message:`Generated deck: "${Y}"`})}else if(!X)await this.reportProgress(Q,{progress:30,message:"Generating description with AI"}),X=(await this.context.ai.generate({prompt:`Title: ${Y}
|
|
2577
2578
|
|
|
2578
2579
|
Content:
|
|
2579
|
-
${I}`,templateName:"decks:description"})).description,await this.reportProgress(Q,{progress:50,message:"Description generated"});else await this.reportProgress(Q,{progress:50,message:"Using provided content"});if(!Y||!I)this.failEarly("Title and content are required");let W={slug:e1(Y),title:Y,status:"draft"},J=await iH({entityType:"deck",title:Y,deriveId:(V)=>V,regeneratePrompt:"Generate a different presentation deck title on the same topic.",context:this.context});if(J!==Y)W.title=J,W.slug=e1(J);let F={title:W.title,status:W.status,slug:W.slug,description:X,author:w,event:$},z=o5(I,F);return{id:J,content:z,metadata:W,title:J,resultExtras:{title:J,slug:W.slug},createOptions:{deduplicateId:!0}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var vT0={name:"@brains/decks",private:!0,version:"0.2.0-alpha.
|
|
2580
|
+
${I}`,templateName:"decks:description"})).description,await this.reportProgress(Q,{progress:50,message:"Description generated"});else await this.reportProgress(Q,{progress:50,message:"Using provided content"});if(!Y||!I)this.failEarly("Title and content are required");let W={slug:e1(Y),title:Y,status:"draft"},J=await iH({entityType:"deck",title:Y,deriveId:(V)=>V,regeneratePrompt:"Generate a different presentation deck title on the same topic.",context:this.context});if(J!==Y)W.title=J,W.slug=e1(J);let F={title:W.title,status:W.status,slug:W.slug,description:X,author:w,event:$},z=o5(I,F);return{id:J,content:z,metadata:W,title:J,resultExtras:{title:J,slug:W.slug},createOptions:{deduplicateId:!0}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var vT0={name:"@brains/decks",private:!0,version:"0.2.0-alpha.38",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/image":"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 CGA extends HQ{entityType=d_.entityType;schema=d_.schema;adapter=d_;constructor(){super("decks",vT0)}createGenerationHandler(A){return new EGA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":ZGA,"deck-list":LGA,generation:xT0,description:TT0}}getDataSources(){return[new MGA(this.logger)]}getEntityTypeConfig(){return{weight:1.5}}async onRegister(A){await this.registerWithPublishPipeline(A),this.subscribeToPublishExecute(A),this.registerEvalHandlers(A),this.logger.info("Decks plugin registered")}async registerWithPublishPipeline(A){await A.messaging.send("publish:register",{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:B,entityId:w}=Q.payload;if(B!=="deck")return{success:!0};try{let $=await A.entityService.getEntity("deck",w);if(!$)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:`Deck not found: ${w}`}),{success:!0};if($.metadata.status==="published")return{success:!0};let D=new Date().toISOString(),Y={...$,metadata:{...$.metadata,status:"published",publishedAt:D}};await A.entityService.updateEntity({...Y,content:this.adapter.toMarkdown(Y)}),await A.messaging.send("publish:report:success",{entityType:B,entityId:w,result:{id:w}})}catch($){await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:L0($)})}return{success:!0}})}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let B=Z.object({prompt:Z.string(),event:Z.string().optional()}).parse(Q);return A.ai.generate({prompt:`${B.prompt}${B.event?`
|
|
2580
2581
|
|
|
2581
2582
|
Note: This presentation is for "${B.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let B=Z.object({title:Z.string(),content:Z.string()}).parse(Q);return A.ai.generate({prompt:`Title: ${B.title}
|
|
2582
2583
|
|
|
@@ -2591,7 +2592,7 @@ Guidelines:
|
|
|
2591
2592
|
3. Depth: Provide enough detail to be useful as a reference, but stay focused on the topic.
|
|
2592
2593
|
4. Style: Informative and educational. Write as if explaining to yourself for future reference.
|
|
2593
2594
|
5. Length: Adjust based on topic complexity - concise for simple topics, more detailed for complex ones.
|
|
2594
|
-
6. No meta-commentary: Just provide the content directly without phrases like "Here is..." or "This note covers..."`});B0();GA();var gT0=Z.object({prompt:Z.string(),title:Z.string().optional()}),Vz2=j7.extend({title:Z.string().optional()});class Gi extends Q9{constructor(A,Q){super(A,Q,{schema:gT0,jobTypeName:"note-generation",entityType:"base"})}async generate(A,Q){await this.reportProgress(Q,{progress:10,message:"Generating note content with AI"});let B=await this.context.ai.generate({prompt:A.prompt,templateName:"note:generation"}),w=A.title??B.title;return await this.reportProgress(Q,{progress:50,message:`Generated note: "${w}"`}),{id:w,content:eM.createNoteContent(w,B.body),metadata:{title:w},title:w,resultExtras:{title:w}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var yT0={name:"@brains/note",private:!0,version:"0.2.0-alpha.
|
|
2595
|
+
6. No meta-commentary: Just provide the content directly without phrases like "Here is..." or "This note covers..."`});B0();GA();var gT0=Z.object({prompt:Z.string(),title:Z.string().optional()}),Vz2=j7.extend({title:Z.string().optional()});class Gi extends Q9{constructor(A,Q){super(A,Q,{schema:gT0,jobTypeName:"note-generation",entityType:"base"})}async generate(A,Q){await this.reportProgress(Q,{progress:10,message:"Generating note content with AI"});let B=await this.context.ai.generate({prompt:A.prompt,templateName:"note:generation"}),w=A.title??B.title;return await this.reportProgress(Q,{progress:50,message:`Generated note: "${w}"`}),{id:w,content:eM.createNoteContent(w,B.body),metadata:{title:w},title:w,resultExtras:{title:w}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var yT0={name:"@brains/note",private:!0,version:"0.2.0-alpha.38",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/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 jGA extends HQ{entityType=eM.entityType;schema=tM;adapter=eM;constructor(A={}){super("note",yT0,A,fGA)}createGenerationHandler(A){return new Gi(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:RGA}}async onRegister(A){A.eval.registerHandler("generateNote",async(Q)=>{let B=Z.object({prompt:Z.string()}).parse(Q);return A.ai.generate({prompt:B.prompt,templateName:"note:generation"})})}}function wz(A={}){return new jGA(A)}B0();GA();GA();B0();var mT0=Z.object({ref:Z.string(),label:Z.string()}),uT0=Z.enum(["pending","draft","published"]),AU=Z.object({status:uT0,title:Z.string(),url:Z.string().url(),description:Z.string().optional(),domain:Z.string(),capturedAt:Z.string().datetime(),source:mT0}),cT0=AU.pick({title:!0,status:!0}),n_=U2.extend({entityType:Z.literal("link"),metadata:cT0}),kGA=Z.object({enableSummarization:Z.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:Z.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});B0();class DJ extends E2{constructor(){super({entityType:"link",schema:n_,frontmatterSchema:AU})}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},B=A.summary??"";return this.buildMarkdown(B,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,AU),summary:this.extractBody(A).trim()}}toMarkdown(A){return A.content}fromMarkdown(A){let{frontmatter:Q}=this.parseLinkContent(A);return{content:A,entityType:"link",metadata:{title:Q.title,status:Q.status}}}}var PGA=new DJ;B0();GA();var Mz2=Z.object({success:Z.boolean().describe("Set to true if you can extract meaningful content. Set to false only if the provided content is empty, just an error message, or otherwise unusable."),error:Z.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:Z.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:Z.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:Z.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),lT0=M1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:Mz2,basePrompt:`You are an expert at extracting key information from webpage content.
|
|
2595
2596
|
|
|
2596
2597
|
You will receive webpage content in markdown format. Your job is to extract structured information from it.
|
|
2597
2598
|
|
|
@@ -2608,7 +2609,7 @@ Focus only on information present in the provided content. Do not make up or hal
|
|
|
2608
2609
|
|
|
2609
2610
|
`))return{success:!1,error:Y.trim(),errorType:"fetch_failed"};return{success:!0,content:Y}}catch(B){return this.handleFetchError(B,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 fz2}from"crypto";class $z{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match($z.URL_PATTERN)??[];return[...new Set(Q)]}static normalizeUrl(A){try{let Q=new URL(A),B=Q.pathname.replace(/\/$/,"")||"/";return`${Q.protocol}//${Q.host}${B}`}catch{return A}}static generateEntityId(A){let Q=this.normalizeUrl(A),B=fz2("sha256").update(Q).digest("hex");try{return`${new URL(Q).hostname.replace(/\./g,"-")}-${B.substring(0,6)}`}catch{return B.substring(0,12)}}static isValidUrl(A){try{let Q=new URL(A);return["http:","https:"].includes(Q.protocol)}catch{return!1}}}B0();GA();var Rz2=Z.object({url:Z.string().url(),metadata:Z.object({interfaceId:Z.string().optional(),userId:Z.string().optional(),channelId:Z.string().optional(),channelName:Z.string().optional(),timestamp:Z.string().optional()}).optional()}),a2B=Z.object({success:Z.boolean(),entityId:Z.string().optional(),title:Z.string().optional(),url:Z.string().optional(),status:Z.enum(["pending","draft","published"]).optional(),error:Z.string().optional()});class Fi extends MB{context;linkAdapter;urlFetcher;constructor(A,Q,B){super(A,{schema:Rz2,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new DJ,this.urlFetcher=new AE(B?.jinaApiKey?{jinaApiKey:B.jinaApiKey}:void 0)}async process(A,Q,B){let{url:w,metadata:$}=A;try{await B.report({progress:J2.START,total:100,message:"Starting link capture"});let D=$z.generateEntityId(w);await B.report({progress:J2.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity("link",D);if(Y){this.logger.info("Link already captured, returning existing",{url:w,entityId:D});let{frontmatter:z}=this.linkAdapter.parseLinkContent(Y.content);return{success:!0,entityId:Y.id,title:z.title,url:w,status:Y.metadata.status}}await B.report({progress:J2.FETCH,total:100,message:"Fetching webpage content"});let I=await this.urlFetcher.fetch(w);if(!I.success){if(I.errorType==="url_not_found"||I.errorType==="url_unreachable")return this.logger.warn("Link URL not accessible",{url:w,errorType:I.errorType,error:I.error}),{success:!1,error:`Could not capture link: ${I.error}`}}await B.report({progress:J2.PROCESS,total:100,message:"Extracting content with AI"});let X=await this.context.ai.generate({templateName:"link:extraction",prompt:I.success?`Extract structured information from this webpage content:
|
|
2610
2611
|
|
|
2611
|
-
${I.content}`:`The URL ${w} could not be fetched. Return success: false with error: "${I.error}"`,data:{url:w,hasContent:I.success},interfacePermissionGrant:"public"});this.logger.debug("AI extraction result",{result:X}),await B.report({progress:J2.EXTRACT,total:100,message:"Processing extraction results"});let H=this.resolveSource($),W=new Date().toISOString();if(X.success===!1||!X.title||!X.description||!X.summary){let z=X.title||new URL(w).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:w}),await B.report({progress:J2.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:z,url:w,description:X.description,summary:X.summary,domain:new URL(w).hostname,capturedAt:W,source:H}),E=await this.context.entityService.createEntity({id:D,entityType:"link",content:V,metadata:{status:"pending",title:z}});return await B.report({progress:J2.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:E.entityId,title:z,url:w,status:"pending"}}await B.report({progress:J2.SAVE,total:100,message:`Saving link: "${X.title}"`});let J=this.linkAdapter.createLinkContent({status:"draft",title:X.title,url:w,description:X.description,summary:X.summary,domain:new URL(w).hostname,capturedAt:W,source:H}),F=await this.context.entityService.createEntity({id:D,entityType:"link",content:J,metadata:{status:"draft",title:X.title}});return await B.report({progress:J2.COMPLETE,total:100,message:`Link captured: "${X.title}"`}),{success:!0,entityId:F.entityId,title:X.title,url:w,status:"draft"}}catch(D){return this.logger.error("Link capture job failed",{error:D,jobId:Q,data:A}),K6.failure(D)}}resolveSource(A){let Q=A?.channelId,B=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:B??Q};let w=A?.interfaceId??"cli";return{ref:`${w}:local`,label:w.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}var iT0={name:"@brains/link",private:!0,version:"0.2.0-alpha.
|
|
2612
|
+
${I.content}`:`The URL ${w} could not be fetched. Return success: false with error: "${I.error}"`,data:{url:w,hasContent:I.success},interfacePermissionGrant:"public"});this.logger.debug("AI extraction result",{result:X}),await B.report({progress:J2.EXTRACT,total:100,message:"Processing extraction results"});let H=this.resolveSource($),W=new Date().toISOString();if(X.success===!1||!X.title||!X.description||!X.summary){let z=X.title||new URL(w).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:w}),await B.report({progress:J2.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:z,url:w,description:X.description,summary:X.summary,domain:new URL(w).hostname,capturedAt:W,source:H}),E=await this.context.entityService.createEntity({id:D,entityType:"link",content:V,metadata:{status:"pending",title:z}});return await B.report({progress:J2.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:E.entityId,title:z,url:w,status:"pending"}}await B.report({progress:J2.SAVE,total:100,message:`Saving link: "${X.title}"`});let J=this.linkAdapter.createLinkContent({status:"draft",title:X.title,url:w,description:X.description,summary:X.summary,domain:new URL(w).hostname,capturedAt:W,source:H}),F=await this.context.entityService.createEntity({id:D,entityType:"link",content:J,metadata:{status:"draft",title:X.title}});return await B.report({progress:J2.COMPLETE,total:100,message:`Link captured: "${X.title}"`}),{success:!0,entityId:F.entityId,title:X.title,url:w,status:"draft"}}catch(D){return this.logger.error("Link capture job failed",{error:D,jobId:Q,data:A}),K6.failure(D)}}resolveSource(A){let Q=A?.channelId,B=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:B??Q};let w=A?.interfaceId??"cli";return{ref:`${w}:local`,label:w.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}var iT0={name:"@brains/link",private:!0,version:"0.2.0-alpha.38",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/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 SGA extends HQ{entityType=PGA.entityType;schema=n_;adapter=PGA;shell;constructor(A={}){super("link",iT0,A,kGA)}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 Fi(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,B){if(A.content)try{let D=this.adapter.fromMarkdown(A.content).metadata,Y=typeof D?.title==="string"?D.title:void 0,I=typeof D?.status==="string"?D.status:void 0,X=this.extractFirstUrl(A.content);if(Y&&I&&X){let H=e1(X)||e1(Y)||`${A.entityType}-${Date.now()}`,W=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await B.entityService.createEntity({id:H,entityType:A.entityType,content:A.content,metadata:{title:Y,status:I},created:W,updated:W})).entityId,status:"created"}}}}}catch{}let w=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(w){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await this.shell.getJobQueueService().enqueue("link-capture",{url:w,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}})}}}}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 Fi(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:lT0,"link-list":pT0,"link-detail":dT0}}getDataSources(){return[new vGA(this.logger.child("LinksDataSource"))]}async onRegister(A){A.eval.registerHandler("extractContent",async(Q)=>{let{url:B}=Z.object({url:Z.string().url()}).parse(Q),$=await new AE(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(B);if(!$.success)return{success:!1,error:$.error,errorType:$.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
|
|
2612
2613
|
|
|
2613
2614
|
${$.content}`,data:{url:B,hasContent:!0},interfacePermissionGrant:"public"})})}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[B]=$z.extractUrls(Q);if(B)return B}return}}function rT0(A={}){return new SGA(A)}var Dz=rT0;GA();var zQB=Z.object({id:Z.string().optional(),metadata:Z.object({conversationId:Z.string().optional(),interfaceId:Z.string().optional(),userId:Z.string().optional(),messageId:Z.string().optional(),timestamp:Z.string().optional()}).optional()});B0();GA();s8();GA();B0();var nT0=Z.enum(["draft","published"]),YD=Z.object({title:Z.string(),slug:Z.string().optional(),status:nT0,publishedAt:Z.string().datetime().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),url:Z.string().url().optional()}),oT0=YD.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:Z.string()}),QE=U2.extend({entityType:Z.literal("project"),metadata:oT0}),Zi=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),s_=QE.extend({frontmatter:YD,body:Z.string(),structuredContent:Zi.optional(),coverImageUrl:Z.string().optional()}),BE=s_.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),kz2=s_.extend({url:Z.string(),typeLabel:Z.string(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});B0();GA();GA();class hGA extends dB{constructor(){super(Zi,{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 gGA=new hGA;class yGA extends E2{constructor(){super({entityType:"project",schema:QE,frontmatterSchema:YD,supportsCoverImage:!0,bodyFormatter:gGA})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,YD),w={...B,slug:B.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,YD),B=Q.slug??e1(Q.title);return{content:A,entityType:"project",metadata:{title:Q.title,slug:B,status:Q.status,publishedAt:Q.publishedAt,year:Q.year}}}parseProjectFrontmatter(A){return this.parseFrontMatter(A.content,YD)}parseStructuredContent(A){return gGA.parse(this.extractBody(A.content))}createProjectContent(A,Q){let B=gGA.format(Q);return this.buildMarkdown(B,A)}}var YJ=new yGA;GA();var mGA=Z.object({});import{jsxDEV as B4,Fragment as _z2}from"preact/jsx-dev-runtime";var Pz2=({project:A})=>{let{frontmatter:Q,url:B,coverImageUrl:w}=A;return B4(MQ,{href:B,children:[w&&B4("img",{src:w,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),B4(G9,{children:Q.title},void 0,!1,void 0,this),B4("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},uGA=({projects:A,pageTitle:Q,pagination:B,baseUrl:w="/projects"})=>{let $=Q??"Projects",D=B?.totalItems??A.length,Y=`Browse all ${D} ${D===1?"project":"projects"}`;return B4(_z2,{children:[B4(o2,{title:$,description:Y},void 0,!1,void 0,this),B4("div",{className:"project-list bg-theme",children:B4("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[B4("h1",{className:"text-4xl font-bold text-heading mb-12",children:$},void 0,!1,void 0,this),B4("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((I)=>B4(Pz2,{project:I},I.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&B4("div",{className:"mt-12",children:B4(jY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:w},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 HB,Fragment as sT0}from"preact/jsx-dev-runtime";var bz2=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return HB("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:HB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?HB(MQ,{href:A.url,variant:"compact",children:[HB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),HB("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):HB("div",{},void 0,!1,void 0,this),Q&&HB(MQ,{href:Q.url,variant:"compact",className:"md:text-right",children:[HB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),HB("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)},zi=({title:A,content:Q})=>{if(!Q)return null;return HB("section",{className:"mb-12",children:[HB("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),HB(RY,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},cGA=({project:A,prevProject:Q,nextProject:B})=>{let{frontmatter:w,structuredContent:$,metadata:D,coverImageUrl:Y}=A;return HB(sT0,{children:[HB(o2,{title:w.title,description:w.description,...Y&&{ogImage:Y},ogType:"article"},void 0,!1,void 0,this),HB("article",{className:"project-detail",children:HB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:HB("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&HB(bK,{src:Y,alt:w.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),HB("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:w.title},void 0,!1,void 0,this),HB("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[HB("span",{className:"text-sm",children:D.year},void 0,!1,void 0,this),w.url&&HB(sT0,{children:[HB("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),HB("a",{href:w.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),HB("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:w.description},void 0,!1,void 0,this),$&&HB("div",{className:"case-study",children:[HB(zi,{title:"Context",content:$.context},void 0,!1,void 0,this),HB(zi,{title:"Problem",content:$.problem},void 0,!1,void 0,this),HB(zi,{title:"Solution",content:$.solution},void 0,!1,void 0,this),HB(zi,{title:"Outcome",content:$.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),HB(bz2,{prevProject:Q,nextProject: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)]},void 0,!0,void 0,this)};GA();B0();var xz2=Z.object({title:Z.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:Z.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:Z.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:Z.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:Z.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:Z.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),lGA=M1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:xz2,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
|
|
2614
2615
|
|
|
@@ -2627,7 +2628,7 @@ Guidelines:
|
|
|
2627
2628
|
CRITICAL: Only include information that can be derived from the provided content. If information is missing, keep that section brief rather than inventing details.
|
|
2628
2629
|
|
|
2629
2630
|
Tone: Professional but accessible. Write for someone evaluating real work.
|
|
2630
|
-
Structure: Use markdown formatting. Break long sections into paragraphs for readability.`});B0();GA();var Tz2=Z.object({prompt:Z.string(),year:Z.number(),title:Z.string().optional()}),sQB=j7.extend({title:Z.string().optional()});class qi extends Q9{constructor(A,Q){super(A,Q,{schema:Tz2,jobTypeName:"project-generation",entityType:"project"})}async generate(A,Q){let{prompt:B,year:w}=A;await this.reportProgress(Q,{progress:10,message:"Generating project content with AI"});let $=await this.context.ai.generate({prompt:B,templateName:"portfolio:generation"}),D=A.title??$.title,Y=e1(D);await this.reportProgress(Q,{progress:50,message:`Generated project: "${D}"`});let I={title:D,slug:Y,status:"draft",description:$.description,year:w},X={context:$.context,problem:$.problem,solution:$.solution,outcome:$.outcome};return{id:Y,content:YJ.createProjectContent(I,X),metadata:{title:D,slug:Y,status:"draft",year:w},title:D,resultExtras:{title:D}}}summarizeDataForLog(A){return{prompt:A.prompt.substring(0,100),year:A.year,title:A.title}}}B0();B0();function vz2(A){let Q=F2(A.content,YD),B=YJ.parseStructuredContent(A);return s_.parse({...A,frontmatter:Q.metadata,body:Q.content,structuredContent:B})}class Ni extends s5{id="portfolio:entities";name="Portfolio Project DataSource";description="Fetches and transforms project entities for rendering";config={entityType:"project",defaultSort:[{field:"year",direction:"desc"},{field:"title",direction:"asc"}],defaultLimit:10,enableNavigation:!0};constructor(A){super(A);this.logger.debug("ProjectDataSource initialized")}transformEntity(A){return vz2(A)}buildDetailResult(A,Q){return{project:A,prevProject:Q?.prev??null,nextProject:Q?.next??null}}buildListResult(A,Q,B){return{projects:A,pagination:Q,baseUrl:B.baseUrl}}}var aT0={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.
|
|
2631
|
+
Structure: Use markdown formatting. Break long sections into paragraphs for readability.`});B0();GA();var Tz2=Z.object({prompt:Z.string(),year:Z.number(),title:Z.string().optional()}),sQB=j7.extend({title:Z.string().optional()});class qi extends Q9{constructor(A,Q){super(A,Q,{schema:Tz2,jobTypeName:"project-generation",entityType:"project"})}async generate(A,Q){let{prompt:B,year:w}=A;await this.reportProgress(Q,{progress:10,message:"Generating project content with AI"});let $=await this.context.ai.generate({prompt:B,templateName:"portfolio:generation"}),D=A.title??$.title,Y=e1(D);await this.reportProgress(Q,{progress:50,message:`Generated project: "${D}"`});let I={title:D,slug:Y,status:"draft",description:$.description,year:w},X={context:$.context,problem:$.problem,solution:$.solution,outcome:$.outcome};return{id:Y,content:YJ.createProjectContent(I,X),metadata:{title:D,slug:Y,status:"draft",year:w},title:D,resultExtras:{title:D}}}summarizeDataForLog(A){return{prompt:A.prompt.substring(0,100),year:A.year,title:A.title}}}B0();B0();function vz2(A){let Q=F2(A.content,YD),B=YJ.parseStructuredContent(A);return s_.parse({...A,frontmatter:Q.metadata,body:Q.content,structuredContent:B})}class Ni extends s5{id="portfolio:entities";name="Portfolio Project DataSource";description="Fetches and transforms project entities for rendering";config={entityType:"project",defaultSort:[{field:"year",direction:"desc"},{field:"title",direction:"asc"}],defaultLimit:10,enableNavigation:!0};constructor(A){super(A);this.logger.debug("ProjectDataSource initialized")}transformEntity(A){return vz2(A)}buildDetailResult(A,Q){return{project:A,prevProject:Q?.prev??null,nextProject:Q?.next??null}}buildListResult(A,Q,B){return{projects:A,pagination:Q,baseUrl:B.baseUrl}}}var aT0={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.38",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/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 hz2=Z.object({projects:Z.array(BE),pageTitle:Z.string().optional(),pagination:_7.nullable(),baseUrl:Z.string().optional()});class pGA extends HQ{entityType=YJ.entityType;schema=QE;adapter=YJ;constructor(A={}){super("portfolio",aT0,A,mGA)}createGenerationHandler(A){return new qi(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":M1({name:"project-list",description:"Portfolio project list page template",schema:hz2,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:uGA}}),"project-detail":M1({name:"project-detail",description:"Individual project case study template",schema:Z.object({project:BE,prevProject:BE.nullable(),nextProject:BE.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:cGA}}),generation:lGA}}getDataSources(){return[new Ni(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),await this.registerWithPublishPipeline(A),this.subscribeToPublishExecute(A)}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let B=Z.object({prompt:Z.string(),year:Z.number()}).parse(Q);return A.ai.generate({prompt:B.prompt,templateName:"portfolio:generation"})})}async registerWithPublishPipeline(A){let Q={name:"internal",publish:async()=>({id:"internal"})};await A.messaging.send("publish:register",{entityType:"project",provider:Q})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:B,entityId:w}=Q.payload;if(B!=="project")return{success:!0};try{let $=await A.entityService.getEntity("project",w);if(!$)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:`Project not found: ${w}`}),{success:!0};if($.metadata.status==="published")return{success:!0};let D=F2($.content,YD),Y=new Date().toISOString(),I=o5(D.content,{...D.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({...$,content:I,metadata:{...$.metadata,status:"published",publishedAt:Y}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:w,publishedAt:Y})}catch($){await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:L0($)})}return{success:!0}})}}function dGA(A={}){return new pGA(A)}B0();GA();GA();var tT0=Z.object({includeEntityTypes:Z.array(Z.string()).default([]),minRelevanceScore:Z.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:Z.number().min(0).max(1).default(0.85),autoMerge:Z.boolean().default(!0),enableAutoExtraction:Z.boolean().default(!0)});B0();GA();B0();var gz2=Z.object({aliases:Z.array(Z.string()).optional()}),Vi=U2.extend({entityType:Z.literal("topic"),metadata:gz2}),_BB=Z.object({content:Z.string()}),eT0=Z.object({title:Z.string().describe("Topic title")}),bBB=Z.object({timeWindowHours:Z.number().min(1),minRelevanceScore:Z.number().min(0).max(1)}),xBB=Z.object({topicIds:Z.array(Z.string()).min(2),similarityThreshold:Z.number().min(0).max(1)});class w4 extends E2{constructor(){super({entityType:"topic",schema:Vi,frontmatterSchema:eT0})}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:"topic"}}extractMetadata(A){return{aliases:A.metadata.aliases??[]}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),w=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return w?w[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))}}GA();var Av0=40,yz2=new w4;async function Li(A,Q=Av0){return(await A.listEntities("topic",{limit:Q})).map((w)=>yz2.parseTopicBody(w.content).title).filter((w)=>w.trim().length>0)}function Mi(A){let Q=(A.existingTopicTitles??[]).slice(0,Av0),B=Q.length>0?`
|
|
2631
2632
|
|
|
2632
2633
|
Existing topic titles to reuse when they clearly fit:
|
|
2633
2634
|
${Q.map((w)=>`- ${w}`).join(`
|
|
@@ -2728,13 +2729,13 @@ RULES:
|
|
|
2728
2729
|
|
|
2729
2730
|
Return JSON with:
|
|
2730
2731
|
- title
|
|
2731
|
-
- content`,requiredPermission:"public"});s8();GA();var Qq2=Z.object({id:Z.string(),title:Z.string(),summary:Z.string(),created:Z.string(),updated:Z.string()}),t_=Z.object({topics:Z.array(Qq2),totalCount:Z.number()});import{jsxDEV as SX}from"preact/jsx-dev-runtime";var nGA=({topics:A,totalCount:Q})=>{return SX("div",{className:"topic-list-container w-full max-w-4xl mx-auto p-6 bg-theme",children:[SX(fY,{title:"Topics",count:Q,singularLabel:"topic",description:"discovered from your knowledge base"},void 0,!1,void 0,this),SX("div",{className:"space-y-6",children:A.map((B)=>SX(MQ,{variant:"vertical",children:[SX(G9,{href:`/topics/${B.id}`,className:"text-xl",children:B.title},void 0,!1,void 0,this),SX("p",{className:"text-theme-muted mb-4",children:B.summary},void 0,!1,void 0,this),SX(Y7,{children:SX("div",{className:"flex justify-between text-sm text-theme-muted",children:SX("time",{dateTime:B.updated,children:["Updated ",m8(B.updated)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},B.id,!0,void 0,this))},void 0,!1,void 0,this),A.length===0&&SX(a$,{message:"No topics discovered yet.",description:"Topics will appear here as they are extracted from your content."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();class Oi extends dB{constructor(){super(t_,{title:"Topic List",mappings:[{key:"topics",label:"Topics",type:"array",itemType:"object"},{key:"totalCount",label:"Total Count",type:"number"}]})}}var Wv0=M1({name:"topics:topic-list",description:"List view of all discovered topics",schema:t_,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Oi,layout:{component:nGA}});s8();GA();var e_=Z.object({id:Z.string(),title:Z.string(),content:Z.string(),created:Z.string(),updated:Z.string()});import{jsxDEV as Ab}from"preact/jsx-dev-runtime";var oGA=({title:A,content:Q,created:B,updated:w})=>{return Ab("article",{className:"topic-detail-container max-w-4xl mx-auto p-6 bg-theme",children:[Ab(fZ,{title:A,created:B,updated:w},void 0,!1,void 0,this),Ab("div",{className:"prose prose-lg max-w-none mb-8 text-theme-muted",children:Ab("div",{dangerouslySetInnerHTML:{__html:Q}},void 0,!1,void 0,this)},void 0,!1,void 0,this),Ab(CZ,{href:"/topics",children:"Back to Topics"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();class fi extends dB{constructor(){super(e_,{title:"Topic Detail",mappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"content",label:"Content",type:"string"},{key:"created",label:"Created",type:"string"},{key:"updated",label:"Updated",type:"string"}]})}}var Gv0=M1({name:"topics:topic-detail",description:"Detailed view of a single topic",schema:e_,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new fi,layout:{component:oGA}});B0();GA();class sGA extends s5{id="topics:entities";name="Topics Entity DataSource";description="Fetches and transforms topic entities for rendering";config={entityType:"topic",defaultSort:[{field:"updated",direction:"desc"}],defaultLimit:100,lookupField:"id"};adapter=new w4;constructor(A){super(A);this.logger.debug("TopicsDataSource initialized")}transformEntity(A){let Q=this.adapter.parseTopicBody(A.content);return{id:A.id,title:Q.title,summary:FW(Q.content,200),created:A.created,updated:A.updated}}buildListResult(A,Q,B){return{topics:A,totalCount:A.length}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A);if(w.id){let D=await B.entityService.getEntity(this.config.entityType,w.id);if(!D)throw Error(`Entity not found: ${w.id}`);let Y=this.adapter.parseTopicBody(D.content);return Q.parse({id:D.id,title:Y.title,content:Y.content,created:D.created,updated:D.updated})}return super.fetch(A,Q,B)}}aD();function Jv0(){let A=new w4;return async(Q)=>{if(!Q.hasEntityType("topic"))return{topics:[]};return{topics:(await Q.listEntities("topic")).map(($)=>{let D=A.parseTopicBody($.content);return{topic:$.id,title:D.title}})}}}var Fv0={name:"@brains/topics",private:!0,version:"0.2.0-alpha.37",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/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var wq2=new w4;function $q2(A){let Q=A.replace(/\s+/g," ").trim();if(!Q)return;let B=Q.match(/^(.*?[.!?])(?:\s|$)/);if(B?.[1])return B[1];return Q.length<=200?Q:`${Q.slice(0,197)}\u2026`}class Zv0 extends HQ{entityType="topic";schema=Vi;adapter=wq2;autoExtractionEnabled=!1;initialDerivationDone=!1;constructor(A={}){super("topics",Fv0,A,tT0)}getEntityTypeConfig(){return{weight:0.5}}getTemplates(){return{extraction:Kv0,"merge-synthesis":Uv0,"topic-list":Wv0,"topic-detail":Gv0}}getDataSources(){return[new sGA(this.logger.child("TopicsDataSource"))]}async onRegister(A){let Q=new Ci(A,this.logger);A.jobs.registerHandler("process-single",Q);let B=new rGA(A,this.logger);if(A.jobs.registerHandler("extract",B),A.insights.register("topic-distribution",Jv0()),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"topics",pluginId:this.id,title:"Topics",section:"secondary",priority:20,rendererName:"ListWidget",dataProvider:async()=>{return{items:(await A.entityService.listEntities("topic",{limit:10,sortFields:[{field:"updated",direction:"desc"}]})).map(($)=>{let D=this.adapter.parseTopicBody($.content),Y=$q2(D.content);return{id:$.id,name:D.title||$.id,...Y&&{description:Y}}})}}}),{success:!0}}),this.registerEvalHandler(A),this.config.enableAutoExtraction){A.messaging.subscribe("sync:initial:completed",async()=>{if(this.enableAutoExtraction(),!this.initialDerivationDone)this.initialDerivationDone=!0,await this.deriveAll(A);return{success:!0}});let w=async($)=>{if(!this.autoExtractionEnabled)return{success:!0};let{entityType:D,entity:Y}=$.payload;if(!this.shouldProcessEntityType(D))return{success:!0};if(!Y)return{success:!0};return await this.handleEntityChanged(A,Y),{success:!0}};A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w)}}async derive(A,Q,B){if(!this.shouldProcessEntityType(A.entityType))return;if(!this.isEntityPublished(A))return;await this.handleEntityChanged(B,A)}async deriveAll(A){let Q=await this.getEntitiesToExtract(A);if(Q.length===0){this.logger.info("No entities to extract topics from");return}this.logger.info(`Batch topic extraction: ${Q.length} entities`);let B=await Ei(Q,A,this.logger);this.logger.info("Batch topic extraction complete",B)}async rebuildAll(A){let Q=await this.getEntitiesToExtract(A),B=await this.replaceAllTopics(Q,A);this.logger.info("Topic rebuild complete",B)}isAutoExtractionEnabled(){return this.autoExtractionEnabled}hasRunInitialDerivation(){return this.initialDerivationDone}enableAutoExtraction(){if(this.config.enableAutoExtraction)this.autoExtractionEnabled=!0,this.logger.info("Auto-extraction enabled after initial sync")}shouldProcessEntityType(A){if(A==="topic")return!1;return this.config.includeEntityTypes.includes(A)}isEntityPublished(A){let B=A.metadata.status;return B==="published"||B===void 0||B===null}async replaceAllTopics(A,Q){let B=new ID(Q.entityService,this.logger),w=await B.listTopics();for(let D of w)await B.deleteTopic(D.id);if(A.length===0)return{deleted:w.length,created:0,skipped:0,batches:0};let $=await Ei(A,Q,this.logger);return{deleted:w.length,...$}}async getEntitiesToExtract(A){let Q=this.getExtractableEntityTypes(A),B=[];for(let w of Q){let $=await A.entityService.listEntities(w);for(let D of $){if(!this.isEntityPublished(D))continue;B.push(D)}}return B}getExtractableEntityTypes(A){return A.entityService.getEntityTypes().filter((B)=>this.shouldProcessEntityType(B))}async handleEntityChanged(A,Q){if(!this.isEntityPublished(Q))return;try{await A.jobs.enqueue("extract",{entityId:Q.id,entityType:Q.entityType,contentHash:Q.contentHash,minRelevanceScore:this.config.minRelevanceScore,autoMerge:this.config.autoMerge,mergeSimilarityThreshold:this.config.mergeSimilarityThreshold},null,{priority:5,source:"topics-plugin",metadata:{operationType:"data_processing",operationTarget:`topic-extraction:${Q.entityType}:${Q.id}`,pluginId:"topics"}})}catch(B){this.logger.error("Failed to queue topic extraction job",{error:L0(B),entityId:Q.id,entityType:Q.entityType})}}registerEvalHandler(A){let Q=new a_(A,this.logger),B=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.unknown()).optional()}),w=(V,E="")=>({id:`eval${E}-${Date.now()}`,entityType:V.entityType,content:V.content,contentHash:aB(V.content),metadata:V.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}),$=async(V,E,L="")=>{let k=w(V,L);return Q.extractFromEntity(k,E)},D=B.extend({minRelevanceScore:Z.number().optional()});A.eval.registerHandler("extractFromEntity",async(V)=>{let E=D.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore;return $(E,L)});let Y=Z.object({contentA:B,contentB:B,minRelevanceScore:Z.number().optional()});A.eval.registerHandler("checkMergeSimilarity",async(V)=>{let E=Y.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore,[k,_]=await Promise.all([$(E.contentA,L,"-a"),$(E.contentB,L,"-b")]),j=k.map((g)=>g.title.toLowerCase()),r=_.map((g)=>g.title.toLowerCase()),n=j.filter((g)=>r.includes(g));return{topicsA:k.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),topicsB:_.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),matchingTitles:n,wouldMerge:n.length>0}});let I=Z.object({title:Z.string(),content:Z.string()}),X=Z.object({existingTopics:Z.array(I),incomingTopic:I,threshold:Z.number().optional()});A.eval.registerHandler("detectMergeCandidate",async(V)=>{let E=X.parse(V),L=E.threshold??this.config.mergeSimilarityThreshold,k=new ID(A.entityService,this.logger);for(let j of E.existingTopics)await k.createTopic(j);let _=await k.findMergeCandidate({title:E.incomingTopic.title},L);return{found:_!==null,candidateTitle:_?.title,candidateScore:_?.score}});let H=Z.object({existingAliases:Z.array(Z.string()).optional(),canonicalTitle:Z.string(),candidateAliases:Z.array(Z.string())});A.eval.registerHandler("mergeAliases",async(V)=>{let E=H.parse(V);return{aliases:new ID(A.entityService,this.logger).mergeAliases(E.existingAliases,E.canonicalTitle,E.candidateAliases)}});let W=Z.object({existingTopics:Z.array(I.extend({aliases:Z.array(Z.string()).optional()})).default([]),incomingTopic:I.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()});A.eval.registerHandler("processTopicWithAutoMerge",async(V)=>{let E=W.parse(V),L=new ID(A.entityService,this.logger);for(let n of E.existingTopics)await L.createTopic({title:n.title,content:n.content,metadata:{aliases:n.aliases??[]}});let k=new Ci(A,this.logger),_=Lw.from(async()=>{});if(!_)throw Error("Failed to create progress reporter");let j=await k.process({topic:{title:E.incomingTopic.title,content:E.incomingTopic.content,relevanceScore:E.incomingTopic.relevanceScore??0.9},sourceEntityId:"eval-source",sourceEntityType:"post",autoMerge:!0,mergeSimilarityThreshold:E.threshold??this.config.mergeSimilarityThreshold},`eval-job-${Date.now()}`,_),r=await A.entityService.listEntities("topic");return{...j,topicCount:r.length,topics:r.map((n)=>{let g=this.adapter.parseTopicBody(n.content);return{id:n.id,title:g.title,content:g.content,metadata:n.metadata}})}});let J=Z.object({entities:Z.array(B).min(1),minRelevanceScore:Z.number().optional()}),F=Z.object({existingTopics:Z.array(I).optional(),entities:Z.array(B)});A.eval.registerHandler("rebuildTopics",async(V)=>{let E=F.parse(V),L=new ID(A.entityService,this.logger);for(let r of E.existingTopics??[])await L.createTopic(r);let k=E.entities.map((r,n)=>w(r,`-rebuild-${n}`)),_=await this.replaceAllTopics(k,A),j=await A.entityService.listEntities("topic");return{..._,topicCount:j.length,topics:j.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,metadata:r.metadata}})}}),A.eval.registerHandler("extractSequentially",async(V)=>{let E=J.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore,k=new ID(A.entityService,this.logger),_=[];for(let[r,n]of E.entities.entries()){let g=w(n,`-sequential-${r}`),T=await Q.extractFromEntity(g,L);for(let S of T)await k.createTopic({title:S.title,content:S.content});_.push({extractedTitles:T.map((S)=>S.title)})}let j=await A.entityService.listEntities("topic");return{totalTopics:j.length,perEntity:_,topics:j.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content}})}});let z=Z.object({entities:Z.array(B)});A.eval.registerHandler("batchExtract",async(V)=>{let L=z.parse(V).entities.map((j,r)=>w(j,`-batch-${r}`)),k=await Ei(L,A,this.logger),_=await A.entityService.listEntities("topic");return{...k,topics:_.map((j)=>{let r=this.adapter.parseTopicBody(j.content);return{id:j.id,title:r.title,content:r.content}})}})}}function Ri(A){return new Zv0(A)}B0();GA();B0();var zv0=Z.enum(["linkedin"]),qv0=Z.enum(["draft","queued","published","failed"]),Nv0=Z.enum(["post","deck"]),XD=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:zv0.describe("Target platform"),status:qv0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Nv0.optional().describe("Source entity type (post, deck)")}),Vv0=XD.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}")}),wE=U2.extend({entityType:Z.literal("social-post"),metadata:Vv0}),ji=wE.extend({frontmatter:XD,body:Z.string()}),ki=ji.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});B0();GA();class aGA extends E2{constructor(){super({entityType:"social-post",schema:wE,frontmatterSchema:XD,supportsCoverImage:!0})}toMarkdown(A){let Q="",B={};try{B=this.parseFrontMatter(A.content,XD),Q=this.extractBody(A.content)}catch{Q=A.content}let w={...B,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,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,XD),B=`${Q.platform}-${e1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:Q.platform,status:Q.status,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,XD)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}}var t7=new aGA;B0();B0();GA();var Dq2=mI.extend({platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),Yq2=uI.extend({query:Dq2.optional()});function Lv0(A){let Q=F2(A.content,XD);return ji.parse({...A,frontmatter:Q.metadata,body:Q.content})}class Pi extends s5{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=Yq2.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Lv0(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,B){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:B.baseUrl}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A),$=B.entityService;if(w.nextInQueue)return this.fetchNextInQueue(Q,$);if(w.id){let{item:W}=await this.fetchDetail(w.id,$);return Q.parse(this.buildDetailResult(W,null))}let D={};if(w.platform)D.platform=w.platform;if(w.status)D.status=w.status;let Y=Object.keys(D).length>0,I=w.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:X,pagination:H}=await this.fetchList(w,$,{...Y&&{filter:{metadata:D}},sortFields:I});return Q.parse(this.buildListResult(X,H,w))}async fetchNextInQueue(A,Q){let w=(await Q.listEntities(this.config.entityType,{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}))[0],$=w?Lv0(w):null;return A.parse({post:$})}}GA();var Mv0=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional()}),tGA=Z.object({linkedin:Mv0.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});B0();GA();AJA();import{jsxDEV as y6,Fragment as Hq2}from"preact/jsx-dev-runtime";function Iq2(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Xq2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var bi=({posts:A,pageTitle:Q,pagination:B,baseUrl:w="/social-posts"})=>{let $=Q??"Social Posts",D=B?.totalItems??A.length,Y=`Browse all ${D} social ${D===1?"post":"posts"}`;return y6(Hq2,{children:[y6(o2,{title:$,description:Y},void 0,!1,void 0,this),y6("div",{className:"social-post-list bg-theme",children:y6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[y6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?y6("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):y6("ul",{className:"space-y-6",children:A.map((I)=>y6("li",{children:y6(MQ,{href:I.url,variant:"horizontal",children:y6("div",{className:"flex flex-col sm:flex-row gap-4",children:[I.coverImageUrl&&y6("img",{src:I.coverImageUrl,alt:I.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),y6("div",{className:"flex-1 min-w-0",children:[y6("div",{className:"flex items-start justify-between gap-4 mb-2",children:[y6("h2",{className:"text-lg font-semibold text-heading",children:I.frontmatter.title},void 0,!1,void 0,this),y6("time",{className:"text-sm text-theme-muted shrink-0",children:Xq2(I.frontmatter.publishedAt??I.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y6("div",{className:"flex items-center gap-2 mb-3",children:[y6(n7,{status:I.frontmatter.status},void 0,!1,void 0,this),y6("span",{className:"text-xs text-theme-muted uppercase",children:I.frontmatter.platform},void 0,!1,void 0,this),y6("span",{className:"text-xs text-theme-muted font-mono",children:I.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y6("p",{className:"text-theme leading-relaxed",children:Iq2(I.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)},I.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&y6(jY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:w},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 m6,Fragment as Kq2}from"preact/jsx-dev-runtime";function Ev0(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var xi=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,B=A.body.slice(0,160),w=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return m6(Kq2,{children:[m6(o2,{title:Q,description:B},void 0,!1,void 0,this),m6("section",{className:"social-post-detail",children:m6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:m6("div",{className:"max-w-3xl mx-auto",children:[m6(QD,{items:w},void 0,!1,void 0,this),m6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),m6("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[m6(n7,{status:A.frontmatter.status},void 0,!1,void 0,this),m6("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),m6("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&&m6(bK,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),m6(MQ,{className:"p-8 mb-8",children:m6("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),m6("div",{className:"space-y-4 text-sm text-theme-muted",children:[m6("div",{children:[m6("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Ev0(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&m6("div",{children:[m6("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Ev0(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&m6("div",{children:m6("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 Qb(A){return`social-media:${A}`}var QJA=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post")}),Uq2=j7.extend({slug:Z.string().optional()});class Yz extends Q9{constructor(A,Q){super(A,Q,{schema:QJA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let B=A.platform??"linkedin",w=A.addToQueue??!1,{prompt:$,sourceEntityType:D,sourceEntityId:Y}=A,{content:I,title:X}=A;if(I&&X)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(I&&!X){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:I,templateName:Qb(B)});X=L.title,I=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&D){await this.reportProgress(Q,{progress:10,message:`Fetching source ${D}`});let L=await this.context.entityService.getEntity(D,Y);if(!L)this.failEarly(`Source entity not found: ${D}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let _=Z.object({slug:Z.string()}).safeParse(L.metadata),j=_.success?_.data.slug:Y,r=await this.context.ai.generate({prompt:`Create an engaging ${B} post to promote this ${D}:
|
|
2732
|
+
- content`,requiredPermission:"public"});s8();GA();var Qq2=Z.object({id:Z.string(),title:Z.string(),summary:Z.string(),created:Z.string(),updated:Z.string()}),t_=Z.object({topics:Z.array(Qq2),totalCount:Z.number()});import{jsxDEV as SX}from"preact/jsx-dev-runtime";var nGA=({topics:A,totalCount:Q})=>{return SX("div",{className:"topic-list-container w-full max-w-4xl mx-auto p-6 bg-theme",children:[SX(fY,{title:"Topics",count:Q,singularLabel:"topic",description:"discovered from your knowledge base"},void 0,!1,void 0,this),SX("div",{className:"space-y-6",children:A.map((B)=>SX(MQ,{variant:"vertical",children:[SX(G9,{href:`/topics/${B.id}`,className:"text-xl",children:B.title},void 0,!1,void 0,this),SX("p",{className:"text-theme-muted mb-4",children:B.summary},void 0,!1,void 0,this),SX(Y7,{children:SX("div",{className:"flex justify-between text-sm text-theme-muted",children:SX("time",{dateTime:B.updated,children:["Updated ",m8(B.updated)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},B.id,!0,void 0,this))},void 0,!1,void 0,this),A.length===0&&SX(a$,{message:"No topics discovered yet.",description:"Topics will appear here as they are extracted from your content."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();class Oi extends dB{constructor(){super(t_,{title:"Topic List",mappings:[{key:"topics",label:"Topics",type:"array",itemType:"object"},{key:"totalCount",label:"Total Count",type:"number"}]})}}var Wv0=M1({name:"topics:topic-list",description:"List view of all discovered topics",schema:t_,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Oi,layout:{component:nGA}});s8();GA();var e_=Z.object({id:Z.string(),title:Z.string(),content:Z.string(),created:Z.string(),updated:Z.string()});import{jsxDEV as Ab}from"preact/jsx-dev-runtime";var oGA=({title:A,content:Q,created:B,updated:w})=>{return Ab("article",{className:"topic-detail-container max-w-4xl mx-auto p-6 bg-theme",children:[Ab(fZ,{title:A,created:B,updated:w},void 0,!1,void 0,this),Ab("div",{className:"prose prose-lg max-w-none mb-8 text-theme-muted",children:Ab("div",{dangerouslySetInnerHTML:{__html:Q}},void 0,!1,void 0,this)},void 0,!1,void 0,this),Ab(CZ,{href:"/topics",children:"Back to Topics"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();class fi extends dB{constructor(){super(e_,{title:"Topic Detail",mappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"content",label:"Content",type:"string"},{key:"created",label:"Created",type:"string"},{key:"updated",label:"Updated",type:"string"}]})}}var Gv0=M1({name:"topics:topic-detail",description:"Detailed view of a single topic",schema:e_,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new fi,layout:{component:oGA}});B0();GA();class sGA extends s5{id="topics:entities";name="Topics Entity DataSource";description="Fetches and transforms topic entities for rendering";config={entityType:"topic",defaultSort:[{field:"updated",direction:"desc"}],defaultLimit:100,lookupField:"id"};adapter=new w4;constructor(A){super(A);this.logger.debug("TopicsDataSource initialized")}transformEntity(A){let Q=this.adapter.parseTopicBody(A.content);return{id:A.id,title:Q.title,summary:FW(Q.content,200),created:A.created,updated:A.updated}}buildListResult(A,Q,B){return{topics:A,totalCount:A.length}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A);if(w.id){let D=await B.entityService.getEntity(this.config.entityType,w.id);if(!D)throw Error(`Entity not found: ${w.id}`);let Y=this.adapter.parseTopicBody(D.content);return Q.parse({id:D.id,title:Y.title,content:Y.content,created:D.created,updated:D.updated})}return super.fetch(A,Q,B)}}aD();function Jv0(){let A=new w4;return async(Q)=>{if(!Q.hasEntityType("topic"))return{topics:[]};return{topics:(await Q.listEntities("topic")).map(($)=>{let D=A.parseTopicBody($.content);return{topic:$.id,title:D.title}})}}}var Fv0={name:"@brains/topics",private:!0,version:"0.2.0-alpha.38",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/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","@types/node":"^20.0.0",typescript:"^5.3.3"}};var wq2=new w4;function $q2(A){let Q=A.replace(/\s+/g," ").trim();if(!Q)return;let B=Q.match(/^(.*?[.!?])(?:\s|$)/);if(B?.[1])return B[1];return Q.length<=200?Q:`${Q.slice(0,197)}\u2026`}class Zv0 extends HQ{entityType="topic";schema=Vi;adapter=wq2;autoExtractionEnabled=!1;initialDerivationDone=!1;constructor(A={}){super("topics",Fv0,A,tT0)}getEntityTypeConfig(){return{weight:0.5}}getTemplates(){return{extraction:Kv0,"merge-synthesis":Uv0,"topic-list":Wv0,"topic-detail":Gv0}}getDataSources(){return[new sGA(this.logger.child("TopicsDataSource"))]}async onRegister(A){let Q=new Ci(A,this.logger);A.jobs.registerHandler("process-single",Q);let B=new rGA(A,this.logger);if(A.jobs.registerHandler("extract",B),A.insights.register("topic-distribution",Jv0()),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"topics",pluginId:this.id,title:"Topics",section:"secondary",priority:20,rendererName:"ListWidget",dataProvider:async()=>{return{items:(await A.entityService.listEntities("topic",{limit:10,sortFields:[{field:"updated",direction:"desc"}]})).map(($)=>{let D=this.adapter.parseTopicBody($.content),Y=$q2(D.content);return{id:$.id,name:D.title||$.id,...Y&&{description:Y}}})}}}),{success:!0}}),this.registerEvalHandler(A),this.config.enableAutoExtraction){A.messaging.subscribe("sync:initial:completed",async()=>{if(this.enableAutoExtraction(),!this.initialDerivationDone)this.initialDerivationDone=!0,await this.deriveAll(A);return{success:!0}});let w=async($)=>{if(!this.autoExtractionEnabled)return{success:!0};let{entityType:D,entity:Y}=$.payload;if(!this.shouldProcessEntityType(D))return{success:!0};if(!Y)return{success:!0};return await this.handleEntityChanged(A,Y),{success:!0}};A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w)}}async derive(A,Q,B){if(!this.shouldProcessEntityType(A.entityType))return;if(!this.isEntityPublished(A))return;await this.handleEntityChanged(B,A)}async deriveAll(A){let Q=await this.getEntitiesToExtract(A);if(Q.length===0){this.logger.info("No entities to extract topics from");return}this.logger.info(`Batch topic extraction: ${Q.length} entities`);let B=await Ei(Q,A,this.logger);this.logger.info("Batch topic extraction complete",B)}async rebuildAll(A){let Q=await this.getEntitiesToExtract(A),B=await this.replaceAllTopics(Q,A);this.logger.info("Topic rebuild complete",B)}isAutoExtractionEnabled(){return this.autoExtractionEnabled}hasRunInitialDerivation(){return this.initialDerivationDone}enableAutoExtraction(){if(this.config.enableAutoExtraction)this.autoExtractionEnabled=!0,this.logger.info("Auto-extraction enabled after initial sync")}shouldProcessEntityType(A){if(A==="topic")return!1;return this.config.includeEntityTypes.includes(A)}isEntityPublished(A){let B=A.metadata.status;return B==="published"||B===void 0||B===null}async replaceAllTopics(A,Q){let B=new ID(Q.entityService,this.logger),w=await B.listTopics();for(let D of w)await B.deleteTopic(D.id);if(A.length===0)return{deleted:w.length,created:0,skipped:0,batches:0};let $=await Ei(A,Q,this.logger);return{deleted:w.length,...$}}async getEntitiesToExtract(A){let Q=this.getExtractableEntityTypes(A),B=[];for(let w of Q){let $=await A.entityService.listEntities(w);for(let D of $){if(!this.isEntityPublished(D))continue;B.push(D)}}return B}getExtractableEntityTypes(A){return A.entityService.getEntityTypes().filter((B)=>this.shouldProcessEntityType(B))}async handleEntityChanged(A,Q){if(!this.isEntityPublished(Q))return;try{await A.jobs.enqueue("extract",{entityId:Q.id,entityType:Q.entityType,contentHash:Q.contentHash,minRelevanceScore:this.config.minRelevanceScore,autoMerge:this.config.autoMerge,mergeSimilarityThreshold:this.config.mergeSimilarityThreshold},null,{priority:5,source:"topics-plugin",metadata:{operationType:"data_processing",operationTarget:`topic-extraction:${Q.entityType}:${Q.id}`,pluginId:"topics"}})}catch(B){this.logger.error("Failed to queue topic extraction job",{error:L0(B),entityId:Q.id,entityType:Q.entityType})}}registerEvalHandler(A){let Q=new a_(A,this.logger),B=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.unknown()).optional()}),w=(V,E="")=>({id:`eval${E}-${Date.now()}`,entityType:V.entityType,content:V.content,contentHash:aB(V.content),metadata:V.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}),$=async(V,E,L="")=>{let k=w(V,L);return Q.extractFromEntity(k,E)},D=B.extend({minRelevanceScore:Z.number().optional()});A.eval.registerHandler("extractFromEntity",async(V)=>{let E=D.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore;return $(E,L)});let Y=Z.object({contentA:B,contentB:B,minRelevanceScore:Z.number().optional()});A.eval.registerHandler("checkMergeSimilarity",async(V)=>{let E=Y.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore,[k,_]=await Promise.all([$(E.contentA,L,"-a"),$(E.contentB,L,"-b")]),j=k.map((g)=>g.title.toLowerCase()),r=_.map((g)=>g.title.toLowerCase()),n=j.filter((g)=>r.includes(g));return{topicsA:k.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),topicsB:_.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),matchingTitles:n,wouldMerge:n.length>0}});let I=Z.object({title:Z.string(),content:Z.string()}),X=Z.object({existingTopics:Z.array(I),incomingTopic:I,threshold:Z.number().optional()});A.eval.registerHandler("detectMergeCandidate",async(V)=>{let E=X.parse(V),L=E.threshold??this.config.mergeSimilarityThreshold,k=new ID(A.entityService,this.logger);for(let j of E.existingTopics)await k.createTopic(j);let _=await k.findMergeCandidate({title:E.incomingTopic.title},L);return{found:_!==null,candidateTitle:_?.title,candidateScore:_?.score}});let H=Z.object({existingAliases:Z.array(Z.string()).optional(),canonicalTitle:Z.string(),candidateAliases:Z.array(Z.string())});A.eval.registerHandler("mergeAliases",async(V)=>{let E=H.parse(V);return{aliases:new ID(A.entityService,this.logger).mergeAliases(E.existingAliases,E.canonicalTitle,E.candidateAliases)}});let W=Z.object({existingTopics:Z.array(I.extend({aliases:Z.array(Z.string()).optional()})).default([]),incomingTopic:I.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()});A.eval.registerHandler("processTopicWithAutoMerge",async(V)=>{let E=W.parse(V),L=new ID(A.entityService,this.logger);for(let n of E.existingTopics)await L.createTopic({title:n.title,content:n.content,metadata:{aliases:n.aliases??[]}});let k=new Ci(A,this.logger),_=Lw.from(async()=>{});if(!_)throw Error("Failed to create progress reporter");let j=await k.process({topic:{title:E.incomingTopic.title,content:E.incomingTopic.content,relevanceScore:E.incomingTopic.relevanceScore??0.9},sourceEntityId:"eval-source",sourceEntityType:"post",autoMerge:!0,mergeSimilarityThreshold:E.threshold??this.config.mergeSimilarityThreshold},`eval-job-${Date.now()}`,_),r=await A.entityService.listEntities("topic");return{...j,topicCount:r.length,topics:r.map((n)=>{let g=this.adapter.parseTopicBody(n.content);return{id:n.id,title:g.title,content:g.content,metadata:n.metadata}})}});let J=Z.object({entities:Z.array(B).min(1),minRelevanceScore:Z.number().optional()}),F=Z.object({existingTopics:Z.array(I).optional(),entities:Z.array(B)});A.eval.registerHandler("rebuildTopics",async(V)=>{let E=F.parse(V),L=new ID(A.entityService,this.logger);for(let r of E.existingTopics??[])await L.createTopic(r);let k=E.entities.map((r,n)=>w(r,`-rebuild-${n}`)),_=await this.replaceAllTopics(k,A),j=await A.entityService.listEntities("topic");return{..._,topicCount:j.length,topics:j.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,metadata:r.metadata}})}}),A.eval.registerHandler("extractSequentially",async(V)=>{let E=J.parse(V),L=E.minRelevanceScore??this.config.minRelevanceScore,k=new ID(A.entityService,this.logger),_=[];for(let[r,n]of E.entities.entries()){let g=w(n,`-sequential-${r}`),T=await Q.extractFromEntity(g,L);for(let S of T)await k.createTopic({title:S.title,content:S.content});_.push({extractedTitles:T.map((S)=>S.title)})}let j=await A.entityService.listEntities("topic");return{totalTopics:j.length,perEntity:_,topics:j.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content}})}});let z=Z.object({entities:Z.array(B)});A.eval.registerHandler("batchExtract",async(V)=>{let L=z.parse(V).entities.map((j,r)=>w(j,`-batch-${r}`)),k=await Ei(L,A,this.logger),_=await A.entityService.listEntities("topic");return{...k,topics:_.map((j)=>{let r=this.adapter.parseTopicBody(j.content);return{id:j.id,title:r.title,content:r.content}})}})}}function Ri(A){return new Zv0(A)}B0();GA();B0();var zv0=Z.enum(["linkedin"]),qv0=Z.enum(["draft","queued","published","failed"]),Nv0=Z.enum(["post","deck"]),XD=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:zv0.describe("Target platform"),status:qv0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Nv0.optional().describe("Source entity type (post, deck)")}),Vv0=XD.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}")}),wE=U2.extend({entityType:Z.literal("social-post"),metadata:Vv0}),ji=wE.extend({frontmatter:XD,body:Z.string()}),ki=ji.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});B0();GA();class aGA extends E2{constructor(){super({entityType:"social-post",schema:wE,frontmatterSchema:XD,supportsCoverImage:!0})}toMarkdown(A){let Q="",B={};try{B=this.parseFrontMatter(A.content,XD),Q=this.extractBody(A.content)}catch{Q=A.content}let w={...B,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,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,XD),B=`${Q.platform}-${e1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:Q.platform,status:Q.status,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,XD)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}}var t7=new aGA;B0();B0();GA();var Dq2=mI.extend({platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),Yq2=uI.extend({query:Dq2.optional()});function Lv0(A){let Q=F2(A.content,XD);return ji.parse({...A,frontmatter:Q.metadata,body:Q.content})}class Pi extends s5{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=Yq2.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Lv0(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,B){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:B.baseUrl}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A),$=B.entityService;if(w.nextInQueue)return this.fetchNextInQueue(Q,$);if(w.id){let{item:W}=await this.fetchDetail(w.id,$);return Q.parse(this.buildDetailResult(W,null))}let D={};if(w.platform)D.platform=w.platform;if(w.status)D.status=w.status;let Y=Object.keys(D).length>0,I=w.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:X,pagination:H}=await this.fetchList(w,$,{...Y&&{filter:{metadata:D}},sortFields:I});return Q.parse(this.buildListResult(X,H,w))}async fetchNextInQueue(A,Q){let w=(await Q.listEntities(this.config.entityType,{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}))[0],$=w?Lv0(w):null;return A.parse({post:$})}}GA();var Mv0=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional()}),tGA=Z.object({linkedin:Mv0.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});B0();GA();AJA();import{jsxDEV as y6,Fragment as Hq2}from"preact/jsx-dev-runtime";function Iq2(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Xq2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var bi=({posts:A,pageTitle:Q,pagination:B,baseUrl:w="/social-posts"})=>{let $=Q??"Social Posts",D=B?.totalItems??A.length,Y=`Browse all ${D} social ${D===1?"post":"posts"}`;return y6(Hq2,{children:[y6(o2,{title:$,description:Y},void 0,!1,void 0,this),y6("div",{className:"social-post-list bg-theme",children:y6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[y6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?y6("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):y6("ul",{className:"space-y-6",children:A.map((I)=>y6("li",{children:y6(MQ,{href:I.url,variant:"horizontal",children:y6("div",{className:"flex flex-col sm:flex-row gap-4",children:[I.coverImageUrl&&y6("img",{src:I.coverImageUrl,alt:I.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),y6("div",{className:"flex-1 min-w-0",children:[y6("div",{className:"flex items-start justify-between gap-4 mb-2",children:[y6("h2",{className:"text-lg font-semibold text-heading",children:I.frontmatter.title},void 0,!1,void 0,this),y6("time",{className:"text-sm text-theme-muted shrink-0",children:Xq2(I.frontmatter.publishedAt??I.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y6("div",{className:"flex items-center gap-2 mb-3",children:[y6(n7,{status:I.frontmatter.status},void 0,!1,void 0,this),y6("span",{className:"text-xs text-theme-muted uppercase",children:I.frontmatter.platform},void 0,!1,void 0,this),y6("span",{className:"text-xs text-theme-muted font-mono",children:I.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y6("p",{className:"text-theme leading-relaxed",children:Iq2(I.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)},I.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&y6(jY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:w},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 m6,Fragment as Kq2}from"preact/jsx-dev-runtime";function Ev0(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var xi=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,B=A.body.slice(0,160),w=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return m6(Kq2,{children:[m6(o2,{title:Q,description:B},void 0,!1,void 0,this),m6("section",{className:"social-post-detail",children:m6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:m6("div",{className:"max-w-3xl mx-auto",children:[m6(QD,{items:w},void 0,!1,void 0,this),m6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),m6("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[m6(n7,{status:A.frontmatter.status},void 0,!1,void 0,this),m6("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),m6("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&&m6(bK,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),m6(MQ,{className:"p-8 mb-8",children:m6("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),m6("div",{className:"space-y-4 text-sm text-theme-muted",children:[m6("div",{children:[m6("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Ev0(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&m6("div",{children:[m6("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Ev0(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&m6("div",{children:m6("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 Qb(A){return`social-media:${A}`}var QJA=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post")}),Uq2=j7.extend({slug:Z.string().optional()});class Yz extends Q9{constructor(A,Q){super(A,Q,{schema:QJA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let B=A.platform??"linkedin",w=A.addToQueue??!1,{prompt:$,sourceEntityType:D,sourceEntityId:Y}=A,{content:I,title:X}=A;if(I&&X)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(I&&!X){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:I,templateName:Qb(B)});X=L.title,I=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&D){await this.reportProgress(Q,{progress:10,message:`Fetching source ${D}`});let L=await this.context.entityService.getEntity(D,Y);if(!L)this.failEarly(`Source entity not found: ${D}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let _=Z.object({slug:Z.string()}).safeParse(L.metadata),j=_.success?_.data.slug:Y,r=await this.context.ai.generate({prompt:`Create an engaging ${B} post to promote this ${D}:
|
|
2732
2733
|
|
|
2733
2734
|
Source: ${D}/${j}
|
|
2734
2735
|
|
|
2735
2736
|
${L.content}`,templateName:Qb(B)});X=r.title,I=r.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:Qb(B)});X=L.title,I=L.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!I||!X)this.failEarly("Content or title was not generated");let W={title:X,platform:B,status:w?"queued":"draft",...Y&&{sourceEntityId:Y},...D&&{sourceEntityType:D}},J=t7.createPostContent(W,I),z=t7.fromMarkdown(J).metadata;if(!z)this.failEarly("Failed to parse social post metadata");let V=await iH({entityType:"social-post",title:X,deriveId:(L)=>`${B}-${e1(L)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),E=J;if(V!==X){z.title=V,z.slug=`${B}-${e1(V)}`;let L={...W,title:V};E=t7.createPostContent(L,I)}return{id:z.slug,content:E,metadata:z,title:V,resultExtras:{slug:z.slug},createOptions:{deduplicateId:!0}}}async onGenerationFailure(A,Q){await this.context.messaging.send("generate:report:failure",{entityType:"social-post",error:Q})}async afterCreate(A,Q,B,w){if(A.generateImage){await this.reportProgress(B,{progress:90,message:"Queueing image generation"});let $=w.title??"Social Post";await this.context.jobs.enqueue("image:image-generate",{prompt:`Social media graphic for: ${$}`,title:`${$} Image`,aspectRatio:"16:9",targetEntityType:"social-post",targetEntityId:Q},{interfaceType:"job",userId:"system"})}await this.context.messaging.send("generate:report:success",{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}}}class BJA{config;logger;name="linkedin";apiBaseUrl="https://api.linkedin.com/v2";cachedUserId=null;constructor(A,Q){this.config=A;this.logger=Q}async publish(A,Q,B){if(!this.config.accessToken)throw Error("LinkedIn access token not configured");let w=await this.getAuthor(),$=null;if(B)$=await this.uploadImage(w,B);let D={shareCommentary:{text:A},shareMediaCategory:$?"IMAGE":"NONE",...$&&{media:[{status:"READY",media:$}]}},Y=await 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:w,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":D},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!Y.ok){let H=await Y.text();throw this.logger.error("LinkedIn API error",{status:Y.status,error:H}),Error(`LinkedIn API error: ${Y.status} - ${H}`)}let I=Y.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:I,hasImage:!!$});let X={id:I};if(I)X.url=`https://www.linkedin.com/feed/update/${I}`;return X}async uploadImage(A,Q){try{let B=await 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(!B.ok){let I=await B.text();return this.logger.warn("LinkedIn image upload registration failed",{status:B.status,error:I}),null}let w=await B.json(),$=w.value.uploadMechanism["com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"].uploadUrl,D=w.value.asset,Y=await fetch($,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!Y.ok)return this.logger.warn("LinkedIn image binary upload failed",{status:Y.status}),null;return this.logger.info("LinkedIn image uploaded",{assetUrn:D}),D}catch(B){return this.logger.warn("LinkedIn image upload error",{error:B}),null}}async validateCredentials(){if(!this.config.accessToken)return!1;try{if(this.config.organizationId)return(await 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 B=await fetch("https://api.linkedin.com/v2/userinfo",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(B.ok){let w=await B.json();return this.cachedUserId=`urn:li:person:${w.sub}`,this.cachedUserId}}catch{}let A=await fetch("https://api.linkedin.com/v2/me",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(!A.ok){let B=await A.text();throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${B}`)}let Q=await A.json();return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function wJA(A,Q){return new BJA(A,Q)}B0();GA();s8();AJA();var Wq2=Z.object({posts:Z.array(ki),totalCount:Z.number().optional(),pagination:_7.nullable(),baseUrl:Z.string().optional()}),Gq2=Z.object({post:ki});function Cv0(){return{linkedin:_i,"social-post-list":M1({name:"social-post-list",description:"Social post list page template",schema:Wq2,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:bi}}),"social-post-detail":M1({name:"social-post-detail",description:"Individual social post template",schema:Gq2,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:xi}})}}GA();var Jq2=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),platform:Z.enum(["linkedin"]).default("linkedin")}),Fq2=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),title:Z.string().optional(),platform:Z.enum(["linkedin"]).optional()});function Ov0(A){A.eval.registerHandler("generation",async(Q)=>{let B=Jq2.parse(Q),w=B.content?`Create an engaging LinkedIn post to share this content:
|
|
2736
2737
|
|
|
2737
|
-
${B.content}`:B.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${B.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let B=Fq2.parse(Q),w=[],$=Lw.from(async(H)=>{let W={progress:H.progress};if(H.message!==void 0)W.message=H.message;w.push(W)});if(!$)throw Error("Failed to create progress reporter");let Y=await new Yz(A.logger,A).process(B,`eval-${Date.now()}`,$),I=!1,X;if(Y.success&&Y.entityId){let H=await A.entityService.getEntity("social-post",Y.entityId);I=!!H,X=H?.content.slice(0,300)}return{...Y,entityExists:I,entityPreview:X,progressSteps:w}})}GA();B0();class Bb{sendMessage;logger;entityService;providers;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers}async handle(A){let{entityType:Q,entityId:B}=A;if(Q!=="social-post")return;this.logger.debug("Handling publish:execute",{entityId:B});try{let w=await this.entityService.getEntity("social-post",B);if(!w){await this.reportFailure(Q,B,`Post not found: ${B}`);return}if(w.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:B});return}let $=w.metadata.platform,D=this.providers.get($);if(!D){await this.reportFailure(Q,B,`No provider configured for platform: ${$}`);return}let Y=F2(w.content,XD),I;if(Y.metadata.coverImageId)I=await this.fetchImageData(Y.metadata.coverImageId);try{let X=await D.publish(Y.content,w.metadata,I),H=new Date().toISOString(),W=X.id||void 0,J={...Y.metadata,status:"published",publishedAt:H,...W&&{platformPostId:W}},F=t7.createPostContent(J,Y.content);await this.entityService.updateEntity({...w,content:F,metadata:{...w.metadata,status:"published",publishedAt:H,platformPostId:W}}),await this.reportSuccess(Q,B,X.id),this.logger.info(`Post published successfully: ${B}`,{platform:$,platformPostId:W})}catch(X){let H=X instanceof Error?X.message:String(X),W={...Y.metadata,status:"failed"},J=t7.createPostContent(W,Y.content);await this.entityService.updateEntity({...w,content:J,metadata:{...w.metadata,status:"failed"}}),await this.reportFailure(Q,B,H),this.logger.error(`Post publish failed: ${B}`,{platform:$,error:H})}}catch(w){let $=L0(w);this.logger.error("Unexpected error in publish handler",{entityId:B,error:$}),await this.reportFailure(Q,B,$)}}async reportSuccess(A,Q,B){await this.sendMessage("publish:report:success",{entityType:A,entityId:Q,result:{id:B}})}async reportFailure(A,Q,B){await this.sendMessage("publish:report:failure",{entityType:A,entityId:Q,error:B})}async fetchImageData(A){try{let Q=await this.entityService.getEntity("image",A);if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let w=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!w?.[1]||!w[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=w[1],D=w[2];return{data:Buffer.from(D,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function fv0(A,Q,B){if(Q.size===0){B.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let w=Q.values().next().value;return await A.messaging.send("publish:register",{entityType:"social-post",provider:w}),B.info("Registered social-post with publish-pipeline"),{success:!0}})}function Rv0(A,Q,B){let w=new Bb({sendMessage:A.messaging.send,logger:B.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q});A.messaging.subscribe("publish:execute",async($)=>{return await w.handle($.payload),{success:!0}}),B.debug("Subscribed to publish:execute messages")}GA();function jv0(A,Q){A.messaging.subscribe("entity:updated",async(B)=>{let{entityType:w,entityId:$,entity:D}=B.payload;if(w!=="post")return{success:!0};if(D.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities("social-post",{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("social:auto-generate",{sourceEntityType:w,sourceEntityId:$,platform:"linkedin"}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(I){let X=L0(I);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:X}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function kv0(A,Q){A.messaging.subscribe("social:auto-generate",async(B)=>{let{sourceEntityType:w,sourceEntityId:$,platform:D}=B.payload;try{let Y=await A.jobs.enqueue(`${t7.entityType}:generation`,{sourceEntityType:w,sourceEntityId:$,platform:D,addToQueue:!1},{interfaceType:"job",userId:"system"});return Q.info(`Social post generation job enqueued for ${w}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let I=L0(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:I}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Pv0(A,Q){A.messaging.subscribe("generate:execute",async(B)=>{let{entityType:w}=B.payload;if(w!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities("post",{filter:{metadata:{status:"published"}},limit:5});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:"No published posts available for social post generation"}),{success:!0};let D=null;for(let I of $)if((await A.entityService.listEntities("social-post",{filter:{metadata:{sourceEntityType:"post",sourceEntityId:I.id}},limit:1})).length===0){D=I;break}if(!D)return Q.info("All recent posts already have social posts"),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:"All recent posts already have social posts generated"}),{success:!0};let Y=await A.jobs.enqueue(`${t7.entityType}:generation`,{sourceEntityType:"post",sourceEntityId:D.id,platform:"linkedin",addToQueue:!1},{interfaceType:"job",userId:"system"});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:D.id}),{success:!0}}catch($){let D=L0($);return Q.error("Failed to handle generate:execute:",{error:D}),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:D}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}var _v0={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.37",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/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 $JA extends HQ{entityType=t7.entityType;schema=wE;adapter=t7;providers=new Map;constructor(A){super("social-media",_v0,A,tGA)}createGenerationHandler(A){return new Yz(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Cv0()}getDataSources(){return[new Pi(this.logger.child("SocialPostDataSource"))]}async onRegister(A){if(this.initializeProviders(),fv0(A,this.providers,this.logger),Rv0(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)jv0(A,this.logger),kv0(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Pv0(A,this.logger),Ov0(A),this.logger.info("Social media plugin registered successfully")}async derive(A,Q,B){if(A.metadata.status!=="published")return;await B.jobs.enqueue(`${this.entityType}:generation`,{sourceEntityId:A.id,sourceEntityType:A.entityType},null,{priority:5,source:"social-media-plugin",metadata:{operationType:"content_operations",operationTarget:`social-post:${A.entityType}:${A.id}`,pluginId:"social-media"}})}initializeProviders(){if(this.config.linkedin?.accessToken){let A=wJA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function wb(A){return new $JA(A)}GA();var zq2=Z.enum(["draft","queued","published","failed"]),t5B=Z.object({status:zq2.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class DJA{name="internal";async publish(A,Q){return{id:"internal"}}}var u6={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",EXECUTE:"publish:execute",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},hX={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"};GA();var qq2=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),bv0=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),qq2).optional(),maxRetries:Z.number().optional().default(3),retryBaseDelayMs:Z.number().optional().default(5000)});class gX{static instance=null;queues=new Map;static getInstance(){return gX.instance??=new gX,gX.instance}static resetInstance(){gX.instance=null}static createFresh(){return new gX}constructor(){}async add(A,Q){let B=this.getOrCreateQueue(A),w=B.find((Y)=>Y.entityId===Q);if(w)return{position:w.position};let $=B.length+1,D={entityId:Q,entityType:A,position:$,queuedAt:new Date().toISOString()};return B.push(D),{position:$}}async remove(A,Q){let B=this.queues.get(A);if(!B)return;let w=B.findIndex(($)=>$.entityId===Q);if(w===-1)return;B.splice(w,1),this.recalculatePositions(B)}async reorder(A,Q,B){let w=this.queues.get(A);if(!w)return;let $=w.findIndex((I)=>I.entityId===Q);if($===-1)return;let[D]=w.splice($,1);if(!D)return;let Y=Math.max(0,Math.min(B-1,w.length));w.splice(Y,0,D),this.recalculatePositions(w)}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 B=Q[0];if(!B)continue;if(!A||B.queuedAt<A.queuedAt)A=B}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let B=Q.shift()??null;if(B)this.recalculatePositions(Q);return B}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,B]of this.queues.entries())if(B.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,B)=>{Q.position=B+1})}}class yX{static instance=null;providers=new Map;defaultProvider=new DJA;static getInstance(){return yX.instance??=new yX,yX.instance}static resetInstance(){yX.instance=null}static createFresh(){return new yX}constructor(){}register(A,Q){this.providers.set(A,Q)}get(A){return this.providers.get(A)??this.defaultProvider}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}GA();GA();async function xv0(A,Q){let B={entityType:A.entityType,entityId:A.entityId};if(Q.messageBus)await Q.messageBus.send(u6.EXECUTE,B,"publish-service");Q.onExecute?.(B)}async function Tv0(A,Q){let B=Q.providerRegistry.get(A.entityType);if(!Q.entityService){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"EntityService not available for provider mode",retryCount:0,willRetry:!1});return}let w=await Q.entityService.getEntity(A.entityType,A.entityId);if(!w){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:`Entity not found: ${A.entityType}/${A.entityId}`,retryCount:0,willRetry:!1});return}try{let $=await B.publish(w.content,w.metadata);Q.retryTracker.clearRetries(A.entityId),Q.onPublish?.({entityType:A.entityType,entityId:A.entityId,result:$})}catch($){let D=L0($);Q.retryTracker.recordFailure(A.entityId,D);let Y=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1})}}function vv0(A,Q,B,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send(u6.COMPLETED,{entityType:A,entityId:Q,result:B},"publish-service");w.onPublish?.({entityType:A,entityId:Q,result:B})}function Sv0(A,Q,B,w){w.retryTracker.recordFailure(Q,B);let $=w.retryTracker.getRetryInfo(Q),D={entityType:A,entityId:Q,error:B,retryCount:$?.retryCount??1,willRetry:$?.willRetry??!1};if(w.messageBus)w.messageBus.send(u6.FAILED,D,"publish-service");w.onFailed?.(D)}async function hv0(A,Q){let B=Q.generationConditions[A];if(B&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,B);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send(hX.SKIPPED,{entityType:A,reason:$.reason??"Conditions not met"},"content-pipeline");return}}let w={entityType:A};if(Q.messageBus)await Q.messageBus.send(hX.EXECUTE,w,"content-pipeline");Q.onGenerate?.(w)}function gv0(A,Q,B){if(B)B.send(hX.COMPLETED,{entityType:A,entityId:Q},"content-pipeline")}function yv0(A,Q,B){if(B)B.send(hX.FAILED,{entityType:A,error:Q},"content-pipeline")}var Nq2=1000;class lY{static instance=null;config;publishJobs=new Map;generationJobs=new Map;immediateIntervalJob=null;running=!1;static getInstance(A){return lY.instance??=new lY(A),lY.instance}static resetInstance(){if(lY.instance)lY.instance.stop();lY.instance=null}static createFresh(A){return new lY(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions()}async start(){if(this.running)return;this.running=!0;for(let[A,Q]of Object.entries(this.entitySchedules)){let B=this.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,B)}for(let[A,Q]of Object.entries(this.generationSchedules)){let B=this.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,B)}this.immediateIntervalJob=this.config.backend.scheduleInterval(Nq2,()=>this.processUnscheduledTypes())}async stop(){if(this.running=!1,this.stopAndClearJobs(this.publishJobs),this.stopAndClearJobs(this.generationJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}isRunning(){return this.running}async processEntityType(A){if(!this.running)return;try{let Q=await this.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.running)return;try{let A=await this.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let B=await this.config.queueManager.getNext(Q);if(B){await this.processEntry(B);break}}}catch(A){this.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){if(await this.config.queueManager.remove(A.entityType,A.entityId),this.config.messageBus!==void 0)await xv0(A,this.publishDeps);else await Tv0(A,this.publishDeps)}completePublish(A,Q,B){vv0(A,Q,B,this.publishDeps)}failPublish(A,Q,B){Sv0(A,Q,B,this.publishDeps)}async publishDirect(A,Q,B,w){return this.config.providerRegistry.get(A).publish(B,w)}async handleTriggerGeneration(A){if(!this.running)return;try{await hv0(A,this.generationDeps)}catch(Q){this.config.logger.error(`Generation trigger error for ${A}:`,Q)}}completeGeneration(A,Q){gv0(A,Q,this.config.messageBus)}failGeneration(A,Q){yv0(A,Q,this.config.messageBus)}stopAndClearJobs(A){for(let Q of A.values())Q.stop();A.clear()}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{providerRegistry:this.config.providerRegistry,retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,entityService:this.config.entityService,onExecute:this.config.onExecute,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,B){try{this.config.backend.validateCron(Q)}catch(w){throw Error(`Invalid ${B} cron expression for ${A}: "${Q}" - ${L0(w)}`)}}}var mv0={maxRetries:3,baseDelayMs:5000};class mX{static instance=null;retries=new Map;config;static getInstance(A){return mX.instance??=new mX(A??mv0),mX.instance}static resetInstance(){mX.instance=null}static createFresh(A){return new mX(A??mv0)}constructor(A){this.config=A}recordFailure(A,Q){let w=(this.retries.get(A)?.retryCount??0)+1,$=this.config.baseDelayMs*Math.pow(2,w-1),D=Date.now()+$;this.retries.set(A,{entityId:A,retryCount:w,lastError:Q,nextRetryAt:D})}shouldRetry(A){let Q=this.retries.get(A);if(!Q)return!1;return Q.retryCount<this.config.maxRetries}isReadyForRetry(A){let Q=this.retries.get(A);if(!Q)return!1;return Date.now()>=Q.nextRetryAt}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,nextRetryAt:Q.nextRetryAt,willRetry:Q.retryCount<this.config.maxRetries}}}function N9(A,Q,B,w,$,D,Y,I){return N9.fromTZ(N9.tp(A,Q,B,w,$,D,Y),I)}N9.fromTZISO=(A,Q,B)=>N9.fromTZ(Vq2(A,Q),B);N9.fromTZ=function(A,Q){let B=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),w=YJA(A.tz,B),$=new Date(B.getTime()-w),D=YJA(A.tz,$);if(D-w===0)return $;{let Y=new Date(B.getTime()-D),I=YJA(A.tz,Y);if(I-D===0)return Y;if(!Q&&I-D>0)return Y;if(Q)throw Error("Invalid date passed to fromTZ()");return $}};N9.toTZ=function(A,Q){let B=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),w=new Date(B);return{y:w.getFullYear(),m:w.getMonth()+1,d:w.getDate(),h:w.getHours(),i:w.getMinutes(),s:w.getSeconds(),tz:Q}};N9.tp=(A,Q,B,w,$,D,Y)=>({y:A,m:Q,d:B,h:w,i:$,s:D,tz:Y});function YJA(A,Q=new Date){let B=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],w=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${w} GMT`)-Date.parse(`${w} ${B}`)}function Vq2(A,Q){let B=new Date(Date.parse(A));if(isNaN(B))throw Error("minitz: Invalid ISO8601 passed to parser.");let w=A.substring(9);return A.includes("Z")||w.includes("-")||w.includes("+")?N9.tp(B.getUTCFullYear(),B.getUTCMonth()+1,B.getUTCDate(),B.getUTCHours(),B.getUTCMinutes(),B.getUTCSeconds(),"Etc/UTC"):N9.tp(B.getFullYear(),B.getMonth()+1,B.getDate(),B.getHours(),B.getMinutes(),B.getSeconds(),Q)}N9.minitz=N9;var IJA=32,Db=31|IJA,pv0=[1,2,4,8,16],uv0=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 HD(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,Db),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,B,w){let $=this[A],D=A==="day"&&this.lastDayOfMonth;if(Q===""&&!D)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(w);let Y=Q.split(",");if(Y.length>1)for(let I=0;I<Y.length;I++)this.partToArray(A,Y[I],B,w);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,B,w):Q.indexOf("-")!==-1?this.handleRange(Q,A,B,w):Q.indexOf("/")!==-1?this.handleStepping(Q,A,B,w):Q!==""&&this.handleNumber(Q,A,B,w)}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,B,w){let $=this.extractNth(A,Q),D=parseInt($[0],10)+B;if(isNaN(D))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,D,$[1]||w)}setPart(A,Q,B){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,B);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]=B}handleRangeWithStepping(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(D===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,I,X]=D,H=parseInt(Y,10)+B,W=parseInt(I,10)+B,J=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(J))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(J===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(J>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 F=H;F<=W;F+=J)this.setPart(Q,F,$[1]||w)}extractNth(A,Q){let B=A,w;if(B.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");w=B.split("#")[1],B=B.split("#")[0]}return[B,w]}handleRange(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].split("-");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(D[0],10)+B,I=parseInt(D[1],10)+B;if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(I))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(Y>I)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let X=Y;X<=I;X++)this.setPart(Q,X,$[1]||w)}handleStepping(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].split("/");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");D[0]===""&&(D[0]="*");let Y=0;D[0]!=="*"&&(Y=parseInt(D[0],10)+B);let I=parseInt(D[1],10);if(isNaN(I))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(I===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(I>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let X=Y;X<this[Q].length;X+=I)this.setPart(Q,X,$[1]||w)}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]|IJA;else if(Q===Db)this.dayOfWeek[A]=Db;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|pv0[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},cv0=[31,28,31,30,31,30,31,31,30,31,30,31],QU=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],HD=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,B){if(this.tz=B,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,B,w,$){let D=new Date(Date.UTC(Q,B,w)).getUTCDay(),Y=0;for(let I=1;I<=w;I++)new Date(Date.UTC(Q,B,I)).getUTCDay()===D&&Y++;if($&Db&&pv0[Y-1]&$)return!0;if($&IJA){let I=new Date(Date.UTC(Q,B+1,0)).getUTCDate();for(let X=w+1;X<=I;X++)if(new Date(Date.UTC(Q,B,X)).getUTCDay()===D)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 B=N9.toTZ(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=B.s,this.minute=B.i,this.hour=B.h,this.day=B.d,this.month=B.m-1,this.year=B.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>cv0[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 B=N9.fromTZISO(Q);this.ms=B.getUTCMilliseconds(),this.second=B.getUTCSeconds(),this.minute=B.getUTCMinutes(),this.hour=B.getUTCHours(),this.day=B.getUTCDate(),this.month=B.getUTCMonth(),this.year=B.getUTCFullYear(),this.apply()}else return this.fromDate(N9.fromTZISO(Q,this.tz))}findNext(Q,B,w,$){let D=this[B],Y;w.lastDayOfMonth&&(this.month!==1?Y=cv0[this.month]:Y=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let I=!w.starDOW&&B=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let X=this[B]+$;X<w[B].length;X++){let H=w[B][X];if(B==="day"&&w.lastDayOfMonth&&X-$==Y&&(H=1),B==="day"&&!w.starDOW){let W=w.dayOfWeek[(I+(X-$-1))%7];if(W&&W&Db)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&&!w.starDOM?H=H||W:H=H&&W}if(H)return this[B]=X-$,D!==this[B]?2:1}return 3}recurse(Q,B,w){let $=this.findNext(B,QU[w][0],Q,QU[w][2]);if($>1){let D=w+1;for(;D<QU.length;)this[QU[D][0]]=-QU[D][2],D++;if($===3)return this[QU[w][1]]++,this[QU[w][0]]=-QU[w][2],this.apply(),this.recurse(Q,B,0);if(this.apply())return this.recurse(Q,B,w-1)}return w+=1,w>=QU.length?this:this.year>=3000?null:this.recurse(Q,B,w)}increment(Q,B,w){return this.second+=B.interval!==void 0&&B.interval>1&&w?B.interval:1,this.ms=0,this.apply(),this.recurse(Q,B,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)):N9.fromTZ(N9.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function Lq2(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 HD(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new HD(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 $b(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function Mq2(A){return $b(A)}function Eq2(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var lv0=30000,Ti=[],XJA=class{name;options;_states;fn;constructor(A,Q,B){let w,$;if($b(Q))$=Q;else if(typeof Q=="object")w=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if($b(B))$=B;else if(typeof B=="object")w=B;else if(B!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=w?.name,this.options=Lq2(w),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:w?w.maxRuns:void 0,paused:w?w.paused:!1,pattern:new uv0("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new HD(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new uv0(A,this.options.timezone),this.name){if(Ti.find((D)=>D.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");Ti.push(this)}return $!==void 0&&Mq2($)&&(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 B=[],w=Q||this._states.currentRun||void 0;for(;A--&&(w=this.nextRun(w));)B.push(w);return B}getPattern(){return this._states.pattern?this._states.pattern.pattern:void 0}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,B=this.fn!==void 0,w=!this._states.kill;return Q&&B&&w&&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 HD||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new HD(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=Ti.indexOf(this);A>=0&&Ti.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(),B=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||B===null?this:(Q>lv0&&(Q=lv0),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(B),Q),this._states.currentTimeout&&this.options.unref&&Eq2(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new HD(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){$b(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new HD(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,B=!this._states.paused&&Q.getTime()>=A.getTime(),w=this._states.blocking&&this.options.protect;B&&!w?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):B&&w&&$b(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),B=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),B=!A),A=new HD(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let w=this._states.once||new HD(A,this.options.timezone||this.options.utcOffset);return!B&&w!==this._states.once&&(w=w.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||w===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&w.getTime()>=this.options.stopAt.getTime()?null:w}_calculatePreviousRun(A,Q){let B=new HD(void 0,this.options.timezone||this.options.utcOffset),w=A;if(this.options.startAt.getTime()<=B.getTime()){w=this.options.startAt;let $=w.getTime()+this.options.interval*1000;for(;$<=B.getTime();)w=new HD(w,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),$=w.getTime()+this.options.interval*1000;Q=!0}return w===null&&(w=void 0),[w,Q]}};class vi{scheduleCron(A,Q){let B=new XJA(A,()=>{Q()});return{stop:()=>B.stop()}}scheduleInterval(A,Q){let B=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(B)}}validateCron(A){new XJA(A).stop()}}B0();GA();var HJA=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),KJA=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),Cq2=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(KJA).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),Oq2=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),UJA=Z.union([Cq2,Oq2]);function Si(A,Q,B){return{...yQ(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",HJA,async($)=>{let{action:D,entityType:Y,entityId:I,position:X}=$;switch(D){case"list":return fq2(B,Y);case"add":return Rq2(B,Y,I);case"remove":return jq2(B,Y,I);case"reorder":return kq2(B,Y,I,X);default:return{success:!1,error:`Unknown action: ${D}`}}}),outputSchema:UJA}}async function fq2(A,Q){let B=[];if(Q)B=await A.list(Q);else{let $=A.getRegisteredTypes();for(let D of $){let Y=await A.list(D);B.push(...Y)}B.sort((D,Y)=>new Date(D.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(B.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:B.map(($,D)=>({position:D+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${B.length} items in queue`}}async function Rq2(A,Q,B){if(!Q)return{success:!1,error:"entityType is required for add action"};if(!B)return{success:!1,error:"entityId is required for add action"};let w=await A.add(Q,B);return{success:!0,data:{entityType:Q,entityId:B,position:w.position},message:`Added to queue at position ${w.position}`}}async function jq2(A,Q,B){if(!Q)return{success:!1,error:"entityType is required for remove action"};if(!B)return{success:!1,error:"entityId is required for remove action"};return await A.remove(Q,B),{success:!0,data:{entityType:Q,entityId:B},message:"Removed from queue"}}async function kq2(A,Q,B,w){if(!Q)return{success:!1,error:"entityType is required for reorder action"};if(!B)return{success:!1,error:"entityId is required for reorder action"};if(w===void 0)return{success:!1,error:"position is required for reorder action"};if(w<1)return{success:!1,error:"position must be a positive number"};return await A.reorder(Q,B,w),{success:!0,data:{entityType:Q,entityId:B,position:w},message:`Moved to position ${w}`}}B0();GA();var WJA=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish")}),Pq2=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),_q2=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),GJA=Z.union([Pq2,_q2]);function hi(A,Q,B){return{...yQ(Q,"publish","Publish an entity directly to its platform. Works with any registered entity type (social-post, post, deck, etc.)",WJA,async($)=>{let{entityType:D,id:Y,slug:I}=$;if(!Y&&!I)return{success:!1,error:"Either 'id' or 'slug' must be provided"};let X=null;if(Y)X=await A.entityService.getEntity(D,Y);else if(I)X=(await A.entityService.listEntities(D,{filter:{metadata:{slug:I}},limit:1}))[0]??null;if(!X)return{success:!1,error:`Entity not found: ${D}:${Y??I}`};if(X.metadata.status==="published")return{success:!1,error:"Entity is already published"};if(!B.has(D))return{success:!1,error:`No publish provider registered for ${D}. Check that the required credentials are configured.`};let H=B.get(D),W=X.content,J;try{let V=F2(X.content,Z.record(Z.unknown()));W=V.content;let E=V.metadata.coverImageId;J=typeof E==="string"?E:void 0}catch{}let F;if(J){let V=await A.entityService.getEntity("image",J);if(V?.content){let E=V.content.match(/^data:([^;]+);base64,(.+)$/);if(E?.[1]&&E[2])F={data:Buffer.from(E[2],"base64"),mimeType:E[1]}}}let z=await H.publish(W,X.metadata,F);return await A.entityService.updateEntity({...X,metadata:{...X.metadata,status:"published",publishedAt:new Date().toISOString(),platformId:z.id}}),{success:!0,data:{entityType:D,entityId:X.id,platformId:z.id,url:z.url},message:`Published ${D}:${X.id}`}}),outputSchema:GJA}}B0();GA();function dv0(A,Q){let{logger:B}=Q;A.messaging.subscribe(u6.REGISTER,async(w)=>bq2(Q,w.payload)),A.messaging.subscribe(u6.QUEUE,async(w)=>xq2(A,Q,w.payload)),A.messaging.subscribe(u6.DIRECT,async(w)=>Tq2(A,Q,w.payload)),A.messaging.subscribe(u6.REMOVE,async(w)=>vq2(Q,w.payload)),A.messaging.subscribe(u6.REORDER,async(w)=>Sq2(Q,w.payload)),A.messaging.subscribe(u6.LIST,async(w)=>hq2(A,Q,w.payload)),A.messaging.subscribe(u6.REPORT_SUCCESS,async(w)=>gq2(A,Q,w.payload)),A.messaging.subscribe(u6.REPORT_FAILURE,async(w)=>yq2(A,Q,w.payload)),B.debug("Subscribed to publish messages"),A.messaging.subscribe(hX.REPORT_SUCCESS,async(w)=>{let{entityType:$,entityId:D}=w.payload;return Q.scheduler.completeGeneration($,D),B.info("Generation completed",{entityType:$,entityId:D}),{success:!0}}),A.messaging.subscribe(hX.REPORT_FAILURE,async(w)=>{let{entityType:$,error:D}=w.payload;return Q.scheduler.failGeneration($,D),B.warn("Generation failed",{entityType:$,error:D}),{success:!0}}),B.debug("Subscribed to generation messages")}async function bq2(A,Q){let{entityType:B,provider:w}=Q;try{if(w)A.providerRegistry.register(B,w),A.logger.info(`Registered provider for entity type: ${B}`,{providerName:w.name});return{success:!0}}catch($){let D=L0($);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function xq2(A,Q,B){let{entityType:w,entityId:$}=B;try{let D=await Q.queueManager.add(w,$);return await A.messaging.send(u6.QUEUED,{entityType:w,entityId:$,position:D.position}),Q.logger.debug(`Entity queued: ${$}`,{entityType:w,position:D.position}),{success:!0}}catch(D){let Y=L0(D);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Tq2(A,Q,B){let{entityType:w,entityId:$}=B;return await A.messaging.send(u6.EXECUTE,{entityType:w,entityId:$}),Q.logger.debug(`Direct publish requested: ${$}`,{entityType:w}),{success:!0}}async function vq2(A,Q){let{entityType:B,entityId:w}=Q;try{return await A.queueManager.remove(B,w),A.logger.debug(`Entity removed from queue: ${w}`,{entityType:B}),{success:!0}}catch($){let D=L0($);return A.logger.error(`Failed to remove entity: ${D}`),{success:!1}}}async function Sq2(A,Q){let{entityType:B,entityId:w,position:$}=Q;try{return await A.queueManager.reorder(B,w,$),A.logger.debug(`Entity reordered: ${w}`,{entityType:B,newPosition:$}),{success:!0}}catch(D){let Y=L0(D);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function hq2(A,Q,B){let{entityType:w}=B;try{let $=await Q.queueManager.list(w);return await A.messaging.send(u6.LIST_RESPONSE,{entityType:w,queue:$.map((D)=>({entityId:D.entityId,position:D.position,queuedAt:D.queuedAt}))}),{success:!0}}catch($){let D=L0($);return Q.logger.error(`Failed to list queue: ${D}`),{success:!1}}}async function gq2(A,Q,B){let{entityType:w,entityId:$,result:D}=B;return Q.retryTracker.clearRetries($),await A.messaging.send(u6.COMPLETED,{entityType:w,entityId:$,result:D}),Q.logger.info(`Publish reported success: ${$}`,{entityType:w}),{success:!0}}async function yq2(A,Q,B){let{entityType:w,entityId:$,error:D}=B;Q.retryTracker.recordFailure($,D);let Y=Q.retryTracker.getRetryInfo($);return await A.messaging.send(u6.FAILED,{entityType:w,entityId:$,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1}),Q.logger.info(`Publish reported failure: ${$}`,{entityType:w,error:D,retryCount:Y?.retryCount,willRetry:Y?.willRetry}),{success:!0}}GA();async function iv0(A,Q,B,w){try{if(w.skipIfDraftExists!==!1){if((await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:1})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(w.maxUnpublishedDrafts!==void 0){let $=await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:w.maxUnpublishedDrafts+1});if($.length>=w.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${w.maxUnpublishedDrafts})`}}if(w.minSourceEntities!==void 0&&w.sourceEntityType){let $=await A.listEntities(w.sourceEntityType,{publishedOnly:!0,limit:w.minSourceEntities});if($.length<w.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${w.minSourceEntities} ${w.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:B,error:L0($)}),{shouldGenerate:!1,reason:`Condition check failed: ${L0($)}`}}}function rv0(A){let{context:Q,config:B,queueManager:w,providerRegistry:$,retryTracker:D,logger:Y}=A,I={send:async(X,H)=>{return Q.messaging.send(X,H)},subscribe:()=>()=>{}};return lY.createFresh({queueManager:w,providerRegistry:$,retryTracker:D,logger:Y,backend:new vi,...B.entitySchedules&&{entitySchedules:B.entitySchedules},...B.generationSchedules&&{generationSchedules:B.generationSchedules},...B.generationConditions&&{generationConditions:B.generationConditions},messageBus:I,entityService:Q.entityService,onPublish:(X)=>{Q.messaging.send(u6.COMPLETED,{entityType:X.entityType,entityId:X.entityId,result:X.result})},onFailed:(X)=>{Q.messaging.send(u6.FAILED,{entityType:X.entityType,entityId:X.entityId,error:X.error,retryCount:X.retryCount,willRetry:X.willRetry})},onCheckGenerationConditions:(X,H)=>iv0(Q.entityService,Y,X,H),onGenerate:(X)=>{Y.info(`Generation triggered for ${X.entityType}`),Q.messaging.send(hX.EXECUTE,{entityType:X.entityType})}})}async function nv0(A,Q,B){let w=A.getEntityTypes();for(let D of w){let Y=await A.listEntities(D,{filter:{metadata:{status:"queued"}}});for(let I of Y)await Q.add(I.entityType,I.id)}let $=0;for(let D of w){let Y=await Q.list(D);$+=Y.length}if($>0)B.info(`Rebuilt queue with ${$} queued entities`)}var ov0={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.37",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/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 JJA extends tB{pluginContext;queueManager;providerRegistry;retryTracker;scheduler;constructor(A){super("content-pipeline",ov0,A??{},bv0)}async onRegister(A){this.pluginContext=A,this.queueManager=gX.createFresh(),this.providerRegistry=yX.createFresh(),this.retryTracker=mX.createFresh({maxRetries:this.config.maxRetries,baseDelayMs:this.config.retryBaseDelayMs}),this.scheduler=rv0({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,logger:this.logger}),dv0(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,scheduler:this.scheduler,logger:this.logger}),A.messaging.subscribe("sync:initial:completed",async()=>{return await nv0(A.entityService,this.queueManager,this.logger),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"publication-pipeline",pluginId:this.id,title:"Publication Pipeline",section:"secondary",priority:100,rendererName:"PipelineWidget",dataProvider:async()=>{let Q=A.entityService.getEntityTypes(),B=[],w={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let D=await A.entityService.listEntities($);for(let Y of D){let I=Y.metadata.status;if(I!=="draft"&&I!=="queued"&&I!=="published"&&I!=="failed")continue;w[I]++;let X=Y.metadata.title;B.push({id:Y.id,title:typeof X==="string"?X:Y.id,type:$,status:I})}}return{summary:w,items:B}}}),{success:!0}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[Si(this.pluginContext,this.id,this.queueManager),hi(this.pluginContext,this.id,this.providerRegistry)]}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).\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}async cleanup(){await this.scheduler.stop(),this.logger.info("Content pipeline plugin stopped")}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getScheduler(){return this.scheduler}async onShutdown(){gX.resetInstance(),yX.resetInstance(),mX.resetInstance()}}function FJA(A){return new JJA(A)}B0();GA();var sv0=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),ZJA=Z.object({cloudflare:sv0.optional()});B0();GA();var uq2=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function cq2(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 av0(A,Q,B){let w=[];if(!B)return w;return w.push(yQ(A,"query",`Query website analytics from Cloudflare.
|
|
2738
|
+
${B.content}`:B.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${B.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let B=Fq2.parse(Q),w=[],$=Lw.from(async(H)=>{let W={progress:H.progress};if(H.message!==void 0)W.message=H.message;w.push(W)});if(!$)throw Error("Failed to create progress reporter");let Y=await new Yz(A.logger,A).process(B,`eval-${Date.now()}`,$),I=!1,X;if(Y.success&&Y.entityId){let H=await A.entityService.getEntity("social-post",Y.entityId);I=!!H,X=H?.content.slice(0,300)}return{...Y,entityExists:I,entityPreview:X,progressSteps:w}})}GA();B0();class Bb{sendMessage;logger;entityService;providers;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers}async handle(A){let{entityType:Q,entityId:B}=A;if(Q!=="social-post")return;this.logger.debug("Handling publish:execute",{entityId:B});try{let w=await this.entityService.getEntity("social-post",B);if(!w){await this.reportFailure(Q,B,`Post not found: ${B}`);return}if(w.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:B});return}let $=w.metadata.platform,D=this.providers.get($);if(!D){await this.reportFailure(Q,B,`No provider configured for platform: ${$}`);return}let Y=F2(w.content,XD),I;if(Y.metadata.coverImageId)I=await this.fetchImageData(Y.metadata.coverImageId);try{let X=await D.publish(Y.content,w.metadata,I),H=new Date().toISOString(),W=X.id||void 0,J={...Y.metadata,status:"published",publishedAt:H,...W&&{platformPostId:W}},F=t7.createPostContent(J,Y.content);await this.entityService.updateEntity({...w,content:F,metadata:{...w.metadata,status:"published",publishedAt:H,platformPostId:W}}),await this.reportSuccess(Q,B,X.id),this.logger.info(`Post published successfully: ${B}`,{platform:$,platformPostId:W})}catch(X){let H=X instanceof Error?X.message:String(X),W={...Y.metadata,status:"failed"},J=t7.createPostContent(W,Y.content);await this.entityService.updateEntity({...w,content:J,metadata:{...w.metadata,status:"failed"}}),await this.reportFailure(Q,B,H),this.logger.error(`Post publish failed: ${B}`,{platform:$,error:H})}}catch(w){let $=L0(w);this.logger.error("Unexpected error in publish handler",{entityId:B,error:$}),await this.reportFailure(Q,B,$)}}async reportSuccess(A,Q,B){await this.sendMessage("publish:report:success",{entityType:A,entityId:Q,result:{id:B}})}async reportFailure(A,Q,B){await this.sendMessage("publish:report:failure",{entityType:A,entityId:Q,error:B})}async fetchImageData(A){try{let Q=await this.entityService.getEntity("image",A);if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let w=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!w?.[1]||!w[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=w[1],D=w[2];return{data:Buffer.from(D,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function fv0(A,Q,B){if(Q.size===0){B.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let w=Q.values().next().value;return await A.messaging.send("publish:register",{entityType:"social-post",provider:w}),B.info("Registered social-post with publish-pipeline"),{success:!0}})}function Rv0(A,Q,B){let w=new Bb({sendMessage:A.messaging.send,logger:B.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q});A.messaging.subscribe("publish:execute",async($)=>{return await w.handle($.payload),{success:!0}}),B.debug("Subscribed to publish:execute messages")}GA();function jv0(A,Q){A.messaging.subscribe("entity:updated",async(B)=>{let{entityType:w,entityId:$,entity:D}=B.payload;if(w!=="post")return{success:!0};if(D.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities("social-post",{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("social:auto-generate",{sourceEntityType:w,sourceEntityId:$,platform:"linkedin"}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(I){let X=L0(I);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:X}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function kv0(A,Q){A.messaging.subscribe("social:auto-generate",async(B)=>{let{sourceEntityType:w,sourceEntityId:$,platform:D}=B.payload;try{let Y=await A.jobs.enqueue(`${t7.entityType}:generation`,{sourceEntityType:w,sourceEntityId:$,platform:D,addToQueue:!1},{interfaceType:"job",userId:"system"});return Q.info(`Social post generation job enqueued for ${w}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let I=L0(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:I}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Pv0(A,Q){A.messaging.subscribe("generate:execute",async(B)=>{let{entityType:w}=B.payload;if(w!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities("post",{filter:{metadata:{status:"published"}},limit:5});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:"No published posts available for social post generation"}),{success:!0};let D=null;for(let I of $)if((await A.entityService.listEntities("social-post",{filter:{metadata:{sourceEntityType:"post",sourceEntityId:I.id}},limit:1})).length===0){D=I;break}if(!D)return Q.info("All recent posts already have social posts"),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:"All recent posts already have social posts generated"}),{success:!0};let Y=await A.jobs.enqueue(`${t7.entityType}:generation`,{sourceEntityType:"post",sourceEntityId:D.id,platform:"linkedin",addToQueue:!1},{interfaceType:"job",userId:"system"});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:D.id}),{success:!0}}catch($){let D=L0($);return Q.error("Failed to handle generate:execute:",{error:D}),await A.messaging.send("generate:report:failure",{entityType:"social-post",error:D}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}var _v0={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.38",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/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 $JA extends HQ{entityType=t7.entityType;schema=wE;adapter=t7;providers=new Map;constructor(A){super("social-media",_v0,A,tGA)}createGenerationHandler(A){return new Yz(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Cv0()}getDataSources(){return[new Pi(this.logger.child("SocialPostDataSource"))]}async onRegister(A){if(this.initializeProviders(),fv0(A,this.providers,this.logger),Rv0(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)jv0(A,this.logger),kv0(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Pv0(A,this.logger),Ov0(A),this.logger.info("Social media plugin registered successfully")}async derive(A,Q,B){if(A.metadata.status!=="published")return;await B.jobs.enqueue(`${this.entityType}:generation`,{sourceEntityId:A.id,sourceEntityType:A.entityType},null,{priority:5,source:"social-media-plugin",metadata:{operationType:"content_operations",operationTarget:`social-post:${A.entityType}:${A.id}`,pluginId:"social-media"}})}initializeProviders(){if(this.config.linkedin?.accessToken){let A=wJA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function wb(A){return new $JA(A)}GA();var zq2=Z.enum(["draft","queued","published","failed"]),t5B=Z.object({status:zq2.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class DJA{name="internal";async publish(A,Q){return{id:"internal"}}}var u6={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",EXECUTE:"publish:execute",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},hX={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"};GA();var qq2=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),bv0=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),qq2).optional(),maxRetries:Z.number().optional().default(3),retryBaseDelayMs:Z.number().optional().default(5000)});class gX{static instance=null;queues=new Map;static getInstance(){return gX.instance??=new gX,gX.instance}static resetInstance(){gX.instance=null}static createFresh(){return new gX}constructor(){}async add(A,Q){let B=this.getOrCreateQueue(A),w=B.find((Y)=>Y.entityId===Q);if(w)return{position:w.position};let $=B.length+1,D={entityId:Q,entityType:A,position:$,queuedAt:new Date().toISOString()};return B.push(D),{position:$}}async remove(A,Q){let B=this.queues.get(A);if(!B)return;let w=B.findIndex(($)=>$.entityId===Q);if(w===-1)return;B.splice(w,1),this.recalculatePositions(B)}async reorder(A,Q,B){let w=this.queues.get(A);if(!w)return;let $=w.findIndex((I)=>I.entityId===Q);if($===-1)return;let[D]=w.splice($,1);if(!D)return;let Y=Math.max(0,Math.min(B-1,w.length));w.splice(Y,0,D),this.recalculatePositions(w)}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 B=Q[0];if(!B)continue;if(!A||B.queuedAt<A.queuedAt)A=B}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let B=Q.shift()??null;if(B)this.recalculatePositions(Q);return B}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,B]of this.queues.entries())if(B.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,B)=>{Q.position=B+1})}}class yX{static instance=null;providers=new Map;defaultProvider=new DJA;static getInstance(){return yX.instance??=new yX,yX.instance}static resetInstance(){yX.instance=null}static createFresh(){return new yX}constructor(){}register(A,Q){this.providers.set(A,Q)}get(A){return this.providers.get(A)??this.defaultProvider}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}GA();GA();async function xv0(A,Q){let B={entityType:A.entityType,entityId:A.entityId};if(Q.messageBus)await Q.messageBus.send(u6.EXECUTE,B,"publish-service");Q.onExecute?.(B)}async function Tv0(A,Q){let B=Q.providerRegistry.get(A.entityType);if(!Q.entityService){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"EntityService not available for provider mode",retryCount:0,willRetry:!1});return}let w=await Q.entityService.getEntity(A.entityType,A.entityId);if(!w){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:`Entity not found: ${A.entityType}/${A.entityId}`,retryCount:0,willRetry:!1});return}try{let $=await B.publish(w.content,w.metadata);Q.retryTracker.clearRetries(A.entityId),Q.onPublish?.({entityType:A.entityType,entityId:A.entityId,result:$})}catch($){let D=L0($);Q.retryTracker.recordFailure(A.entityId,D);let Y=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1})}}function vv0(A,Q,B,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send(u6.COMPLETED,{entityType:A,entityId:Q,result:B},"publish-service");w.onPublish?.({entityType:A,entityId:Q,result:B})}function Sv0(A,Q,B,w){w.retryTracker.recordFailure(Q,B);let $=w.retryTracker.getRetryInfo(Q),D={entityType:A,entityId:Q,error:B,retryCount:$?.retryCount??1,willRetry:$?.willRetry??!1};if(w.messageBus)w.messageBus.send(u6.FAILED,D,"publish-service");w.onFailed?.(D)}async function hv0(A,Q){let B=Q.generationConditions[A];if(B&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,B);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send(hX.SKIPPED,{entityType:A,reason:$.reason??"Conditions not met"},"content-pipeline");return}}let w={entityType:A};if(Q.messageBus)await Q.messageBus.send(hX.EXECUTE,w,"content-pipeline");Q.onGenerate?.(w)}function gv0(A,Q,B){if(B)B.send(hX.COMPLETED,{entityType:A,entityId:Q},"content-pipeline")}function yv0(A,Q,B){if(B)B.send(hX.FAILED,{entityType:A,error:Q},"content-pipeline")}var Nq2=1000;class lY{static instance=null;config;publishJobs=new Map;generationJobs=new Map;immediateIntervalJob=null;running=!1;static getInstance(A){return lY.instance??=new lY(A),lY.instance}static resetInstance(){if(lY.instance)lY.instance.stop();lY.instance=null}static createFresh(A){return new lY(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions()}async start(){if(this.running)return;this.running=!0;for(let[A,Q]of Object.entries(this.entitySchedules)){let B=this.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,B)}for(let[A,Q]of Object.entries(this.generationSchedules)){let B=this.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,B)}this.immediateIntervalJob=this.config.backend.scheduleInterval(Nq2,()=>this.processUnscheduledTypes())}async stop(){if(this.running=!1,this.stopAndClearJobs(this.publishJobs),this.stopAndClearJobs(this.generationJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}isRunning(){return this.running}async processEntityType(A){if(!this.running)return;try{let Q=await this.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.running)return;try{let A=await this.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let B=await this.config.queueManager.getNext(Q);if(B){await this.processEntry(B);break}}}catch(A){this.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){if(await this.config.queueManager.remove(A.entityType,A.entityId),this.config.messageBus!==void 0)await xv0(A,this.publishDeps);else await Tv0(A,this.publishDeps)}completePublish(A,Q,B){vv0(A,Q,B,this.publishDeps)}failPublish(A,Q,B){Sv0(A,Q,B,this.publishDeps)}async publishDirect(A,Q,B,w){return this.config.providerRegistry.get(A).publish(B,w)}async handleTriggerGeneration(A){if(!this.running)return;try{await hv0(A,this.generationDeps)}catch(Q){this.config.logger.error(`Generation trigger error for ${A}:`,Q)}}completeGeneration(A,Q){gv0(A,Q,this.config.messageBus)}failGeneration(A,Q){yv0(A,Q,this.config.messageBus)}stopAndClearJobs(A){for(let Q of A.values())Q.stop();A.clear()}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{providerRegistry:this.config.providerRegistry,retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,entityService:this.config.entityService,onExecute:this.config.onExecute,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,B){try{this.config.backend.validateCron(Q)}catch(w){throw Error(`Invalid ${B} cron expression for ${A}: "${Q}" - ${L0(w)}`)}}}var mv0={maxRetries:3,baseDelayMs:5000};class mX{static instance=null;retries=new Map;config;static getInstance(A){return mX.instance??=new mX(A??mv0),mX.instance}static resetInstance(){mX.instance=null}static createFresh(A){return new mX(A??mv0)}constructor(A){this.config=A}recordFailure(A,Q){let w=(this.retries.get(A)?.retryCount??0)+1,$=this.config.baseDelayMs*Math.pow(2,w-1),D=Date.now()+$;this.retries.set(A,{entityId:A,retryCount:w,lastError:Q,nextRetryAt:D})}shouldRetry(A){let Q=this.retries.get(A);if(!Q)return!1;return Q.retryCount<this.config.maxRetries}isReadyForRetry(A){let Q=this.retries.get(A);if(!Q)return!1;return Date.now()>=Q.nextRetryAt}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,nextRetryAt:Q.nextRetryAt,willRetry:Q.retryCount<this.config.maxRetries}}}function N9(A,Q,B,w,$,D,Y,I){return N9.fromTZ(N9.tp(A,Q,B,w,$,D,Y),I)}N9.fromTZISO=(A,Q,B)=>N9.fromTZ(Vq2(A,Q),B);N9.fromTZ=function(A,Q){let B=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),w=YJA(A.tz,B),$=new Date(B.getTime()-w),D=YJA(A.tz,$);if(D-w===0)return $;{let Y=new Date(B.getTime()-D),I=YJA(A.tz,Y);if(I-D===0)return Y;if(!Q&&I-D>0)return Y;if(Q)throw Error("Invalid date passed to fromTZ()");return $}};N9.toTZ=function(A,Q){let B=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),w=new Date(B);return{y:w.getFullYear(),m:w.getMonth()+1,d:w.getDate(),h:w.getHours(),i:w.getMinutes(),s:w.getSeconds(),tz:Q}};N9.tp=(A,Q,B,w,$,D,Y)=>({y:A,m:Q,d:B,h:w,i:$,s:D,tz:Y});function YJA(A,Q=new Date){let B=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],w=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${w} GMT`)-Date.parse(`${w} ${B}`)}function Vq2(A,Q){let B=new Date(Date.parse(A));if(isNaN(B))throw Error("minitz: Invalid ISO8601 passed to parser.");let w=A.substring(9);return A.includes("Z")||w.includes("-")||w.includes("+")?N9.tp(B.getUTCFullYear(),B.getUTCMonth()+1,B.getUTCDate(),B.getUTCHours(),B.getUTCMinutes(),B.getUTCSeconds(),"Etc/UTC"):N9.tp(B.getFullYear(),B.getMonth()+1,B.getDate(),B.getHours(),B.getMinutes(),B.getSeconds(),Q)}N9.minitz=N9;var IJA=32,Db=31|IJA,pv0=[1,2,4,8,16],uv0=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 HD(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,Db),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,B,w){let $=this[A],D=A==="day"&&this.lastDayOfMonth;if(Q===""&&!D)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(w);let Y=Q.split(",");if(Y.length>1)for(let I=0;I<Y.length;I++)this.partToArray(A,Y[I],B,w);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,B,w):Q.indexOf("-")!==-1?this.handleRange(Q,A,B,w):Q.indexOf("/")!==-1?this.handleStepping(Q,A,B,w):Q!==""&&this.handleNumber(Q,A,B,w)}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,B,w){let $=this.extractNth(A,Q),D=parseInt($[0],10)+B;if(isNaN(D))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,D,$[1]||w)}setPart(A,Q,B){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,B);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]=B}handleRangeWithStepping(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(D===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,I,X]=D,H=parseInt(Y,10)+B,W=parseInt(I,10)+B,J=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(J))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(J===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(J>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 F=H;F<=W;F+=J)this.setPart(Q,F,$[1]||w)}extractNth(A,Q){let B=A,w;if(B.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");w=B.split("#")[1],B=B.split("#")[0]}return[B,w]}handleRange(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].split("-");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(D[0],10)+B,I=parseInt(D[1],10)+B;if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(I))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(Y>I)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let X=Y;X<=I;X++)this.setPart(Q,X,$[1]||w)}handleStepping(A,Q,B,w){let $=this.extractNth(A,Q),D=$[0].split("/");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");D[0]===""&&(D[0]="*");let Y=0;D[0]!=="*"&&(Y=parseInt(D[0],10)+B);let I=parseInt(D[1],10);if(isNaN(I))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(I===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(I>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let X=Y;X<this[Q].length;X+=I)this.setPart(Q,X,$[1]||w)}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]|IJA;else if(Q===Db)this.dayOfWeek[A]=Db;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|pv0[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},cv0=[31,28,31,30,31,30,31,31,30,31,30,31],QU=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],HD=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,B){if(this.tz=B,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,B,w,$){let D=new Date(Date.UTC(Q,B,w)).getUTCDay(),Y=0;for(let I=1;I<=w;I++)new Date(Date.UTC(Q,B,I)).getUTCDay()===D&&Y++;if($&Db&&pv0[Y-1]&$)return!0;if($&IJA){let I=new Date(Date.UTC(Q,B+1,0)).getUTCDate();for(let X=w+1;X<=I;X++)if(new Date(Date.UTC(Q,B,X)).getUTCDay()===D)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 B=N9.toTZ(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=B.s,this.minute=B.i,this.hour=B.h,this.day=B.d,this.month=B.m-1,this.year=B.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>cv0[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 B=N9.fromTZISO(Q);this.ms=B.getUTCMilliseconds(),this.second=B.getUTCSeconds(),this.minute=B.getUTCMinutes(),this.hour=B.getUTCHours(),this.day=B.getUTCDate(),this.month=B.getUTCMonth(),this.year=B.getUTCFullYear(),this.apply()}else return this.fromDate(N9.fromTZISO(Q,this.tz))}findNext(Q,B,w,$){let D=this[B],Y;w.lastDayOfMonth&&(this.month!==1?Y=cv0[this.month]:Y=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let I=!w.starDOW&&B=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let X=this[B]+$;X<w[B].length;X++){let H=w[B][X];if(B==="day"&&w.lastDayOfMonth&&X-$==Y&&(H=1),B==="day"&&!w.starDOW){let W=w.dayOfWeek[(I+(X-$-1))%7];if(W&&W&Db)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&&!w.starDOM?H=H||W:H=H&&W}if(H)return this[B]=X-$,D!==this[B]?2:1}return 3}recurse(Q,B,w){let $=this.findNext(B,QU[w][0],Q,QU[w][2]);if($>1){let D=w+1;for(;D<QU.length;)this[QU[D][0]]=-QU[D][2],D++;if($===3)return this[QU[w][1]]++,this[QU[w][0]]=-QU[w][2],this.apply(),this.recurse(Q,B,0);if(this.apply())return this.recurse(Q,B,w-1)}return w+=1,w>=QU.length?this:this.year>=3000?null:this.recurse(Q,B,w)}increment(Q,B,w){return this.second+=B.interval!==void 0&&B.interval>1&&w?B.interval:1,this.ms=0,this.apply(),this.recurse(Q,B,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)):N9.fromTZ(N9.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function Lq2(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 HD(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new HD(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 $b(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function Mq2(A){return $b(A)}function Eq2(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var lv0=30000,Ti=[],XJA=class{name;options;_states;fn;constructor(A,Q,B){let w,$;if($b(Q))$=Q;else if(typeof Q=="object")w=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if($b(B))$=B;else if(typeof B=="object")w=B;else if(B!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=w?.name,this.options=Lq2(w),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:w?w.maxRuns:void 0,paused:w?w.paused:!1,pattern:new uv0("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new HD(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new uv0(A,this.options.timezone),this.name){if(Ti.find((D)=>D.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");Ti.push(this)}return $!==void 0&&Mq2($)&&(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 B=[],w=Q||this._states.currentRun||void 0;for(;A--&&(w=this.nextRun(w));)B.push(w);return B}getPattern(){return this._states.pattern?this._states.pattern.pattern:void 0}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,B=this.fn!==void 0,w=!this._states.kill;return Q&&B&&w&&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 HD||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new HD(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=Ti.indexOf(this);A>=0&&Ti.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(),B=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||B===null?this:(Q>lv0&&(Q=lv0),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(B),Q),this._states.currentTimeout&&this.options.unref&&Eq2(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new HD(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){$b(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new HD(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,B=!this._states.paused&&Q.getTime()>=A.getTime(),w=this._states.blocking&&this.options.protect;B&&!w?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):B&&w&&$b(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),B=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),B=!A),A=new HD(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let w=this._states.once||new HD(A,this.options.timezone||this.options.utcOffset);return!B&&w!==this._states.once&&(w=w.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||w===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&w.getTime()>=this.options.stopAt.getTime()?null:w}_calculatePreviousRun(A,Q){let B=new HD(void 0,this.options.timezone||this.options.utcOffset),w=A;if(this.options.startAt.getTime()<=B.getTime()){w=this.options.startAt;let $=w.getTime()+this.options.interval*1000;for(;$<=B.getTime();)w=new HD(w,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),$=w.getTime()+this.options.interval*1000;Q=!0}return w===null&&(w=void 0),[w,Q]}};class vi{scheduleCron(A,Q){let B=new XJA(A,()=>{Q()});return{stop:()=>B.stop()}}scheduleInterval(A,Q){let B=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(B)}}validateCron(A){new XJA(A).stop()}}B0();GA();var HJA=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),KJA=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),Cq2=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(KJA).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),Oq2=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),UJA=Z.union([Cq2,Oq2]);function Si(A,Q,B){return{...yQ(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",HJA,async($)=>{let{action:D,entityType:Y,entityId:I,position:X}=$;switch(D){case"list":return fq2(B,Y);case"add":return Rq2(B,Y,I);case"remove":return jq2(B,Y,I);case"reorder":return kq2(B,Y,I,X);default:return{success:!1,error:`Unknown action: ${D}`}}}),outputSchema:UJA}}async function fq2(A,Q){let B=[];if(Q)B=await A.list(Q);else{let $=A.getRegisteredTypes();for(let D of $){let Y=await A.list(D);B.push(...Y)}B.sort((D,Y)=>new Date(D.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(B.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:B.map(($,D)=>({position:D+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${B.length} items in queue`}}async function Rq2(A,Q,B){if(!Q)return{success:!1,error:"entityType is required for add action"};if(!B)return{success:!1,error:"entityId is required for add action"};let w=await A.add(Q,B);return{success:!0,data:{entityType:Q,entityId:B,position:w.position},message:`Added to queue at position ${w.position}`}}async function jq2(A,Q,B){if(!Q)return{success:!1,error:"entityType is required for remove action"};if(!B)return{success:!1,error:"entityId is required for remove action"};return await A.remove(Q,B),{success:!0,data:{entityType:Q,entityId:B},message:"Removed from queue"}}async function kq2(A,Q,B,w){if(!Q)return{success:!1,error:"entityType is required for reorder action"};if(!B)return{success:!1,error:"entityId is required for reorder action"};if(w===void 0)return{success:!1,error:"position is required for reorder action"};if(w<1)return{success:!1,error:"position must be a positive number"};return await A.reorder(Q,B,w),{success:!0,data:{entityType:Q,entityId:B,position:w},message:`Moved to position ${w}`}}B0();GA();var WJA=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish")}),Pq2=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),_q2=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),GJA=Z.union([Pq2,_q2]);function hi(A,Q,B){return{...yQ(Q,"publish","Publish an entity directly to its platform. Works with any registered entity type (social-post, post, deck, etc.)",WJA,async($)=>{let{entityType:D,id:Y,slug:I}=$;if(!Y&&!I)return{success:!1,error:"Either 'id' or 'slug' must be provided"};let X=null;if(Y)X=await A.entityService.getEntity(D,Y);else if(I)X=(await A.entityService.listEntities(D,{filter:{metadata:{slug:I}},limit:1}))[0]??null;if(!X)return{success:!1,error:`Entity not found: ${D}:${Y??I}`};if(X.metadata.status==="published")return{success:!1,error:"Entity is already published"};if(!B.has(D))return{success:!1,error:`No publish provider registered for ${D}. Check that the required credentials are configured.`};let H=B.get(D),W=X.content,J;try{let V=F2(X.content,Z.record(Z.unknown()));W=V.content;let E=V.metadata.coverImageId;J=typeof E==="string"?E:void 0}catch{}let F;if(J){let V=await A.entityService.getEntity("image",J);if(V?.content){let E=V.content.match(/^data:([^;]+);base64,(.+)$/);if(E?.[1]&&E[2])F={data:Buffer.from(E[2],"base64"),mimeType:E[1]}}}let z=await H.publish(W,X.metadata,F);return await A.entityService.updateEntity({...X,metadata:{...X.metadata,status:"published",publishedAt:new Date().toISOString(),platformId:z.id}}),{success:!0,data:{entityType:D,entityId:X.id,platformId:z.id,url:z.url},message:`Published ${D}:${X.id}`}}),outputSchema:GJA}}B0();GA();function dv0(A,Q){let{logger:B}=Q;A.messaging.subscribe(u6.REGISTER,async(w)=>bq2(Q,w.payload)),A.messaging.subscribe(u6.QUEUE,async(w)=>xq2(A,Q,w.payload)),A.messaging.subscribe(u6.DIRECT,async(w)=>Tq2(A,Q,w.payload)),A.messaging.subscribe(u6.REMOVE,async(w)=>vq2(Q,w.payload)),A.messaging.subscribe(u6.REORDER,async(w)=>Sq2(Q,w.payload)),A.messaging.subscribe(u6.LIST,async(w)=>hq2(A,Q,w.payload)),A.messaging.subscribe(u6.REPORT_SUCCESS,async(w)=>gq2(A,Q,w.payload)),A.messaging.subscribe(u6.REPORT_FAILURE,async(w)=>yq2(A,Q,w.payload)),B.debug("Subscribed to publish messages"),A.messaging.subscribe(hX.REPORT_SUCCESS,async(w)=>{let{entityType:$,entityId:D}=w.payload;return Q.scheduler.completeGeneration($,D),B.info("Generation completed",{entityType:$,entityId:D}),{success:!0}}),A.messaging.subscribe(hX.REPORT_FAILURE,async(w)=>{let{entityType:$,error:D}=w.payload;return Q.scheduler.failGeneration($,D),B.warn("Generation failed",{entityType:$,error:D}),{success:!0}}),B.debug("Subscribed to generation messages")}async function bq2(A,Q){let{entityType:B,provider:w}=Q;try{if(w)A.providerRegistry.register(B,w),A.logger.info(`Registered provider for entity type: ${B}`,{providerName:w.name});return{success:!0}}catch($){let D=L0($);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function xq2(A,Q,B){let{entityType:w,entityId:$}=B;try{let D=await Q.queueManager.add(w,$);return await A.messaging.send(u6.QUEUED,{entityType:w,entityId:$,position:D.position}),Q.logger.debug(`Entity queued: ${$}`,{entityType:w,position:D.position}),{success:!0}}catch(D){let Y=L0(D);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Tq2(A,Q,B){let{entityType:w,entityId:$}=B;return await A.messaging.send(u6.EXECUTE,{entityType:w,entityId:$}),Q.logger.debug(`Direct publish requested: ${$}`,{entityType:w}),{success:!0}}async function vq2(A,Q){let{entityType:B,entityId:w}=Q;try{return await A.queueManager.remove(B,w),A.logger.debug(`Entity removed from queue: ${w}`,{entityType:B}),{success:!0}}catch($){let D=L0($);return A.logger.error(`Failed to remove entity: ${D}`),{success:!1}}}async function Sq2(A,Q){let{entityType:B,entityId:w,position:$}=Q;try{return await A.queueManager.reorder(B,w,$),A.logger.debug(`Entity reordered: ${w}`,{entityType:B,newPosition:$}),{success:!0}}catch(D){let Y=L0(D);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function hq2(A,Q,B){let{entityType:w}=B;try{let $=await Q.queueManager.list(w);return await A.messaging.send(u6.LIST_RESPONSE,{entityType:w,queue:$.map((D)=>({entityId:D.entityId,position:D.position,queuedAt:D.queuedAt}))}),{success:!0}}catch($){let D=L0($);return Q.logger.error(`Failed to list queue: ${D}`),{success:!1}}}async function gq2(A,Q,B){let{entityType:w,entityId:$,result:D}=B;return Q.retryTracker.clearRetries($),await A.messaging.send(u6.COMPLETED,{entityType:w,entityId:$,result:D}),Q.logger.info(`Publish reported success: ${$}`,{entityType:w}),{success:!0}}async function yq2(A,Q,B){let{entityType:w,entityId:$,error:D}=B;Q.retryTracker.recordFailure($,D);let Y=Q.retryTracker.getRetryInfo($);return await A.messaging.send(u6.FAILED,{entityType:w,entityId:$,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1}),Q.logger.info(`Publish reported failure: ${$}`,{entityType:w,error:D,retryCount:Y?.retryCount,willRetry:Y?.willRetry}),{success:!0}}GA();async function iv0(A,Q,B,w){try{if(w.skipIfDraftExists!==!1){if((await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:1})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(w.maxUnpublishedDrafts!==void 0){let $=await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:w.maxUnpublishedDrafts+1});if($.length>=w.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${w.maxUnpublishedDrafts})`}}if(w.minSourceEntities!==void 0&&w.sourceEntityType){let $=await A.listEntities(w.sourceEntityType,{publishedOnly:!0,limit:w.minSourceEntities});if($.length<w.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${w.minSourceEntities} ${w.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:B,error:L0($)}),{shouldGenerate:!1,reason:`Condition check failed: ${L0($)}`}}}function rv0(A){let{context:Q,config:B,queueManager:w,providerRegistry:$,retryTracker:D,logger:Y}=A,I={send:async(X,H)=>{return Q.messaging.send(X,H)},subscribe:()=>()=>{}};return lY.createFresh({queueManager:w,providerRegistry:$,retryTracker:D,logger:Y,backend:new vi,...B.entitySchedules&&{entitySchedules:B.entitySchedules},...B.generationSchedules&&{generationSchedules:B.generationSchedules},...B.generationConditions&&{generationConditions:B.generationConditions},messageBus:I,entityService:Q.entityService,onPublish:(X)=>{Q.messaging.send(u6.COMPLETED,{entityType:X.entityType,entityId:X.entityId,result:X.result})},onFailed:(X)=>{Q.messaging.send(u6.FAILED,{entityType:X.entityType,entityId:X.entityId,error:X.error,retryCount:X.retryCount,willRetry:X.willRetry})},onCheckGenerationConditions:(X,H)=>iv0(Q.entityService,Y,X,H),onGenerate:(X)=>{Y.info(`Generation triggered for ${X.entityType}`),Q.messaging.send(hX.EXECUTE,{entityType:X.entityType})}})}async function nv0(A,Q,B){let w=A.getEntityTypes();for(let D of w){let Y=await A.listEntities(D,{filter:{metadata:{status:"queued"}}});for(let I of Y)await Q.add(I.entityType,I.id)}let $=0;for(let D of w){let Y=await Q.list(D);$+=Y.length}if($>0)B.info(`Rebuilt queue with ${$} queued entities`)}var ov0={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.38",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/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 JJA extends tB{pluginContext;queueManager;providerRegistry;retryTracker;scheduler;constructor(A){super("content-pipeline",ov0,A??{},bv0)}async onRegister(A){this.pluginContext=A,this.queueManager=gX.createFresh(),this.providerRegistry=yX.createFresh(),this.retryTracker=mX.createFresh({maxRetries:this.config.maxRetries,baseDelayMs:this.config.retryBaseDelayMs}),this.scheduler=rv0({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,logger:this.logger}),dv0(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,scheduler:this.scheduler,logger:this.logger}),A.messaging.subscribe("sync:initial:completed",async()=>{return await nv0(A.entityService,this.queueManager,this.logger),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"publication-pipeline",pluginId:this.id,title:"Publication Pipeline",section:"secondary",priority:100,rendererName:"PipelineWidget",dataProvider:async()=>{let Q=A.entityService.getEntityTypes(),B=[],w={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let D=await A.entityService.listEntities($);for(let Y of D){let I=Y.metadata.status;if(I!=="draft"&&I!=="queued"&&I!=="published"&&I!=="failed")continue;w[I]++;let X=Y.metadata.title;B.push({id:Y.id,title:typeof X==="string"?X:Y.id,type:$,status:I})}}return{summary:w,items:B}}}),{success:!0}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[Si(this.pluginContext,this.id,this.queueManager),hi(this.pluginContext,this.id,this.providerRegistry)]}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).\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}async cleanup(){await this.scheduler.stop(),this.logger.info("Content pipeline plugin stopped")}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getScheduler(){return this.scheduler}async onShutdown(){gX.resetInstance(),yX.resetInstance(),mX.resetInstance()}}function FJA(A){return new JJA(A)}B0();GA();var sv0=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),ZJA=Z.object({cloudflare:sv0.optional()});B0();GA();var uq2=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function cq2(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 av0(A,Q,B){let w=[];if(!B)return w;return w.push(yQ(A,"query",`Query website analytics from Cloudflare.
|
|
2738
2739
|
|
|
2739
2740
|
Date range options (use only one):
|
|
2740
2741
|
- No params: yesterday only
|
|
@@ -2872,7 +2873,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,uq2,
|
|
|
2872
2873
|
}
|
|
2873
2874
|
}
|
|
2874
2875
|
}
|
|
2875
|
-
`,variables:B})});if(!w.ok){let Y=await w.text();throw Error(`Cloudflare API error: ${w.status} - ${Y}`)}let $=await w.json();if($.errors&&$.errors.length>0)throw Error(`Cloudflare GraphQL error: ${$.errors.map((Y)=>Y.message).join(", ")}`);return($.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((Y)=>({country:Y.dimensions.countryName,visits:Y.sum.visits}))}}GA();var qJA=7,lq2=10;function ev0(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=AN(),B=Xv(qJA),w=ZW(B),$=ZW(Q);try{let[D,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:$}),A.getTopPages({startDate:w,endDate:$,limit:lq2})]);return{days:qJA,startDate:w,endDate:$,pageviews:D.pageviews,visitors:D.visitors,topPages:Y}}catch(D){return{error:D instanceof Error?D.message:"Failed to fetch analytics",days:qJA}}}}var AS0={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.
|
|
2876
|
+
`,variables:B})});if(!w.ok){let Y=await w.text();throw Error(`Cloudflare API error: ${w.status} - ${Y}`)}let $=await w.json();if($.errors&&$.errors.length>0)throw Error(`Cloudflare GraphQL error: ${$.errors.map((Y)=>Y.message).join(", ")}`);return($.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((Y)=>({country:Y.dimensions.countryName,visits:Y.sum.visits}))}}GA();var qJA=7,lq2=10;function ev0(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=AN(),B=Xv(qJA),w=ZW(B),$=ZW(Q);try{let[D,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:$}),A.getTopPages({startDate:w,endDate:$,limit:lq2})]);return{days:qJA,startDate:w,endDate:$,pageviews:D.pageviews,visitors:D.visitors,topPages:Y}}catch(D){return{error:D instanceof Error?D.message:"Failed to fetch analytics",days:qJA}}}}var AS0={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.38",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 QS0 extends tB{cloudflareClient;constructor(A={}){super("analytics",AS0,A,ZJA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new zJA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",ev0(this.cloudflareClient));let Q=this.config.cloudflare?.siteTag;if(Q)A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("plugin:site-builder:head-script:register",{pluginId:this.id,script:tv0(Q)}),{success:!0}})}async getTools(){return av0(this.id,this.getContext(),this.cloudflareClient)}}function dq2(A={}){return new QS0(A)}var gi=dq2;B0();function NJA(A){return`<!doctype html>
|
|
2876
2877
|
<html>
|
|
2877
2878
|
<head>
|
|
2878
2879
|
<meta charset="utf-8" />
|
|
@@ -2883,7 +2884,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,uq2,
|
|
|
2883
2884
|
</head>
|
|
2884
2885
|
<body></body>
|
|
2885
2886
|
</html>
|
|
2886
|
-
`}GA();var BS0={name:"@brains/cms",private:!0,version:"0.2.0-alpha.
|
|
2887
|
+
`}GA();var BS0={name:"@brains/cms",private:!0,version:"0.2.0-alpha.38",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/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 rq2=Z.object({label:Z.string().optional(),pluralName:Z.string().optional()}).passthrough(),nq2=Z.object({entityDisplay:Z.record(rq2).optional(),routePath:Z.string().default("/")});function oq2(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function sq2(A){let Q=A.entityDisplay;return Q?{entityDisplay:Q}:{}}async function aq2(A){let Q=await A.messaging.send("git-sync:get-repo-info",{});if("noop"in Q||!Q.success||!Q.data)throw Error("CMS config unavailable: git-sync repo info unavailable");let{repo:B,branch:w}=Q.data;if(!B||!w)throw Error("CMS config unavailable: git-sync repo info incomplete");return{repo:B,branch:w}}async function tq2(A,Q={}){let{repo:B,branch:w}=await aq2(A);return S_({repo:B,branch:w,...A.siteUrl&&{baseUrl:A.siteUrl},entityTypes:A.entityService.getEntityTypes(),getFrontmatterSchema:($)=>A.entities.getEffectiveFrontmatterSchema($),getAdapter:($)=>A.entities.getAdapter($),...Q.entityDisplay&&{entityDisplay:Q.entityDisplay}})}async function wS0(A,Q={}){return O4(await tq2(A,Q))}class yi extends tB{constructor(A={}){super("admin",BS0,A,nq2)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40})}getWebRoutes(){let A=oq2(this.config.routePath);return[{path:this.config.routePath,method:"GET",public:!0,handler:async()=>{return new Response(NJA({cmsConfigPath:A}),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:A,method:"GET",public:!0,handler:async()=>{try{let Q=await wS0(this.getContext(),sq2(this.config));return new Response(Q,{headers:{"Content-Type":"application/yaml; charset=utf-8"}})}catch(Q){return new Response(Q instanceof Error?Q.message:"CMS unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}})}}}]}}function IJ(A){return new yi(A)}B0();GA();GA();var mi=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],eq2=new Set(mi);function VJA(A){return eq2.has(A)}var AN2=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string()});class ui{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let Q=`${A.pluginId}:${A.id}`;this.widgets.set(Q,A),this.logger.debug("Dashboard widget registered",{key:Q,title:A.title,rendererName:A.rendererName})}unregister(A,Q){if(Q){this.widgets.delete(`${A}:${Q}`);return}for(let B of this.widgets.keys())if(B.startsWith(`${A}:`))this.widgets.delete(B)}get(A,Q){return this.widgets.get(`${A}:${Q}`)}list(A){return Array.from(this.widgets.values()).filter((Q)=>!A||Q.section===A).sort((Q,B)=>Q.priority-B.priority)}get size(){return this.widgets.size}}GA();class ci{id="dashboard:dashboard";name="Dashboard DataSource";description="Aggregates dashboard widgets from all plugins";registry;logger;constructor(A,Q){this.registry=A,this.logger=Q.child("DashboardDataSource")}async getDashboardData(){let A={},Q=this.registry.list(),B=await Promise.allSettled(Q.map(async(w)=>{let $=await w.dataProvider(),{dataProvider:D,component:Y,...I}=w;return{key:`${w.pluginId}:${w.id}`,widget:I,data:$}}));for(let w=0;w<B.length;w++){let $=B[w],D=Q[w];if(!$||!D)continue;if($.status==="fulfilled")A[$.value.key]={widget:$.value.widget,data:$.value.data};else this.logger.error("Widget data provider failed",{widgetId:D.id,pluginId:D.pluginId,error:L0($.reason)})}return{widgets:A}}async fetch(A,Q,B){return await this.getDashboardData()}}import{render as fN2}from"preact-render-to-string";var $S0=`
|
|
2887
2888
|
:root {
|
|
2888
2889
|
--ink: #0a0819;
|
|
2889
2890
|
--ink-raised: #14112b;
|
|
@@ -3817,7 +3818,7 @@ body::after {
|
|
|
3817
3818
|
}
|
|
3818
3819
|
});
|
|
3819
3820
|
})();`;function _N2({input:A}){let Q=A.entityCounts.reduce((D,{count:Y})=>D+Y,0),B=jN2(A.widgets),w=Boolean(A.character.role)||Boolean(A.character.purpose)||A.character.values.length>0,$=A.appInfo.endpoints.length>0;return nB("html",{lang:"en","data-theme":"dark",children:[nB("head",{children:[nB("meta",{charSet:"utf-8"},void 0,!1,void 0,this),nB("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"},void 0,!1,void 0,this),nB("title",{children:A.title},void 0,!1,void 0,this),nB("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),nB("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),nB("link",{href:RN2,rel:"stylesheet"},void 0,!1,void 0,this),nB("style",{dangerouslySetInnerHTML:{__html:$S0}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),nB("body",{children:[nB("main",{class:"console","data-component":"dashboard:dashboard",children:[nB(YS0,{title:A.title,tagline:A.profile.description,appInfo:A.appInfo,now:new Date},void 0,!1,void 0,this),nB("section",{class:"layout",children:[nB("div",{class:"main-column",children:[nB(IS0,{total:Q,entityCounts:A.entityCounts},void 0,!1,void 0,this),B.primary.map((D)=>nB(li,{widget:D},`${D.widget.pluginId}:${D.widget.id}`,!1,void 0,this)),B.secondary.map((D)=>nB(li,{widget:D},`${D.widget.pluginId}:${D.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),(w||B.sidebar.length>0||$)&&nB("div",{class:"sidebar-column",children:[nB(XS0,{character:A.character},void 0,!1,void 0,this),B.sidebar.map((D)=>nB(li,{widget:D},`${D.widget.pluginId}:${D.widget.id}`,!1,void 0,this)),nB(HS0,{endpoints:A.appInfo.endpoints,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),nB(GS0,{title:A.title,appInfo:A.appInfo},void 0,!1,void 0,this)]},void 0,!0,void 0,this),nB("button",{class:"theme-toggle",id:"themeToggle","aria-label":"Toggle theme",children:"Light mode"},void 0,!1,void 0,this),nB("script",{dangerouslySetInnerHTML:{__html:kN2}},void 0,!1,void 0,this),nB("script",{dangerouslySetInnerHTML:{__html:PN2}},void 0,!1,void 0,this),A.widgetScripts.map((D,Y)=>nB("script",{dangerouslySetInnerHTML:{__html:D}},`widget-script:${Y}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function JS0(A){return`<!doctype html>
|
|
3820
|
-
${fN2(nB(_N2,{input:A},void 0,!1,void 0,this))}`}function FS0(A,Q){let B={},w=new Set;for(let[$,D]of Object.entries(A)){let Y=Q?.get(D.widget.pluginId,D.widget.id);if(B[$]={...D,...Y?.component?{component:Y.component}:{}},Y?.clientScript)w.add(Y.clientScript)}return{widgets:B,widgetScripts:Array.from(w)}}var ZS0={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.
|
|
3821
|
+
${fN2(nB(_N2,{input:A},void 0,!1,void 0,this))}`}function FS0(A,Q){let B={},w=new Set;for(let[$,D]of Object.entries(A)){let Y=Q?.get(D.widget.pluginId,D.widget.id);if(B[$]={...D,...Y?.component?{component:Y.component}:{}},Y?.clientScript)w.add(Y.clientScript)}return{widgets:B,widgetScripts:Array.from(w)}}var ZS0={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.38",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/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 xN2=Z.object({version:Z.string().default("1.0.0"),routePath:Z.string().default("/dashboard")}),TN2=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),component:Z.custom().optional(),clientScript:Z.string().optional(),dataProvider:Z.function().returns(Z.promise(Z.unknown()))}).superRefine((A,Q)=>{if(!VJA(A.rendererName)&&!A.component)Q.addIssue({code:Z.ZodIssueCode.custom,message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),vN2=Z.object({pluginId:Z.string(),widgetId:Z.string().optional()});function SN2(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,...A.component?{component:A.component}:{},...A.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider}}class EJA extends tB{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A){super("dashboard",ZS0,A??{},xN2)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new ui(this.logger),this.datasource=new ci(this.widgetRegistry,this.logger),A.entities.registerDataSource(this.datasource),A.messaging.subscribe("dashboard:register-widget",async(Q)=>{try{let B=TN2.parse(Q.payload),w=SN2(B);return this.widgetRegistry?.register(w),this.logger.debug("Widget registered via messaging",{widgetId:B.id,pluginId:B.pluginId,rendererName:B.rendererName,builtIn:mi.includes(B.rendererName)}),{success:!0}}catch(B){return this.logger.error("Failed to register widget",{error:L0(B),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{let B=vN2.parse(Q.payload);return this.widgetRegistry?.unregister(B.pluginId,B.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:B.pluginId,widgetId:B.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,[B,w,$]=await Promise.all([this.datasource.getDashboardData(),Q.appInfo(),Q.entityService.getEntityCounts()]),D=Q.identity.get(),Y=Q.identity.getProfile(),I=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),X=Y.name||w.model||"Brain Dashboard",H=FS0(B.widgets,this.widgetRegistry),W={title:X,baseUrl:I,widgets:H.widgets,widgetScripts:H.widgetScripts,character:D,profile:Y,appInfo:w,entityCounts:$};return new Response(JS0(W),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function Xz(A){return new EJA(A)}GA();var hN2=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),priority:Z.number(),section:Z.enum(["primary","secondary","sidebar"]),rendererName:Z.string(),component:Z.custom().optional()}),gN2=Z.object({widget:hN2,data:Z.unknown()}),yN2=Z.object({widgets:Z.record(gN2)});GA();B0();GA();import{h as eN2}from"preact";GA();aD();B0();var $E=Z.enum(["draft","queued","published","failed"]),Yb=Z.object({subject:Z.string(),status:$E,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional()}),zS0=Yb.pick({subject:!0,status:!0,entityIds:!0,scheduledFor:!0,sentAt:!0,buttondownId:!0,sourceEntityType:!0}),Ib=U2.extend({entityType:Z.literal("newsletter"),metadata:zS0});B0();class qS0 extends E2{constructor(){super({entityType:"newsletter",schema:Ib,frontmatterSchema:Yb})}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}}}var NS0=new qS0;B0();B0();GA();var mN2=mI.extend({status:Z.enum(["draft","queued","published","failed"]).optional()}),uN2=uI.extend({query:mN2.optional()});function VS0(A){try{let{content:Q}=F2(A.content,Yb);return Q}catch{return A.content}}class CJA extends s5{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=uN2.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=VS0(A),B={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:FW(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)B.sentAt=A.metadata.sentAt;return B}buildListResult(A,Q,B){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A),$=B.entityService;if(w.id)return this.fetchSingleNewsletter(w.id,Q,$);let D=w.status,Y=D?{filter:{metadata:{status:D}}}:void 0,{items:I,pagination:X}=await this.fetchList(w,$,Y);return Q.parse(this.buildListResult(I,X,w))}async fetchSingleNewsletter(A,Q,B){let w=await B.getEntity(this.config.entityType,A);if(!w)throw Error(`Newsletter not found: ${A}`);let $=await this.resolveNavigation(w,B),D=[];if(w.metadata.entityIds?.length){let X=w.metadata.sourceEntityType??"post";D=(await Promise.all(w.metadata.entityIds.map(async(W)=>{let J=await B.getEntity(X,W);if(J){let F=J.metadata;return{id:W,title:F.title??W,url:`/${X}s/${F.slug??W}`}}return null}))).filter((W)=>W!==null)}let Y=VS0(w),I={id:w.id,subject:w.metadata.subject,status:w.metadata.status,content:Y,created:w.created,updated:w.updated,sentAt:w.metadata.sentAt,scheduledFor:w.metadata.scheduledFor,newsletter:w,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:D.length>0?D:void 0};return Q.parse(I)}}B0();GA();var cN2=Z.object({prompt:Z.string().optional().describe("AI generation prompt"),sourceEntityIds:Z.array(Z.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:Z.enum(["post"]).optional().describe("Type of source entities"),content:Z.string().optional().describe("Direct content (skip AI)"),subject:Z.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:Z.boolean().optional().describe("Create as queued (true) or draft (false)")});class OJA extends Q9{constructor(A,Q){super(A,Q,{schema:cN2,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let B=A.addToQueue??!1,{prompt:w,sourceEntityIds:$,sourceEntityType:D}=A,{content:Y,subject:I}=A;if(Y){if(!I)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let F=D??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let V=(await Promise.all($.map((j)=>this.context.entityService.getEntity(F,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:
|
|
3821
3822
|
|
|
3822
3823
|
${V.map((j)=>`## ${j.metadata.title}
|
|
3823
3824
|
|
|
@@ -3886,17 +3887,17 @@ Newsletter-specific guidelines:
|
|
|
3886
3887
|
- "Reply and let me know..."
|
|
3887
3888
|
- "Until next time..."
|
|
3888
3889
|
|
|
3889
|
-
The goal is to build a relationship with readers through valuable, authentic content.`});GA();B0();import{jsxDEV as U7,Fragment as rN2}from"preact/jsx-dev-runtime";var pN2=Z.object({id:Z.string(),subject:Z.string(),status:$E,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),dN2=Z.object({newsletters:Z.array(pN2),totalCount:Z.number(),pagination:_7.nullable()}),iN2=({newsletters:A,totalCount:Q,pageTitle:B,pagination:w,baseUrl:$="/newsletters"})=>{let D=B??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return U7(rN2,{children:[U7(o2,{title:D,description:Y},void 0,!1,void 0,this),U7("div",{className:"newsletter-list bg-theme",children:U7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[U7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:D},void 0,!1,void 0,this),A.length===0?U7("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):U7("div",{className:"space-y-4",children:A.map((I)=>U7(MQ,{href:I.url,children:[U7(G9,{className:"text-lg",children:I.subject},void 0,!1,void 0,this),U7(Y7,{children:U7("div",{className:"flex items-center gap-3",children:[U7(n7,{status:I.status},void 0,!1,void 0,this),U7("span",{className:"text-sm text-theme-muted",children:m8(I.sentAt??I.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),I.excerpt&&U7("p",{className:"text-theme-muted line-clamp-2",children:I.excerpt},void 0,!1,void 0,this)]},I.id,!0,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&U7(jY,{currentPage:w.currentPage,totalPages:w.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)},MS0=M1({name:"newsletter-list",description:"Newsletter list page template",schema:dN2,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:iN2}});GA();B0();import{jsxDEV as D8,Fragment as aN2}from"preact/jsx-dev-runtime";var nN2=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),ES0=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),oN2=Z.object({id:Z.string(),subject:Z.string(),status:$E,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(nN2).optional(),prevNewsletter:ES0.nullable().optional(),nextNewsletter:ES0.nullable().optional()}),sN2=({subject:A,status:Q,content:B,created:w,sentAt:$,scheduledFor:D,sourceEntities:Y,prevNewsletter:I,nextNewsletter:X})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],W=$??w,J=$?"Sent":"Created";return D8(aN2,{children:[D8(o2,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),D8("section",{className:"newsletter-detail-section",children:D8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:D8("div",{className:"max-w-3xl mx-auto",children:[D8(QD,{items:H},void 0,!1,void 0,this),D8("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),D8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[D8(n7,{status:Q},void 0,!1,void 0,this),D8("span",{children:[J,": ",m8(W,{style:"long"})]},void 0,!0,void 0,this),D&&Q==="queued"&&D8("span",{children:["Scheduled for: ",m8(D,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&D8(MQ,{variant:"compact",className:"mb-8",children:[D8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),D8("ul",{className:"space-y-1",children:Y.map((F)=>D8("li",{children:D8("a",{href:F.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:F.title},void 0,!1,void 0,this)},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D8(RY,{markdown:B},void 0,!1,void 0,this),(I??X)&&D8("nav",{className:"mt-12 pt-8 border-t border-theme",children:D8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[I?D8(MQ,{href:I.url,variant:"compact",children:[D8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),D8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:I.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):D8("div",{},void 0,!1,void 0,this),X&&D8(MQ,{href:X.url,variant:"compact",className:"md:text-right",children:[D8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),D8("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)},CS0=M1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:oN2,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:sN2}});var OS0={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.
|
|
3890
|
+
The goal is to build a relationship with readers through valuable, authentic content.`});GA();B0();import{jsxDEV as U7,Fragment as rN2}from"preact/jsx-dev-runtime";var pN2=Z.object({id:Z.string(),subject:Z.string(),status:$E,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),dN2=Z.object({newsletters:Z.array(pN2),totalCount:Z.number(),pagination:_7.nullable()}),iN2=({newsletters:A,totalCount:Q,pageTitle:B,pagination:w,baseUrl:$="/newsletters"})=>{let D=B??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return U7(rN2,{children:[U7(o2,{title:D,description:Y},void 0,!1,void 0,this),U7("div",{className:"newsletter-list bg-theme",children:U7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[U7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:D},void 0,!1,void 0,this),A.length===0?U7("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):U7("div",{className:"space-y-4",children:A.map((I)=>U7(MQ,{href:I.url,children:[U7(G9,{className:"text-lg",children:I.subject},void 0,!1,void 0,this),U7(Y7,{children:U7("div",{className:"flex items-center gap-3",children:[U7(n7,{status:I.status},void 0,!1,void 0,this),U7("span",{className:"text-sm text-theme-muted",children:m8(I.sentAt??I.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),I.excerpt&&U7("p",{className:"text-theme-muted line-clamp-2",children:I.excerpt},void 0,!1,void 0,this)]},I.id,!0,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&U7(jY,{currentPage:w.currentPage,totalPages:w.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)},MS0=M1({name:"newsletter-list",description:"Newsletter list page template",schema:dN2,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:iN2}});GA();B0();import{jsxDEV as D8,Fragment as aN2}from"preact/jsx-dev-runtime";var nN2=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),ES0=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),oN2=Z.object({id:Z.string(),subject:Z.string(),status:$E,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(nN2).optional(),prevNewsletter:ES0.nullable().optional(),nextNewsletter:ES0.nullable().optional()}),sN2=({subject:A,status:Q,content:B,created:w,sentAt:$,scheduledFor:D,sourceEntities:Y,prevNewsletter:I,nextNewsletter:X})=>{let H=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],W=$??w,J=$?"Sent":"Created";return D8(aN2,{children:[D8(o2,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),D8("section",{className:"newsletter-detail-section",children:D8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:D8("div",{className:"max-w-3xl mx-auto",children:[D8(QD,{items:H},void 0,!1,void 0,this),D8("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),D8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[D8(n7,{status:Q},void 0,!1,void 0,this),D8("span",{children:[J,": ",m8(W,{style:"long"})]},void 0,!0,void 0,this),D&&Q==="queued"&&D8("span",{children:["Scheduled for: ",m8(D,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&D8(MQ,{variant:"compact",className:"mb-8",children:[D8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),D8("ul",{className:"space-y-1",children:Y.map((F)=>D8("li",{children:D8("a",{href:F.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:F.title},void 0,!1,void 0,this)},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D8(RY,{markdown:B},void 0,!1,void 0,this),(I??X)&&D8("nav",{className:"mt-12 pt-8 border-t border-theme",children:D8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[I?D8(MQ,{href:I.url,variant:"compact",children:[D8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),D8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:I.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):D8("div",{},void 0,!1,void 0,this),X&&D8(MQ,{href:X.url,variant:"compact",className:"md:text-right",children:[D8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),D8("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)},CS0=M1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:oN2,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:sN2}});var OS0={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.38",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/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 AV2=Z.object({});class fJA extends HQ{entityType="newsletter";schema=Ib;adapter=NS0;constructor(A={}){super("newsletter",OS0,A,AV2)}createGenerationHandler(A){return new OJA(this.logger,A)}getTemplates(){return{generation:LS0,"newsletter-list":MS0,"newsletter-detail":CS0}}getDataSources(){return[new CJA(this.logger.child("NewsletterDataSource"))]}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.subscribeToGenerateExecute(A),this.registerEvalHandlers(A),A.messaging.subscribe("system:plugins:ready",async()=>{let Q=await A.messaging.send("buttondown:is-configured",{});if(!("noop"in Q)&&Q.success)await A.messaging.send("plugin:site-builder:slot:register",{pluginId:this.id,slotName:"footer-top",render:()=>eN2(wKA,{variant:"inline"})});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("publish:register",{entityType:"newsletter",provider:Q}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:B,entityId:w}=Q.payload;if(B!=="newsletter")return{success:!0};try{let $=await A.entityService.getEntity("newsletter",w);if(!$)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:`Newsletter not found: ${w}`}),{success:!0};if($.metadata.status==="published")return{success:!0};let D=await A.messaging.send("buttondown:send",{entityId:w,subject:$.metadata.subject,content:$.content}),Y=new Date().toISOString(),I=!("noop"in D)&&D.data?D.data.emailId:void 0;return await A.entityService.updateEntity({...$,metadata:{...$.metadata,status:"published",sentAt:Y,buttondownId:I}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:w,sentAt:Y}),this.logger.info(`Published newsletter: ${w}`),{success:!0}}catch($){let D=L0($);return await A.messaging.send("publish:report:failure",{entityType:B,entityId:w,error:D}),{success:!0}}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let B=await A.entityService.listEntities("post",{filter:{metadata:{status:"published"}},limit:10});if(B.length===0)return await A.messaging.send("generate:report:failure",{entityType:"newsletter",error:"No published posts available for newsletter"}),{success:!0};return await A.jobs.enqueue("newsletter:generation",{sourceEntityIds:B.map((w)=>w.id),sourceEntityType:"post",addToQueue:!1},{interfaceType:"job",userId:"system"}),{success:!0}}catch(B){return await A.messaging.send("generate:report:failure",{entityType:"newsletter",error:L0(B)}),{success:!0}}})}registerEvalHandlers(A){let Q=Z.object({prompt:Z.string().optional(),content:Z.string().optional()});A.eval.registerHandler("generation",async(B)=>{let w=Q.parse(B),$=w.content?`Create an engaging newsletter based on this content:
|
|
3890
3891
|
|
|
3891
|
-
${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function RJA(A={}){return new fJA(A)}B0();GA();class DE{config;logger;constructor(A,Q){this.config=A;this.logger=Q}async request(A,Q={}){let B=`https://api.buttondown.email/v1${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let w=await fetch(B,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!w.ok){let $=await w.json().catch(()=>({})),D=$.detail??$.message??`HTTP ${w.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:w.status,error:D}),Error(`Buttondown API error: ${D}`)}return w.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(B){if(B instanceof Error&&B.message.includes("already subscribed")){let w=B.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:w?.[1]??"existing",email:A.email,subscriber_type:"already_subscribed"}}throw B}}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 B=Q.toString(),w=B?`/subscribers?${B}`:"/subscribers";return this.request(w)}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}}}B0();GA();var QV2=Z.object({email:Z.string().email().describe("Email address to subscribe"),name:Z.string().optional().describe("Subscriber name (optional)"),tags:Z.array(Z.string()).optional().describe("Tags to apply to subscriber (optional)")}),BV2=Z.object({email:Z.string().email().describe("Email address to unsubscribe")}),wV2=Z.object({type:Z.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:Z.number().optional().describe("Maximum number of results")});function fS0(A,Q,B){let w=new DE(Q,B);return[yQ(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",QV2,async($)=>{try{let D=await w.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),Y=D.subscriber_type==="already_subscribed";return O5({subscriberId:D.id,email:D.email,status:D.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(D){return Ew(L0(D))}}),yQ(A,"unsubscribe","Unsubscribe an email address from the newsletter.",BV2,async($)=>{try{return await w.unsubscribe($.email),O5({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(D){return Ew(L0(D))}}),yQ(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",wV2,async($)=>{try{let D=await w.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return O5({subscribers:D.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:D.count},`Found ${D.count} subscribers`)}catch(D){return Ew(L0(D))}})]}GA();async function RS0(A,Q,B,w){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let $=await B.getEntity("post",A.entityId);if(!$)return{success:!1,error:`Post ${A.entityId} not found`};w.info("Auto-sending newsletter for published post",{postId:$.id,title:$.metadata.title});try{let D=await Q.createEmail({subject:$.metadata.title,body:$.content,status:"about_to_send"});return w.info("Newsletter sent for post",{postId:$.id,emailId:D.id}),{success:!0,emailId:D.id}}catch(D){let Y=L0(D);return w.error("Failed to send newsletter for post",{postId:$.id,error:Y}),{success:!1,error:Y}}}var jS0={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.
|
|
3892
|
+
${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function RJA(A={}){return new fJA(A)}B0();GA();class DE{config;logger;constructor(A,Q){this.config=A;this.logger=Q}async request(A,Q={}){let B=`https://api.buttondown.email/v1${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let w=await fetch(B,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!w.ok){let $=await w.json().catch(()=>({})),D=$.detail??$.message??`HTTP ${w.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:w.status,error:D}),Error(`Buttondown API error: ${D}`)}return w.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(B){if(B instanceof Error&&B.message.includes("already subscribed")){let w=B.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:w?.[1]??"existing",email:A.email,subscriber_type:"already_subscribed"}}throw B}}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 B=Q.toString(),w=B?`/subscribers?${B}`:"/subscribers";return this.request(w)}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}}}B0();GA();var QV2=Z.object({email:Z.string().email().describe("Email address to subscribe"),name:Z.string().optional().describe("Subscriber name (optional)"),tags:Z.array(Z.string()).optional().describe("Tags to apply to subscriber (optional)")}),BV2=Z.object({email:Z.string().email().describe("Email address to unsubscribe")}),wV2=Z.object({type:Z.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:Z.number().optional().describe("Maximum number of results")});function fS0(A,Q,B){let w=new DE(Q,B);return[yQ(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",QV2,async($)=>{try{let D=await w.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),Y=D.subscriber_type==="already_subscribed";return O5({subscriberId:D.id,email:D.email,status:D.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(D){return Ew(L0(D))}}),yQ(A,"unsubscribe","Unsubscribe an email address from the newsletter.",BV2,async($)=>{try{return await w.unsubscribe($.email),O5({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(D){return Ew(L0(D))}}),yQ(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",wV2,async($)=>{try{let D=await w.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return O5({subscribers:D.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:D.count},`Found ${D.count} subscribers`)}catch(D){return Ew(L0(D))}})]}GA();async function RS0(A,Q,B,w){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let $=await B.getEntity("post",A.entityId);if(!$)return{success:!1,error:`Post ${A.entityId} not found`};w.info("Auto-sending newsletter for published post",{postId:$.id,title:$.metadata.title});try{let D=await Q.createEmail({subject:$.metadata.title,body:$.content,status:"about_to_send"});return w.info("Newsletter sent for post",{postId:$.id,emailId:D.id}),{success:!0,emailId:D.id}}catch(D){let Y=L0(D);return w.error("Failed to send newsletter for post",{postId:$.id,error:Y}),{success:!1,error:Y}}}var jS0={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.38",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 DV2=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class jJA extends tB{constructor(A={}){super("buttondown",jS0,A,DV2)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new DE({apiKey:this.config.apiKey,doubleOptIn:this.config.doubleOptIn},this.logger);if(A.messaging.subscribe("buttondown:send",async(B)=>{try{return{success:!0,data:{emailId:(await Q.createEmail({subject:B.payload.subject,body:B.payload.content,status:"about_to_send"})).id}}}catch(w){return this.logger.error("Buttondown send failed",{error:L0(w)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(B)=>{return await RS0(B.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 fS0(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 kJA(A={}){return new jJA(A)}var YV2=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function kS0(A={}){let Q=YV2.parse(A);return[RJA({}),kJA({...Q.apiKey!==void 0&&{apiKey:Q.apiKey},...Q.doubleOptIn!==void 0&&{doubleOptIn:Q.doubleOptIn},...Q.autoSendOnPublish!==void 0&&{autoSendOnPublish:Q.autoSendOnPublish}})]}B0();GA();import{existsSync as qV2,mkdirSync as NV2,writeFileSync as VV2}from"fs";import{join as BU}from"path";GA();var PJA=Z.object({baseFolder:Z.string().default("_obsidian")});GA();function IV2(A){let Q=A,B=!0,w=void 0,$=!1,D=!0;while(D){if(D=!1,Q instanceof Z.ZodOptional)B=!1,Q=Q._def.innerType,D=!0;if(Q instanceof Z.ZodDefault)B=!1,$=!0,w=Q._def.defaultValue(),Q=Q._def.innerType,D=!0;if(Q instanceof Z.ZodNullable)B=!1,Q=Q._def.innerType,D=!0}let Y={inner:Q,required:B};if($)Y.defaultValue=w;return Y}function XV2(A){if(A instanceof Z.ZodEnum)return{type:"enum",enumValues:A._def.values};if(A instanceof Z.ZodLiteral)return{type:"string",defaultValue:A._def.value};if(A instanceof Z.ZodString)return{type:"string"};if(A instanceof Z.ZodNumber)return{type:"number"};if(A instanceof Z.ZodBoolean)return{type:"boolean"};if(A instanceof Z.ZodArray)return{type:"array"};if(A instanceof Z.ZodDate)return{type:"date"};if(A instanceof Z.ZodPipeline){if(A._def.out instanceof Z.ZodDate)return{type:"date"}}return{type:"unknown"}}function PS0(A){let Q=A.shape,B=[];for(let[w,$]of Object.entries(Q)){let{inner:D,required:Y,defaultValue:I}=IV2($),X=XV2(D),H={name:w,type:X.type,required:Y},W=I!==void 0?I:X.defaultValue;if(W!==void 0)H.defaultValue=W;if(X.enumValues)H.enumValues=X.enumValues;B.push(H)}return B}function HV2(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 _S0(A,Q,B=""){let w=["---"];for(let $ of Q){let D=HV2($,A);if(D==="")w.push(`${$.name}:`);else w.push(`${$.name}: ${D}`)}if(w.push("---"),w.push(""),B)w.push(B);else w.push("<!-- Write your content here -->"),w.push("");return w.join(`
|
|
3892
3893
|
`)}GA();var KV2={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function UV2(A){let Q={name:A.name,id:A.name,type:KV2[A.type]};if(A.type==="enum"&&A.enumValues){let B={};A.enumValues.forEach((w,$)=>{B[String($)]=w}),Q.options=B}return Q}function bS0(A,Q){let B={filesPaths:A,fields:Q.map(UV2)};return`---
|
|
3893
3894
|
${O4(B)}---
|
|
3894
|
-
`}GA();var WV2=new Set(["entityType"]),GV2={base:"Notes"},JV2=new Set(["base"]);function FV2(A){let Q=["file.name"];for(let B of A)if(!WV2.has(B.name))Q.push(B.name);return Q}function ZV2(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function xS0(A,Q){let B=GV2[A]??$v(A),w=ZV2(Q),$=FV2(Q),D=[{type:"table",name:`All ${B}`,order:$}];if(w)D.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let I={filters:{and:[JV2.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:D};return{filename:`${B}.base`,content:O4(I),hasStatus:w}}function TS0(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w}")`),B={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return O4(B)}function vS0(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w.entityType}")`),B={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 O4(B)}var SS0={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.37",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 LV2={mkdir:NV2,writeFile:VV2,existsFile:qV2},MV2=Z.object({entityTypes:Z.array(Z.string()).optional().describe("Entity types to generate templates for (default: all)")});class _JA extends tB{deps;constructor(A={},Q={}){super("obsidian-vault",SS0,A,PJA);this.deps={...LV2,...Q}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A),{success:!0}})}async getTools(){let A=this.getContext();return[yQ(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",MV2,async(Q)=>{return this.sync(A,Q.entityTypes)})]}async sync(A,Q){try{let B=A.entityService.getEntityTypes(),w=Q?B.filter((L)=>Q.includes(L)):B,$=BU(A.dataDir,this.config.baseFolder),D=BU($,"templates"),Y=BU($,"fileClasses"),I=BU($,"bases");this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(I,{recursive:!0});let X=[],H=[],W=[],J=[],F=[],z=[];for(let L of w){let k=A.entities.getEffectiveFrontmatterSchema(L);if(!k){this.logger.debug(`Skipping ${L}: no frontmatter schema`),H.push(L);continue}let _=PS0(k),j=A.entities.getAdapter(L),r=j?.isSingleton===!0,n=bS0(L,_);if(this.deps.writeFile(BU(Y,`${L}.md`),n),W.push(L),r){F.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let g=j?.getBodyTemplate()??"",T=_S0(L,_,g);this.deps.writeFile(BU(D,`${L}.md`),T),X.push(L);let S=xS0(L,_),h=BU(I,S.filename);if(!this.deps.existsFile(h))this.deps.writeFile(h,S.content),J.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)z.push({entityType:L,fields:_});this.logger.debug(`Generated template + fileClass: ${L}`)}let V=TS0(F);if(V){let L=BU(I,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,V),J.push("Settings"),this.logger.debug("Generated Settings.base")}let E=vS0(z);if(E){let L=BU(I,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,E),J.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${X.length} templates, ${W.length} fileClasses, ${J.length} bases (${H.length} skipped)`),O5({generated:X,skipped:H,fileClasses:W,bases:J})}catch(B){return this.logger.error("Failed to sync",{error:B}),Ew(B instanceof Error?B.message:"Unknown error")}}}function bJA(A,Q){return new _JA(A,Q)}B0();GA();B0();var xJA=Z.enum(["new","planned","in-progress","done","declined"]),TJA=Z.enum(["low","medium","high","critical"]),Xb=Z.object({title:Z.string(),status:xJA,priority:TJA.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),hS0=Z.object({title:Z.string(),status:xJA,priority:TJA,requested:Z.number().int(),slug:Z.string()}),Hb=U2.extend({entityType:Z.literal("wish"),metadata:hS0}),vJA=Z.object({});B0();GA();class Kb extends E2{constructor(){super({entityType:"wish",schema:Hb,frontmatterSchema:Xb})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Xb);return{frontmatter:Xb.parse(Q),description:this.extractBody(A).trim()}}toMarkdown(A){return A.content}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),B=e1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:B}}}}var SJA=new Kb;GA();GA();async function gS0(A,Q){let B=`${Q.title}: ${Q.description}`,$=(await A.search(B,{types:["wish"],limit:1}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let D=e1(Q.title);return A.getEntity("wish",D)}class pi{logger;context;adapter=new Kb;constructor(A,Q){this.logger=A;this.context=Q}async process(A,Q,B){let w=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",D=await gS0({search:(H,W)=>this.context.entityService.search(H,W),getEntity:(H,W)=>this.context.entityService.getEntity(H,W),similarityThreshold:0.85},{title:w,description:$});if(D){let{frontmatter:H,description:W}=this.adapter.parseWishContent(D.content),J=H.requested+1,F=this.adapter.createWishContent({...H,requested:J},W);return await this.context.entityService.updateEntity({...D,content:F,metadata:{...D.metadata,requested:J}}),this.logger.info("Incremented wish request count",{id:D.id,requested:J}),{success:!0,entityId:D.id,existed:!0,requested:J}}let Y=e1(w),I=A.options?.priority??"medium",X=this.adapter.createWishContent({title:w,status:"new",priority:I,requested:1},$);return await this.context.entityService.createEntity({id:Y,entityType:"wish",content:X,metadata:{title:w,status:"new",priority:I,requested:1,slug:Y}}),this.logger.info("Created new wish",{id:Y,title:w}),{success:!0,entityId:Y,existed:!1,requested:1}}}var yS0={critical:0,high:1,medium:2,low:3};function mS0(A){A.sort((Q,B)=>{let w=B.metadata.requested-Q.metadata.requested;if(w!==0)return w;return yS0[Q.metadata.priority]-yS0[B.metadata.priority]})}var uS0={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.37",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 cS0 extends HQ{entityType=SJA.entityType;schema=Hb;adapter=SJA;constructor(A={}){super("wishlist",uS0,A,vJA)}async interceptCreate(A,Q,B){let w=await new pi(this.logger,B).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!w.success)return{kind:"handled",result:{success:!1,error:w.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...w.entityId?{entityId:w.entityId}:{},status:w.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"top-wishes",pluginId:this.id,title:"Top Wishes",section:"secondary",priority:30,rendererName:"ListWidget",dataProvider:async()=>{let B=await A.entityService.listEntities("wish",{limit:10});return mS0(B),{items:B.map((w)=>({id:w.id,name:w.metadata.title,count:w.metadata.requested,priority:w.metadata.priority,status:w.metadata.status}))}}}),{success:!0}});let Q=new pi(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(B)=>B})}async getInstructions(){return"**CRITICAL \u2014 Unfulfilled requests**: ALWAYS call `system_create` with entityType "+`"wish" BEFORE responding when you cannot fulfill a user's request. This applies to ALL unfulfillable requests: physical actions, missing integrations, and any capability `+"you lack. Do NOT just explain you can't do it \u2014 create the wish first, THEN respond. "+'In your response, tell the user their request has been added to the wishlist. CRITICAL exception: for A2A agent-contact requests, never create a wish for a missing, ambiguous, archived, URL-only, unsaved-domain, or not-yet-saved local agent-directory target. This includes requests that contain a full agent URL, a bare domain like unknown-agent.io, or phrasing like "message this agent URL for me". Those are save-first directory cases, not wishlist cases. In those cases, tell the user to add/save or clarify the agent first. Never call system_create with entityType "wish" for those agent-contact cases. Only create or save an agent entry if the user explicitly asks you to add or save that agent.'}}function CV2(A={}){return new cS0(A)}var di=CV2;B0();GA();B0();var Ub=Z.object({title:Z.string(),target:Z.string()}),lS0=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),Wb=U2.extend({entityType:Z.literal("prompt"),metadata:lS0});B0();GA();class hJA extends E2{constructor(){super({entityType:"prompt",schema:Wb,frontmatterSchema:Ub})}toMarkdown(A){let Q=this.extractBody(A.content),B=this.parseFrontMatter(A.content,Ub);return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ub),B=e1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:B}}}}var ii=new hJA;var pS0={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.37",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 gJA extends HQ{entityType=ii.entityType;schema=Wb;adapter=ii;constructor(){super("prompt",pS0,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function Hz(){return new gJA}B0();GA();class ri{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let B=new URL(`${this.baseUrl}/search/photos`);B.searchParams.set("query",A),B.searchParams.set("page",String(Q.page)),B.searchParams.set("per_page",String(Q.perPage));let w=await this.fetchFn(B.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!w.ok)throw Error(`Unsplash API error: ${w.status} ${w.statusText}`);let $=await w.json();return{photos:$.results.map(fV2),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function fV2(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}}GA();var dS0={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},iS0={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.string().url().describe("Photographer profile URL for attribution"),sourceUrl:Z.string().url().describe("Photo page URL on provider"),imageUrl:Z.string().url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")};function nS0(A,Q){return[RV2(A,Q),jV2(A,Q)]}function RV2(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:dS0,handler:async(B)=>{let w=Z.object(dS0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(w.data.query,{page:w.data.page,perPage:w.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function jV2(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:iS0,handler:async(B)=>{let w=Z.object(iS0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{photoId:$,downloadLocation:D,photographerName:Y,photographerUrl:I,sourceUrl:X,imageUrl:H,title:W,alt:J,targetEntityType:F,targetEntityId:z}=w.data,V={photographerName:Y,photographerUrl:I,sourceUrl:X},E=await Q.entityService.listEntities("image",{limit:1,filter:{metadata:{sourceUrl:H}}});if(E[0]){let g={imageEntityId:E[0].id,alreadyExisted:!0,attribution:V};if(F&&z)await rS0(Q.entityService,F,z,E[0].id),g.coverSet=!0;return{success:!0,data:g}}Q.provider.triggerDownload(D).catch(()=>{});let L;try{L=await Q.fetchImage(H)}catch(g){return{success:!1,error:g instanceof Error?g.message:"Image download failed"}}let k=W??`Stock photo ${$}`,_=nW.createImageEntity({dataUrl:L,title:k,alt:J??k}),j={id:$,..._,metadata:{..._.metadata,sourceUrl:H}},{entityId:r}=await Q.entityService.createEntity(j),n={imageEntityId:r,alreadyExisted:!1,attribution:V};if(F&&z)await rS0(Q.entityService,F,z,r),n.coverSet=!0;return{success:!0,data:n}}}}async function rS0(A,Q,B,w){let $=await A.getEntity(Q,B);if(!$)return;await A.updateEntity({...$,metadata:{...$.metadata,coverImageId:w}})}GA();var oS0={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.37",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 PV2=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class yJA extends tB{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",oS0,A,PV2);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=new ri(this.config.apiKey,this.deps.fetch??globalThis.fetch);return this.cachedTools=nS0(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??R7}),this.cachedTools}}function mJA(A={},Q={}){return new yJA(A,Q)}GA();B0();GA();B0();var ni=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),Kz=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),pY=AY.pick({name:!0,kind:!0,organization:!0}).extend({brainName:Z.string().describe("Name of the brain instance"),url:Z.string().url().describe("Brain endpoint URL"),did:Z.string().optional().describe("Decentralized identifier (public)"),status:Kz,discoveredAt:Z.string().datetime().describe("When this agent was first discovered")}),sS0=pY.pick({name:!0,url:!0,status:!0}).extend({slug:Z.string()}),Uz=U2.extend({entityType:Z.literal("agent"),metadata:sS0}),Gb=Uz.extend({frontmatter:pY,about:Z.string(),skills:Z.array(ni),notes:Z.string()}),YE=Gb.extend({url:Z.string().optional(),typeLabel:Z.string().optional()}),_V2=Gb.extend({url:Z.string(),typeLabel:Z.string()});B0();GA();var bV2=Z.object({about:Z.string(),skills:Z.array(Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())})),notes:Z.string()});function xV2(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((B)=>{let w=B.tags.length>0?` [${B.tags.join(", ")}]`:"";return`- ${B.name}: ${B.description}${w}`}).join(`
|
|
3895
|
+
`}GA();var WV2=new Set(["entityType"]),GV2={base:"Notes"},JV2=new Set(["base"]);function FV2(A){let Q=["file.name"];for(let B of A)if(!WV2.has(B.name))Q.push(B.name);return Q}function ZV2(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function xS0(A,Q){let B=GV2[A]??$v(A),w=ZV2(Q),$=FV2(Q),D=[{type:"table",name:`All ${B}`,order:$}];if(w)D.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let I={filters:{and:[JV2.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:D};return{filename:`${B}.base`,content:O4(I),hasStatus:w}}function TS0(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w}")`),B={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return O4(B)}function vS0(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w.entityType}")`),B={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 O4(B)}var SS0={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.38",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 LV2={mkdir:NV2,writeFile:VV2,existsFile:qV2},MV2=Z.object({entityTypes:Z.array(Z.string()).optional().describe("Entity types to generate templates for (default: all)")});class _JA extends tB{deps;constructor(A={},Q={}){super("obsidian-vault",SS0,A,PJA);this.deps={...LV2,...Q}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A),{success:!0}})}async getTools(){let A=this.getContext();return[yQ(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",MV2,async(Q)=>{return this.sync(A,Q.entityTypes)})]}async sync(A,Q){try{let B=A.entityService.getEntityTypes(),w=Q?B.filter((L)=>Q.includes(L)):B,$=BU(A.dataDir,this.config.baseFolder),D=BU($,"templates"),Y=BU($,"fileClasses"),I=BU($,"bases");this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(I,{recursive:!0});let X=[],H=[],W=[],J=[],F=[],z=[];for(let L of w){let k=A.entities.getEffectiveFrontmatterSchema(L);if(!k){this.logger.debug(`Skipping ${L}: no frontmatter schema`),H.push(L);continue}let _=PS0(k),j=A.entities.getAdapter(L),r=j?.isSingleton===!0,n=bS0(L,_);if(this.deps.writeFile(BU(Y,`${L}.md`),n),W.push(L),r){F.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let g=j?.getBodyTemplate()??"",T=_S0(L,_,g);this.deps.writeFile(BU(D,`${L}.md`),T),X.push(L);let S=xS0(L,_),h=BU(I,S.filename);if(!this.deps.existsFile(h))this.deps.writeFile(h,S.content),J.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)z.push({entityType:L,fields:_});this.logger.debug(`Generated template + fileClass: ${L}`)}let V=TS0(F);if(V){let L=BU(I,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,V),J.push("Settings"),this.logger.debug("Generated Settings.base")}let E=vS0(z);if(E){let L=BU(I,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,E),J.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${X.length} templates, ${W.length} fileClasses, ${J.length} bases (${H.length} skipped)`),O5({generated:X,skipped:H,fileClasses:W,bases:J})}catch(B){return this.logger.error("Failed to sync",{error:B}),Ew(B instanceof Error?B.message:"Unknown error")}}}function bJA(A,Q){return new _JA(A,Q)}B0();GA();B0();var xJA=Z.enum(["new","planned","in-progress","done","declined"]),TJA=Z.enum(["low","medium","high","critical"]),Xb=Z.object({title:Z.string(),status:xJA,priority:TJA.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),hS0=Z.object({title:Z.string(),status:xJA,priority:TJA,requested:Z.number().int(),slug:Z.string()}),Hb=U2.extend({entityType:Z.literal("wish"),metadata:hS0}),vJA=Z.object({});B0();GA();class Kb extends E2{constructor(){super({entityType:"wish",schema:Hb,frontmatterSchema:Xb})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Xb);return{frontmatter:Xb.parse(Q),description:this.extractBody(A).trim()}}toMarkdown(A){return A.content}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),B=e1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:B}}}}var SJA=new Kb;GA();GA();async function gS0(A,Q){let B=`${Q.title}: ${Q.description}`,$=(await A.search(B,{types:["wish"],limit:1}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let D=e1(Q.title);return A.getEntity("wish",D)}class pi{logger;context;adapter=new Kb;constructor(A,Q){this.logger=A;this.context=Q}async process(A,Q,B){let w=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",D=await gS0({search:(H,W)=>this.context.entityService.search(H,W),getEntity:(H,W)=>this.context.entityService.getEntity(H,W),similarityThreshold:0.85},{title:w,description:$});if(D){let{frontmatter:H,description:W}=this.adapter.parseWishContent(D.content),J=H.requested+1,F=this.adapter.createWishContent({...H,requested:J},W);return await this.context.entityService.updateEntity({...D,content:F,metadata:{...D.metadata,requested:J}}),this.logger.info("Incremented wish request count",{id:D.id,requested:J}),{success:!0,entityId:D.id,existed:!0,requested:J}}let Y=e1(w),I=A.options?.priority??"medium",X=this.adapter.createWishContent({title:w,status:"new",priority:I,requested:1},$);return await this.context.entityService.createEntity({id:Y,entityType:"wish",content:X,metadata:{title:w,status:"new",priority:I,requested:1,slug:Y}}),this.logger.info("Created new wish",{id:Y,title:w}),{success:!0,entityId:Y,existed:!1,requested:1}}}var yS0={critical:0,high:1,medium:2,low:3};function mS0(A){A.sort((Q,B)=>{let w=B.metadata.requested-Q.metadata.requested;if(w!==0)return w;return yS0[Q.metadata.priority]-yS0[B.metadata.priority]})}var uS0={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.38",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 cS0 extends HQ{entityType=SJA.entityType;schema=Hb;adapter=SJA;constructor(A={}){super("wishlist",uS0,A,vJA)}async interceptCreate(A,Q,B){let w=await new pi(this.logger,B).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!w.success)return{kind:"handled",result:{success:!1,error:w.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...w.entityId?{entityId:w.entityId}:{},status:w.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"top-wishes",pluginId:this.id,title:"Top Wishes",section:"secondary",priority:30,rendererName:"ListWidget",dataProvider:async()=>{let B=await A.entityService.listEntities("wish",{limit:10});return mS0(B),{items:B.map((w)=>({id:w.id,name:w.metadata.title,count:w.metadata.requested,priority:w.metadata.priority,status:w.metadata.status}))}}}),{success:!0}});let Q=new pi(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(B)=>B})}async getInstructions(){return"**CRITICAL \u2014 Unfulfilled requests**: ALWAYS call `system_create` with entityType "+`"wish" BEFORE responding when you cannot fulfill a user's request. This applies to ALL unfulfillable requests: physical actions, missing integrations, and any capability `+"you lack. Do NOT just explain you can't do it \u2014 create the wish first, THEN respond. "+'In your response, tell the user their request has been added to the wishlist. CRITICAL exception: for A2A agent-contact requests, never create a wish for a missing, ambiguous, archived, URL-only, unsaved-domain, or not-yet-saved local agent-directory target. This includes requests that contain a full agent URL, a bare domain like unknown-agent.io, or phrasing like "message this agent URL for me". Those are save-first directory cases, not wishlist cases. In those cases, tell the user to add/save or clarify the agent first. Never call system_create with entityType "wish" for those agent-contact cases. Only create or save an agent entry if the user explicitly asks you to add or save that agent.'}}function CV2(A={}){return new cS0(A)}var di=CV2;B0();GA();B0();var Ub=Z.object({title:Z.string(),target:Z.string()}),lS0=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),Wb=U2.extend({entityType:Z.literal("prompt"),metadata:lS0});B0();GA();class hJA extends E2{constructor(){super({entityType:"prompt",schema:Wb,frontmatterSchema:Ub})}toMarkdown(A){let Q=this.extractBody(A.content),B=this.parseFrontMatter(A.content,Ub);return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ub),B=e1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:B}}}}var ii=new hJA;var pS0={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.38",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 gJA extends HQ{entityType=ii.entityType;schema=Wb;adapter=ii;constructor(){super("prompt",pS0,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function Hz(){return new gJA}B0();GA();class ri{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let B=new URL(`${this.baseUrl}/search/photos`);B.searchParams.set("query",A),B.searchParams.set("page",String(Q.page)),B.searchParams.set("per_page",String(Q.perPage));let w=await this.fetchFn(B.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!w.ok)throw Error(`Unsplash API error: ${w.status} ${w.statusText}`);let $=await w.json();return{photos:$.results.map(fV2),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function fV2(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}}GA();var dS0={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},iS0={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.string().url().describe("Photographer profile URL for attribution"),sourceUrl:Z.string().url().describe("Photo page URL on provider"),imageUrl:Z.string().url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")};function nS0(A,Q){return[RV2(A,Q),jV2(A,Q)]}function RV2(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:dS0,handler:async(B)=>{let w=Z.object(dS0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(w.data.query,{page:w.data.page,perPage:w.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function jV2(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:iS0,handler:async(B)=>{let w=Z.object(iS0).safeParse(B);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{photoId:$,downloadLocation:D,photographerName:Y,photographerUrl:I,sourceUrl:X,imageUrl:H,title:W,alt:J,targetEntityType:F,targetEntityId:z}=w.data,V={photographerName:Y,photographerUrl:I,sourceUrl:X},E=await Q.entityService.listEntities("image",{limit:1,filter:{metadata:{sourceUrl:H}}});if(E[0]){let g={imageEntityId:E[0].id,alreadyExisted:!0,attribution:V};if(F&&z)await rS0(Q.entityService,F,z,E[0].id),g.coverSet=!0;return{success:!0,data:g}}Q.provider.triggerDownload(D).catch(()=>{});let L;try{L=await Q.fetchImage(H)}catch(g){return{success:!1,error:g instanceof Error?g.message:"Image download failed"}}let k=W??`Stock photo ${$}`,_=nW.createImageEntity({dataUrl:L,title:k,alt:J??k}),j={id:$,..._,metadata:{..._.metadata,sourceUrl:H}},{entityId:r}=await Q.entityService.createEntity(j),n={imageEntityId:r,alreadyExisted:!1,attribution:V};if(F&&z)await rS0(Q.entityService,F,z,r),n.coverSet=!0;return{success:!0,data:n}}}}async function rS0(A,Q,B,w){let $=await A.getEntity(Q,B);if(!$)return;await A.updateEntity({...$,metadata:{...$.metadata,coverImageId:w}})}GA();var oS0={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.38",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 PV2=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class yJA extends tB{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",oS0,A,PV2);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=new ri(this.config.apiKey,this.deps.fetch??globalThis.fetch);return this.cachedTools=nS0(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??R7}),this.cachedTools}}function mJA(A={},Q={}){return new yJA(A,Q)}GA();B0();GA();B0();var ni=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),Kz=Z.enum(["discovered","approved"]).describe("Discovered for review or approved for calling"),pY=AY.pick({name:!0,kind:!0,organization:!0}).extend({brainName:Z.string().describe("Name of the brain instance"),url:Z.string().url().describe("Brain endpoint URL"),did:Z.string().optional().describe("Decentralized identifier (public)"),status:Kz,discoveredAt:Z.string().datetime().describe("When this agent was first discovered")}),sS0=pY.pick({name:!0,url:!0,status:!0}).extend({slug:Z.string()}),Uz=U2.extend({entityType:Z.literal("agent"),metadata:sS0}),Gb=Uz.extend({frontmatter:pY,about:Z.string(),skills:Z.array(ni),notes:Z.string()}),YE=Gb.extend({url:Z.string().optional(),typeLabel:Z.string().optional()}),_V2=Gb.extend({url:Z.string(),typeLabel:Z.string()});B0();GA();var bV2=Z.object({about:Z.string(),skills:Z.array(Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())})),notes:Z.string()});function xV2(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((B)=>{let w=B.tags.length>0?` [${B.tags.join(", ")}]`:"";return`- ${B.name}: ${B.description}${w}`}).join(`
|
|
3895
3896
|
`)}function TV2(A){if(!A.trim())return[];let Q=[];for(let B of A.split(`
|
|
3896
3897
|
`)){let w=B.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(w){let $=w[1]??"",D=w[2]??"",Y=w[3],I=Y?Y.split(",").map((X)=>X.trim()).filter(Boolean):[];Q.push({name:$,description:D,tags:I})}}return Q}var aS0=new dB(bV2,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:xV2,parser:TV2},{key:"notes",label:"Notes",type:"string"}]});class V9 extends E2{constructor(){super({entityType:"agent",schema:Uz,frontmatterSchema:pY})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,pY),B=eq(Q.url);return{content:A,entityType:"agent",metadata:{name:Q.name,url:Q.url,status:Q.status,slug:B}}}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},status:Kz.parse(A.status),discoveredAt:A.discoveredAt},B=aS0.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(B,Q)}parseAgentContent(A){let Q=this.extractBody(A);if(!Q.trim())return{about:"",skills:[],notes:""};try{let B=aS0.parse(Q);return{about:B.about,skills:B.skills,notes:B.notes}}catch{return{about:"",skills:[],notes:""}}}parseEntity(A){return{frontmatter:this.parseFrontMatter(A.content,pY),body:this.parseAgentContent(A.content)}}}B0();GA();var vV2=new V9,SV2=mI.extend({status:Z.enum(["discovered","approved"]).optional()}),hV2=uI.extend({query:SV2.optional()});function gV2(A){let Q=F2(A.content,pY),B=vV2.parseAgentContent(A.content);return Gb.parse({...A,frontmatter:Q.metadata,about:B.about,skills:B.skills,notes:B.notes})}class oi extends s5{id="agent-discovery:entities";name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:"agent",defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return gV2(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=hV2.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,B){return{agents:A,pagination:Q,baseUrl:B.baseUrl,selectedStatus:B.status==="discovered"||B.status==="approved"?B.status:"all"}}async fetch(A,Q,B){let{query:w}=this.parseQuery(A);if(w.id)return super.fetch(A,Q,B);let{items:$,pagination:D}=await this.fetchList(w,B.entityService,w.status?{filter:{metadata:{status:w.status}}}:void 0);return Q.parse(this.buildListResult($,D,w))}}B0();GA();B0();async function tS0(A,Q){let w=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let $=await Q(w);if(!$.ok)return null;let D=await $.json();return lO(D)}catch{return null}}function eS0(A){let Q=A.trim();if(Q.startsWith("http://")||Q.startsWith("https://"))try{return new URL(Q).hostname}catch{return Q}let B=Q.match(/https?:\/\/[^\s]+?(?=[.,;:!?)]*(?:\s|$))/);if(B)try{return new URL(B[0]).hostname}catch{return B[0]}if(/^[^\s]+\.[^\s]+$/.test(Q))return Q;return""}GA();var yV2=new V9;function Ah0(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function dY(A){let Q=new Set,B=[];for(let w of A){let $=Ah0(w);if(!$||Q.has($))continue;Q.add($),B.push($)}return B}function mV2(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function Qh0(A,Q={}){let B=Q.minCount??1,w=Q.topN??12,$=new Map,[D,Y]=await Promise.all([A.entityService.listEntities("skill"),A.entityService.listEntities("agent")]),I=(X)=>{for(let H of dY(X))$.set(H,($.get(H)??0)+1)};for(let X of D)I(X.metadata.tags);for(let X of Y){let H=yV2.parseAgentContent(X.content);I(H.skills.flatMap((W)=>W.tags))}return Array.from($.entries()).map(([X,H])=>({tag:X,count:H})).filter((X)=>X.count>=B).sort(mV2).slice(0,w)}function Bh0(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:B})=>`- ${Q} (${B})`)].join(`
|
|
3897
|
-
`)}var uV2=new V9;function wh0(A){let
|
|
3898
|
+
`)}var uV2=new V9;function wh0(A,Q={}){let B=A.anchor?.name??A.brainName,w=A.anchor?.kind??"professional",$=[];if(A.anchor?.description)$.push(A.anchor.description);if(A.description)$.push(A.description);let D=Q.status??"discovered";return{content:uV2.createAgentContent({name:B,kind:w,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:D,discoveredAt:new Date().toISOString(),about:$.join(`
|
|
3898
3899
|
|
|
3899
|
-
`),skills:A.skills.map((D)=>({name:D.name,description:D.description,tags:dY(D.tags)})),notes:""}),metadata:{name:Q,url:A.url,status:"discovered",slug:eq(A.url)},anchorName:Q}}var cV2=Z.object({prompt:Z.string().optional(),url:Z.string().optional(),content:Z.string().optional(),skipAi:Z.boolean().optional()}),nDB=j7.extend({name:Z.string().optional(),domain:Z.string().optional()});class uJA extends Q9{constructor(A,Q){super(A,Q,{schema:cV2,jobTypeName:"agent-generation",entityType:"agent"})}async generate(A,Q){let B=A.url??A.prompt??"",w=eS0(B);if(!w)throw Error("No URL or domain provided. Use: system_create agent with a domain like yeehaa.io");let $=await tS0(w,globalThis.fetch);if(!$)throw Error(`Could not fetch Agent Card from ${w}. Make sure the agent is running and accessible.`);let{content:D,metadata:Y,anchorName:I}=wh0($);return{id:w,content:D,metadata:Y,title:I}}}GA();B0();GA();B0();var Jb=Z.object({title:Z.string(),detail:Z.string().optional()}),wU=Z.object({strengths:Z.array(Jb).default([]),weaknesses:Z.array(Jb).default([]),opportunities:Z.array(Jb).default([]),threats:Z.array(Jb).default([]),derivedAt:Z.string().datetime()}),$h0=wU.pick({derivedAt:!0}),IE=U2.extend({entityType:Z.literal("swot"),metadata:$h0}),cJA=Z.object({reason:Z.string().default("entity-change")}),si=Z.object({theme:Z.string(),evidence:Z.string(),action:Z.string()}),lJA=Z.object({strengths:Z.array(si),weaknesses:Z.array(si),opportunities:Z.array(si),threats:Z.array(si)}),ai=Z.object({sourceTheme:Z.string(),title:Z.string(),detail:Z.string().nullable()}),ti=Z.object({strengths:Z.array(ai),weaknesses:Z.array(ai),opportunities:Z.array(ai),threats:Z.array(ai)});class iY extends E2{constructor(){super({entityType:"swot",schema:IE,frontmatterSchema:wU})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,wU);return{content:A,entityType:"swot",metadata:{derivedAt:Q.derivedAt}}}createSwotContent(A){return this.buildMarkdown("",A)}parseSwotContent(A){return{frontmatter:wU.parse(this.parseFrontMatter(A,wU))}}}var lV2=new iY;var pV2=new V9,dV2=new iY,Dh0=pY.shape.kind,pJA=["all",...Dh0.options],iV2=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),wU.extend({status:Z.literal("ready")})]),ei=Z.object({id:Z.string(),name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),kind:Dh0,status:Kz,discoveredAt:Z.string()}),rV2=Z.object({id:Z.string(),name:Z.string(),tags:Z.array(Z.string()),sourceLabel:Z.string(),sourceType:Z.enum(["brain","agent"])}),nV2=Z.object({tag:Z.string(),count:Z.number(),variant:Z.enum(["gap"]).optional()}),Yh0=Z.object({counts:Z.object({agents:Z.number(),skills:Z.number()}),overview:iV2,agents:Z.object({all:Z.array(ei),professional:Z.array(ei),team:Z.array(ei),collective:Z.array(ei)}),skillFilters:Z.array(nV2),skills:Z.array(rV2)});function oV2(A){let Q=A.replace(/\s+/g," ").trim();if(!Q)return;let B=Q.match(/^(.*?[.!?])(?:\s|$)/);if(B?.[1])return B[1];return Q.length<=200?Q:`${Q.slice(0,197)}\u2026`}function sV2(A){return A.name===A.brainName?A.name:`${A.name} \xB7 ${A.brainName}`}function aV2(A,Q){return oV2(Q)??[A.kind,A.organization].filter(Boolean).join(" \xB7 ")}function tV2(A,Q){let B=Q.tags.length-A.tags.length;if(B!==0)return B;let w=new Date(Q.discoveredAt).getTime()-new Date(A.discoveredAt).getTime();if(w!==0)return w;return A.name.localeCompare(Q.name)}function eV2(A,Q){if(A.sourceType!==Q.sourceType)return A.sourceType==="brain"?-1:1;let B=A.name.localeCompare(Q.name);if(B!==0)return B;return A.sourceLabel.localeCompare(Q.sourceLabel)}function AL2(A){let Q=new Map;for(let D of A){let Y=new Set(D.tags),I=D.sourceType==="brain"?"brain":`agent:${D.sourceLabel}`;for(let X of Y){let H=Q.get(X)??{count:0,hasBrain:!1,sources:new Set};if(H.count+=1,H.sources.add(I),D.sourceType==="brain")H.hasBrain=!0;Q.set(X,H)}}let B=Array.from(Q.entries()).map(([D,Y])=>({tag:D,...Y})).sort((D,Y)=>{if(Y.count!==D.count)return Y.count-D.count;return D.tag.localeCompare(Y.tag)}),w=[],$=new Set;for(let D of B.filter((Y)=>Y.sources.size>1).slice(0,5))w.push({tag:D.tag,count:D.count}),$.add(D.tag);for(let D of B.filter((Y)=>Y.hasBrain&&Y.sources.size===1)){if($.has(D.tag))continue;w.push({tag:D.tag,count:D.count,variant:"gap"})}return w}function QL2(A){if(!A)return{status:"generating"};let{frontmatter:Q}=dV2.parseSwotContent(A.content);return{status:"ready",...Q}}async function Ih0(A){let[Q,B,w]=await Promise.all([A.entityService.listEntities("agent"),A.entityService.listEntities("skill"),A.entityService.getEntity("swot","swot")]),$=Q.map((H)=>({entity:H,...pV2.parseEntity(H)})),D=$.map(({entity:H,frontmatter:W,body:J})=>({id:H.id,name:sV2(W),description:aV2(W,J.about),tags:dY(J.skills.flatMap((F)=>F.tags)),kind:W.kind,status:W.status,discoveredAt:W.discoveredAt})).sort(tV2),Y=[],I=new Set,X=(H)=>{let W=`${H.sourceType}:${H.sourceLabel}:${H.name.toLowerCase()}`;if(I.has(W))return;I.add(W),Y.push(H)};for(let H of B)X({id:`brain:${H.id}`,name:H.metadata.name,tags:dY(H.metadata.tags),sourceLabel:"brain",sourceType:"brain"});for(let{entity:H,frontmatter:W,body:J}of $)J.skills.forEach((F,z)=>{X({id:`${H.id}:${z}`,name:F.name,tags:dY(F.tags),sourceLabel:W.brainName,sourceType:"agent"})});return Y.sort(eV2),{counts:{agents:D.length,skills:Y.length},overview:QL2(w),agents:{all:D,professional:D.filter((H)=>H.kind==="professional"),team:D.filter((H)=>H.kind==="team"),collective:D.filter((H)=>H.kind==="collective")},skillFilters:AL2(Y),skills:Y}}B0();s8();GA();import{jsxDEV as Xh0}from"preact/jsx-dev-runtime";function Ar(A){try{return new URL(A).hostname}catch{return A}}var Qr=({name:A,className:Q=""})=>{let B=A.charAt(0).toUpperCase(),w=0;for(let D=0;D<A.length;D++)w=A.charCodeAt(D)+((w<<5)-w);let $=Math.abs(w)%360;return Xh0("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${$}, 55%, 45%)`},children:B},void 0,!1,void 0,this)},Br=({kind:A,size:Q="md"})=>{let w={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 Xh0("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]"} ${w}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as n1,Fragment as $L2}from"preact/jsx-dev-runtime";var BL2=({skills:A})=>{if(A.length===0)return null;return n1("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>n1("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 wL2(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function Hh0(A,Q,B){let w=new URLSearchParams({status:Q});if(B>1)w.set("page",String(B));return`${A}?${w.toString()}`}var dJA=({agent:A})=>{let{frontmatter:Q,about:B,skills:w,url:$}=A,D=Q.status==="approved";return n1("a",{href:$,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${D?"":"opacity-70"}`,children:[n1(Qr,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),n1("div",{className:"flex-1 min-w-0",children:[n1("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[n1("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),n1(Br,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&n1("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),B&&n1("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:B},void 0,!1,void 0,this),D&&n1(BL2,{skills:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[n1("span",{className:"text-xs text-theme-muted",children:Ar(Q.url)},void 0,!1,void 0,this),n1("span",{className:"text-[11px] text-theme-muted opacity-60",children:D?`Discovered ${wL2(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)},Kh0=({agents:A,pageTitle:Q,pagination:B,baseUrl:w="/agents",selectedStatus:$})=>{let D=Q??"Agent Directory",Y=B?.totalItems??A.length,I=A.filter((F)=>F.frontmatter.status==="approved"),X=A.filter((F)=>F.frontmatter.status==="discovered"),H=I.length,W=X.length,J=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return n1($L2,{children:[n1(o2,{title:D,description:J},void 0,!1,void 0,this),n1("div",{className:"agent-list bg-theme",children:n1("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[n1("div",{className:"mb-8 pb-6 border-b border-theme",children:[n1("h1",{className:"text-4xl font-bold text-heading mb-2",children:D},void 0,!1,void 0,this),n1("p",{className:"text-theme-muted mb-4",children:J},void 0,!1,void 0,this),n1("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[n1("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),n1("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),n1("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),n1("div",{className:"flex flex-wrap gap-2 text-sm",children:[n1("a",{href:w,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),n1("a",{href:`${w}?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),n1("a",{href:`${w}?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"&&I.length>0&&n1("section",{className:"mb-10",children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),n1("span",{className:"text-sm text-theme-muted",children:I.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:I.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&n1("section",{children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("div",{children:[n1("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),n1("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),n1("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:X.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&n1("section",{children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),n1("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:A.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&n1("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),B&&B.totalPages>1&&$==="all"&&n1("div",{className:"mt-12",children:n1(jY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&B.totalPages>1&&$!=="all"&&n1("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[B.hasPrevPage?n1("a",{href:Hh0(w,$,B.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):n1("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),n1("span",{className:"text-sm text-theme-muted",children:["Page ",B.currentPage," of ",B.totalPages]},void 0,!0,void 0,this),B.hasNextPage?n1("a",{href:Hh0(w,$,B.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):n1("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 c1,Fragment as XL2}from"preact/jsx-dev-runtime";function DL2(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var Fb=({children:A})=>c1("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),YL2=({skill:A})=>c1("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[c1("div",{className:"flex-1",children:[c1("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),c1("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&&c1("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>c1("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),IL2=({label:A,value:Q,valueClassName:B})=>c1("div",{className:"flex justify-between text-[13px]",children:[c1("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),c1("span",{className:B??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Uh0=({agent:A,prevAgent:Q,nextAgent:B})=>{let{frontmatter:w,about:$,skills:D,notes:Y}=A,I=Ar(w.url),X=w.status==="approved";return c1(XL2,{children:[c1(o2,{title:w.name,description:$||`Agent profile for ${w.name}`},void 0,!1,void 0,this),c1("article",{className:"agent-detail",children:c1("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[c1("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),c1("div",{className:"flex items-start gap-6 mb-8",children:[c1(Qr,{name:w.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),c1("div",{children:[c1("div",{className:"flex items-center gap-3 mb-1",children:[c1("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:w.name},void 0,!1,void 0,this),c1(Br,{kind:w.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c1("div",{className:"text-base text-theme-muted mb-2",children:w.brainName},void 0,!1,void 0,this),c1("div",{className:"flex items-center gap-3 text-theme-muted",children:[w.organization&&c1("span",{className:"text-[15px]",children:w.organization},void 0,!1,void 0,this),w.organization&&c1("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),c1("span",{className:"text-sm",children:["Discovered ",DL2(w.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),c1("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!X&&c1("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[c1("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),c1("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),c1("div",{className:"flex flex-col md:flex-row gap-12",children:[c1("div",{className:"flex-[2] min-w-0",children:[$&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"About"},void 0,!1,void 0,this),c1("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D.length>0&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"Skills"},void 0,!1,void 0,this),c1("div",{className:"flex flex-col gap-2.5",children:D.map((H)=>c1(YL2,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"Notes"},void 0,!1,void 0,this),c1("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c1("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[c1("section",{className:"mb-8",children:[c1(Fb,{children:"Brain"},void 0,!1,void 0,this),c1("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[c1("div",{className:"text-[15px] font-semibold text-heading mb-1",children:w.brainName},void 0,!1,void 0,this),w.did&&c1("div",{className:"text-xs text-theme-muted font-mono",children:w.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c1("section",{className:"mb-8",children:[c1(Fb,{children:"Connection"},void 0,!1,void 0,this),c1("div",{className:"flex flex-col gap-3",children:[c1("div",{children:[c1("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),c1("div",{className:"text-xs text-heading font-mono",children:w.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c1(IL2,{label:"Status",value:w.status==="approved"?"Approved":"Discovered",valueClassName:w.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),c1("a",{href:w.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 ",I," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??B)&&c1("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:[c1("div",{className:"min-h-[1px]",children:Q&&c1("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[c1("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),c1("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),c1("div",{className:"min-h-[1px] md:text-right",children:B&&c1("a",{href:B.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[c1("span",{children:"Next \u2192"},void 0,!1,void 0,this),c1("span",{className:"text-heading font-medium",children:B.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 HL2=Z.object({agents:Z.array(YE),pageTitle:Z.string().optional(),pagination:_7.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.enum(["all","discovered","approved"])});function Wh0(){return{"agent-list":M1({name:"agent-list",description:"Agent directory list page template",schema:HL2,dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:Kh0}}),"agent-detail":M1({name:"agent-detail",description:"Individual agent profile template",schema:Z.object({agent:YE,prevAgent:YE.nullable(),nextAgent:YE.nullable()}),dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:Uh0}})}}GA();import{jsxDEV as L9}from"preact/jsx-dev-runtime";var wr=Z.object({title:Z.string(),detail:Z.string().optional()}),KL2=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(wr).default([]),weaknesses:Z.array(wr).default([]),opportunities:Z.array(wr).default([]),threats:Z.array(wr).default([]),derivedAt:Z.string()})]);function UL2({items:A}){if(A.length===0)return L9("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return L9("ul",{class:"swot-list",children:A.map((Q)=>L9("li",{class:"swot-item",children:[L9("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?L9("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 $r({title:A,tone:Q,items:B}){return L9("section",{class:`swot-cell is-${Q}`,children:[L9("div",{class:"swot-head",children:A},void 0,!1,void 0,this),L9(UL2,{items:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function iJA({data:A}){let Q=KL2.safeParse(A);if(!Q.success||Q.data.status==="generating")return L9("div",{"data-swot-widget":!0,children:L9("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let B=Q.data;return L9("div",{"data-swot-widget":!0,children:L9("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[L9($r,{title:"Strengths",tone:"s",items:B.strengths},void 0,!1,void 0,this),L9($r,{title:"Weaknesses",tone:"w",items:B.weaknesses},void 0,!1,void 0,this),L9($r,{title:"Opportunities",tone:"o",items:B.opportunities},void 0,!1,void 0,this),L9($r,{title:"Threats",tone:"t",items:B.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as v2}from"preact/jsx-dev-runtime";var rJA=`(function () {
|
|
3900
|
+
`),skills:A.skills.map((I)=>({name:I.name,description:I.description,tags:dY(I.tags)})),notes:""}),metadata:{name:B,url:A.url,status:D,slug:eq(A.url)},anchorName:B}}var cV2=Z.object({prompt:Z.string().optional(),url:Z.string().optional(),content:Z.string().optional(),skipAi:Z.boolean().optional(),status:Z.enum(["discovered","approved"]).optional()}),nDB=j7.extend({name:Z.string().optional(),domain:Z.string().optional()});class uJA extends Q9{constructor(A,Q){super(A,Q,{schema:cV2,jobTypeName:"agent-generation",entityType:"agent"})}async generate(A,Q){let B=A.url??A.prompt??"",w=eS0(B);if(!w)throw Error("No URL or domain provided. Use: system_create agent with a domain like yeehaa.io");let $=await tS0(w,globalThis.fetch);if(!$)throw Error(`Could not fetch Agent Card from ${w}. Make sure the agent is running and accessible.`);let{content:D,metadata:Y,anchorName:I}=wh0($,{...A.status!==void 0?{status:A.status}:{}});return{id:w,content:D,metadata:Y,title:I}}}GA();B0();GA();B0();var Jb=Z.object({title:Z.string(),detail:Z.string().optional()}),wU=Z.object({strengths:Z.array(Jb).default([]),weaknesses:Z.array(Jb).default([]),opportunities:Z.array(Jb).default([]),threats:Z.array(Jb).default([]),derivedAt:Z.string().datetime()}),$h0=wU.pick({derivedAt:!0}),IE=U2.extend({entityType:Z.literal("swot"),metadata:$h0}),cJA=Z.object({reason:Z.string().default("entity-change")}),si=Z.object({theme:Z.string(),evidence:Z.string(),action:Z.string()}),lJA=Z.object({strengths:Z.array(si),weaknesses:Z.array(si),opportunities:Z.array(si),threats:Z.array(si)}),ai=Z.object({sourceTheme:Z.string(),title:Z.string(),detail:Z.string().nullable()}),ti=Z.object({strengths:Z.array(ai),weaknesses:Z.array(ai),opportunities:Z.array(ai),threats:Z.array(ai)});class iY extends E2{constructor(){super({entityType:"swot",schema:IE,frontmatterSchema:wU})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,wU);return{content:A,entityType:"swot",metadata:{derivedAt:Q.derivedAt}}}createSwotContent(A){return this.buildMarkdown("",A)}parseSwotContent(A){return{frontmatter:wU.parse(this.parseFrontMatter(A,wU))}}}var lV2=new iY;var pV2=new V9,dV2=new iY,Dh0=pY.shape.kind,pJA=["all",...Dh0.options],iV2=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),wU.extend({status:Z.literal("ready")})]),ei=Z.object({id:Z.string(),name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),kind:Dh0,status:Kz,discoveredAt:Z.string()}),rV2=Z.object({id:Z.string(),name:Z.string(),tags:Z.array(Z.string()),sourceLabel:Z.string(),sourceType:Z.enum(["brain","agent"])}),nV2=Z.object({tag:Z.string(),count:Z.number(),variant:Z.enum(["gap"]).optional()}),Yh0=Z.object({counts:Z.object({agents:Z.number(),skills:Z.number()}),overview:iV2,agents:Z.object({all:Z.array(ei),professional:Z.array(ei),team:Z.array(ei),collective:Z.array(ei)}),skillFilters:Z.array(nV2),skills:Z.array(rV2)});function oV2(A){let Q=A.replace(/\s+/g," ").trim();if(!Q)return;let B=Q.match(/^(.*?[.!?])(?:\s|$)/);if(B?.[1])return B[1];return Q.length<=200?Q:`${Q.slice(0,197)}\u2026`}function sV2(A){return A.name===A.brainName?A.name:`${A.name} \xB7 ${A.brainName}`}function aV2(A,Q){return oV2(Q)??[A.kind,A.organization].filter(Boolean).join(" \xB7 ")}function tV2(A,Q){let B=Q.tags.length-A.tags.length;if(B!==0)return B;let w=new Date(Q.discoveredAt).getTime()-new Date(A.discoveredAt).getTime();if(w!==0)return w;return A.name.localeCompare(Q.name)}function eV2(A,Q){if(A.sourceType!==Q.sourceType)return A.sourceType==="brain"?-1:1;let B=A.name.localeCompare(Q.name);if(B!==0)return B;return A.sourceLabel.localeCompare(Q.sourceLabel)}function AL2(A){let Q=new Map;for(let D of A){let Y=new Set(D.tags),I=D.sourceType==="brain"?"brain":`agent:${D.sourceLabel}`;for(let X of Y){let H=Q.get(X)??{count:0,hasBrain:!1,sources:new Set};if(H.count+=1,H.sources.add(I),D.sourceType==="brain")H.hasBrain=!0;Q.set(X,H)}}let B=Array.from(Q.entries()).map(([D,Y])=>({tag:D,...Y})).sort((D,Y)=>{if(Y.count!==D.count)return Y.count-D.count;return D.tag.localeCompare(Y.tag)}),w=[],$=new Set;for(let D of B.filter((Y)=>Y.sources.size>1).slice(0,5))w.push({tag:D.tag,count:D.count}),$.add(D.tag);for(let D of B.filter((Y)=>Y.hasBrain&&Y.sources.size===1)){if($.has(D.tag))continue;w.push({tag:D.tag,count:D.count,variant:"gap"})}return w}function QL2(A){if(!A)return{status:"generating"};let{frontmatter:Q}=dV2.parseSwotContent(A.content);return{status:"ready",...Q}}async function Ih0(A){let[Q,B,w]=await Promise.all([A.entityService.listEntities("agent"),A.entityService.listEntities("skill"),A.entityService.getEntity("swot","swot")]),$=Q.map((H)=>({entity:H,...pV2.parseEntity(H)})),D=$.map(({entity:H,frontmatter:W,body:J})=>({id:H.id,name:sV2(W),description:aV2(W,J.about),tags:dY(J.skills.flatMap((F)=>F.tags)),kind:W.kind,status:W.status,discoveredAt:W.discoveredAt})).sort(tV2),Y=[],I=new Set,X=(H)=>{let W=`${H.sourceType}:${H.sourceLabel}:${H.name.toLowerCase()}`;if(I.has(W))return;I.add(W),Y.push(H)};for(let H of B)X({id:`brain:${H.id}`,name:H.metadata.name,tags:dY(H.metadata.tags),sourceLabel:"brain",sourceType:"brain"});for(let{entity:H,frontmatter:W,body:J}of $)J.skills.forEach((F,z)=>{X({id:`${H.id}:${z}`,name:F.name,tags:dY(F.tags),sourceLabel:W.brainName,sourceType:"agent"})});return Y.sort(eV2),{counts:{agents:D.length,skills:Y.length},overview:QL2(w),agents:{all:D,professional:D.filter((H)=>H.kind==="professional"),team:D.filter((H)=>H.kind==="team"),collective:D.filter((H)=>H.kind==="collective")},skillFilters:AL2(Y),skills:Y}}B0();s8();GA();import{jsxDEV as Xh0}from"preact/jsx-dev-runtime";function Ar(A){try{return new URL(A).hostname}catch{return A}}var Qr=({name:A,className:Q=""})=>{let B=A.charAt(0).toUpperCase(),w=0;for(let D=0;D<A.length;D++)w=A.charCodeAt(D)+((w<<5)-w);let $=Math.abs(w)%360;return Xh0("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${$}, 55%, 45%)`},children:B},void 0,!1,void 0,this)},Br=({kind:A,size:Q="md"})=>{let w={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 Xh0("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]"} ${w}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as n1,Fragment as $L2}from"preact/jsx-dev-runtime";var BL2=({skills:A})=>{if(A.length===0)return null;return n1("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>n1("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 wL2(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function Hh0(A,Q,B){let w=new URLSearchParams({status:Q});if(B>1)w.set("page",String(B));return`${A}?${w.toString()}`}var dJA=({agent:A})=>{let{frontmatter:Q,about:B,skills:w,url:$}=A,D=Q.status==="approved";return n1("a",{href:$,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${D?"":"opacity-70"}`,children:[n1(Qr,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),n1("div",{className:"flex-1 min-w-0",children:[n1("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[n1("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),n1(Br,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&n1("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),B&&n1("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:B},void 0,!1,void 0,this),D&&n1(BL2,{skills:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[n1("span",{className:"text-xs text-theme-muted",children:Ar(Q.url)},void 0,!1,void 0,this),n1("span",{className:"text-[11px] text-theme-muted opacity-60",children:D?`Discovered ${wL2(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)},Kh0=({agents:A,pageTitle:Q,pagination:B,baseUrl:w="/agents",selectedStatus:$})=>{let D=Q??"Agent Directory",Y=B?.totalItems??A.length,I=A.filter((F)=>F.frontmatter.status==="approved"),X=A.filter((F)=>F.frontmatter.status==="discovered"),H=I.length,W=X.length,J=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return n1($L2,{children:[n1(o2,{title:D,description:J},void 0,!1,void 0,this),n1("div",{className:"agent-list bg-theme",children:n1("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[n1("div",{className:"mb-8 pb-6 border-b border-theme",children:[n1("h1",{className:"text-4xl font-bold text-heading mb-2",children:D},void 0,!1,void 0,this),n1("p",{className:"text-theme-muted mb-4",children:J},void 0,!1,void 0,this),n1("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[n1("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),n1("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[H," approved"]},void 0,!0,void 0,this),n1("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),n1("div",{className:"flex flex-wrap gap-2 text-sm",children:[n1("a",{href:w,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),n1("a",{href:`${w}?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),n1("a",{href:`${w}?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"&&I.length>0&&n1("section",{className:"mb-10",children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),n1("span",{className:"text-sm text-theme-muted",children:I.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:I.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$==="all"&&X.length>0&&n1("section",{children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("div",{children:[n1("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),n1("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),n1("span",{className:"text-sm text-theme-muted",children:X.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:X.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$!=="all"&&A.length>0&&n1("section",{children:[n1("div",{className:"flex items-center justify-between mb-4",children:[n1("h2",{className:"text-lg font-semibold text-heading",children:$==="approved"?"Approved brains":"Discovered brains"},void 0,!1,void 0,this),n1("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n1("div",{className:"flex flex-col gap-4",children:A.map((F)=>n1(dJA,{agent:F},F.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&n1("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),B&&B.totalPages>1&&$==="all"&&n1("div",{className:"mt-12",children:n1(jY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&B.totalPages>1&&$!=="all"&&n1("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[B.hasPrevPage?n1("a",{href:Hh0(w,$,B.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):n1("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),n1("span",{className:"text-sm text-theme-muted",children:["Page ",B.currentPage," of ",B.totalPages]},void 0,!0,void 0,this),B.hasNextPage?n1("a",{href:Hh0(w,$,B.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):n1("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 c1,Fragment as XL2}from"preact/jsx-dev-runtime";function DL2(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var Fb=({children:A})=>c1("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),YL2=({skill:A})=>c1("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[c1("div",{className:"flex-1",children:[c1("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),c1("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&&c1("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>c1("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),IL2=({label:A,value:Q,valueClassName:B})=>c1("div",{className:"flex justify-between text-[13px]",children:[c1("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),c1("span",{className:B??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Uh0=({agent:A,prevAgent:Q,nextAgent:B})=>{let{frontmatter:w,about:$,skills:D,notes:Y}=A,I=Ar(w.url),X=w.status==="approved";return c1(XL2,{children:[c1(o2,{title:w.name,description:$||`Agent profile for ${w.name}`},void 0,!1,void 0,this),c1("article",{className:"agent-detail",children:c1("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[c1("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),c1("div",{className:"flex items-start gap-6 mb-8",children:[c1(Qr,{name:w.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),c1("div",{children:[c1("div",{className:"flex items-center gap-3 mb-1",children:[c1("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:w.name},void 0,!1,void 0,this),c1(Br,{kind:w.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c1("div",{className:"text-base text-theme-muted mb-2",children:w.brainName},void 0,!1,void 0,this),c1("div",{className:"flex items-center gap-3 text-theme-muted",children:[w.organization&&c1("span",{className:"text-[15px]",children:w.organization},void 0,!1,void 0,this),w.organization&&c1("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),c1("span",{className:"text-sm",children:["Discovered ",DL2(w.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),c1("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!X&&c1("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[c1("div",{className:"text-sm font-semibold text-heading mb-1",children:"Saved for review"},void 0,!1,void 0,this),c1("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),c1("div",{className:"flex flex-col md:flex-row gap-12",children:[c1("div",{className:"flex-[2] min-w-0",children:[$&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"About"},void 0,!1,void 0,this),c1("p",{className:"text-[15px] text-theme leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D.length>0&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"Skills"},void 0,!1,void 0,this),c1("div",{className:"flex flex-col gap-2.5",children:D.map((H)=>c1(YL2,{skill:H},H.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&c1("section",{className:"mb-8",children:[c1(Fb,{children:"Notes"},void 0,!1,void 0,this),c1("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c1("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[c1("section",{className:"mb-8",children:[c1(Fb,{children:"Brain"},void 0,!1,void 0,this),c1("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[c1("div",{className:"text-[15px] font-semibold text-heading mb-1",children:w.brainName},void 0,!1,void 0,this),w.did&&c1("div",{className:"text-xs text-theme-muted font-mono",children:w.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c1("section",{className:"mb-8",children:[c1(Fb,{children:"Connection"},void 0,!1,void 0,this),c1("div",{className:"flex flex-col gap-3",children:[c1("div",{children:[c1("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),c1("div",{className:"text-xs text-heading font-mono",children:w.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c1(IL2,{label:"Status",value:w.status==="approved"?"Approved":"Discovered",valueClassName:w.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),c1("a",{href:w.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 ",I," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??B)&&c1("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:[c1("div",{className:"min-h-[1px]",children:Q&&c1("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[c1("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),c1("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),c1("div",{className:"min-h-[1px] md:text-right",children:B&&c1("a",{href:B.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[c1("span",{children:"Next \u2192"},void 0,!1,void 0,this),c1("span",{className:"text-heading font-medium",children:B.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 HL2=Z.object({agents:Z.array(YE),pageTitle:Z.string().optional(),pagination:_7.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.enum(["all","discovered","approved"])});function Wh0(){return{"agent-list":M1({name:"agent-list",description:"Agent directory list page template",schema:HL2,dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:Kh0}}),"agent-detail":M1({name:"agent-detail",description:"Individual agent profile template",schema:Z.object({agent:YE,prevAgent:YE.nullable(),nextAgent:YE.nullable()}),dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:Uh0}})}}GA();import{jsxDEV as L9}from"preact/jsx-dev-runtime";var wr=Z.object({title:Z.string(),detail:Z.string().optional()}),KL2=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(wr).default([]),weaknesses:Z.array(wr).default([]),opportunities:Z.array(wr).default([]),threats:Z.array(wr).default([]),derivedAt:Z.string()})]);function UL2({items:A}){if(A.length===0)return L9("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return L9("ul",{class:"swot-list",children:A.map((Q)=>L9("li",{class:"swot-item",children:[L9("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?L9("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 $r({title:A,tone:Q,items:B}){return L9("section",{class:`swot-cell is-${Q}`,children:[L9("div",{class:"swot-head",children:A},void 0,!1,void 0,this),L9(UL2,{items:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function iJA({data:A}){let Q=KL2.safeParse(A);if(!Q.success||Q.data.status==="generating")return L9("div",{"data-swot-widget":!0,children:L9("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let B=Q.data;return L9("div",{"data-swot-widget":!0,children:L9("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[L9($r,{title:"Strengths",tone:"s",items:B.strengths},void 0,!1,void 0,this),L9($r,{title:"Weaknesses",tone:"w",items:B.weaknesses},void 0,!1,void 0,this),L9($r,{title:"Opportunities",tone:"o",items:B.opportunities},void 0,!1,void 0,this),L9($r,{title:"Threats",tone:"t",items:B.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as v2}from"preact/jsx-dev-runtime";var rJA=`(function () {
|
|
3900
3901
|
function setActive(nodes, match) {
|
|
3901
3902
|
nodes.forEach(function (node) {
|
|
3902
3903
|
var active = match(node);
|
|
@@ -3993,7 +3994,7 @@ ${O4(B)}---
|
|
|
3993
3994
|
setView("overview");
|
|
3994
3995
|
setTagFilter("all");
|
|
3995
3996
|
});
|
|
3996
|
-
})();`;function WL2({item:A}){return v2("li",{class:"list-item",children:[v2("div",{class:"list-main",children:[v2("span",{class:"list-name",children:A.name},void 0,!1,void 0,this),v2("span",{class:"list-desc",children:A.description},void 0,!1,void 0,this),A.tags.length>0&&v2("div",{class:"list-tags",children:A.tags.map((Q)=>v2("span",{class:"tag",children:Q},`${A.id}:${Q}`,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("div",{class:"list-meta",children:A.status==="discovered"&&v2("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 GL2({item:A}){return v2("li",{class:"list-item agent-network-skill-row","data-agent-network-skill-row":!0,"data-agent-network-tags":JSON.stringify(A.tags),children:[v2("div",{class:"list-main",children:v2("span",{class:"list-name",children:A.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),v2("div",{class:"list-meta",children:v2("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 JL2({overview:A}){return v2("div",{class:"agent-network-panel is-active","data-agent-network-panel":"overview",children:v2(iJA,{data:A},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function FL2({kind:A,items:Q,active:B}){return v2("div",{class:`agent-network-panel${B?" is-active":""}`,"data-agent-network-panel":A,children:Q.length>0?v2("ul",{class:"list agent-network-list",children:Q.map((w)=>v2(WL2,{item:w},w.id,!1,void 0,this))},void 0,!1,void 0,this):v2("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ZL2({skills:A,count:Q,filters:B}){return v2("div",{class:"agent-network-panel","data-agent-network-panel":"skills",children:[v2("div",{class:"agent-network-filter-row",role:"tablist","aria-label":"Filter skills by tag",children:[v2("button",{class:"agent-network-filter is-active",type:"button","data-agent-network-tag-filter":"all","aria-pressed":"true",children:[v2("span",{class:"count",children:Q},void 0,!1,void 0,this),v2("span",{class:"label",children:"all"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.map((w)=>v2("button",{class:`agent-network-filter${w.variant==="gap"?" is-gap":""}`,type:"button","data-agent-network-tag-filter":w.tag,"aria-pressed":"false",children:[v2("span",{class:"count",children:w.count},void 0,!1,void 0,this),v2("span",{class:"label",children:w.tag},void 0,!1,void 0,this)]},w.tag,!0,void 0,this))]},void 0,!0,void 0,this),A.length>0?v2("ul",{class:"list agent-network-list agent-network-skills-list",children:A.map((w)=>v2(GL2,{item:w},w.id,!1,void 0,this))},void 0,!1,void 0,this):v2("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function nJA({data:A}){let Q=Yh0.safeParse(A);if(!Q.success)return v2("p",{class:"muted",children:"Nothing to show yet."},void 0,!1,void 0,this);let B=Q.data;return v2("div",{"data-agent-network-widget":!0,"data-agent-network-view":"overview",children:[v2("div",{class:"agent-network-view-tabs",role:"tablist","aria-label":"Browse the agent network",children:[v2("button",{class:"agent-network-view-tab is-active",type:"button","data-agent-network-view-tab":"overview","aria-pressed":"true",children:"Overview"},void 0,!1,void 0,this),v2("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"agents","aria-pressed":"false",children:["Agents",v2("span",{class:"agent-network-view-count",children:B.counts.agents},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"skills","aria-pressed":"false",children:["Skills",v2("span",{class:"agent-network-view-count",children:B.counts.skills},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),v2("div",{class:"agent-network-kind-tabs",role:"tablist","aria-label":"Filter agents by kind",children:pJA.map((w)=>{let $=w==="all";return v2("button",{class:`agent-network-kind-tab${$?" is-active":""}`,type:"button","data-agent-network-kind-tab":w,"aria-pressed":$?"true":"false",children:[v2("span",{class:"agent-network-kind-count",children:B.agents[w].length},void 0,!1,void 0,this),v2("span",{class:"agent-network-kind-label",children:w},void 0,!1,void 0,this)]},w,!0,void 0,this)})},void 0,!1,void 0,this),v2(JL2,{overview:B.overview},void 0,!1,void 0,this),pJA.map((w)=>v2(FL2,{kind:w,items:B.agents[w],active:!1},w,!1,void 0,this)),v2(ZL2,{skills:B.skills,count:B.counts.skills,filters:B.skillFilters},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Wz={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.
|
|
3997
|
+
})();`;function WL2({item:A}){return v2("li",{class:"list-item",children:[v2("div",{class:"list-main",children:[v2("span",{class:"list-name",children:A.name},void 0,!1,void 0,this),v2("span",{class:"list-desc",children:A.description},void 0,!1,void 0,this),A.tags.length>0&&v2("div",{class:"list-tags",children:A.tags.map((Q)=>v2("span",{class:"tag",children:Q},`${A.id}:${Q}`,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("div",{class:"list-meta",children:A.status==="discovered"&&v2("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 GL2({item:A}){return v2("li",{class:"list-item agent-network-skill-row","data-agent-network-skill-row":!0,"data-agent-network-tags":JSON.stringify(A.tags),children:[v2("div",{class:"list-main",children:v2("span",{class:"list-name",children:A.name},void 0,!1,void 0,this)},void 0,!1,void 0,this),v2("div",{class:"list-meta",children:v2("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 JL2({overview:A}){return v2("div",{class:"agent-network-panel is-active","data-agent-network-panel":"overview",children:v2(iJA,{data:A},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function FL2({kind:A,items:Q,active:B}){return v2("div",{class:`agent-network-panel${B?" is-active":""}`,"data-agent-network-panel":A,children:Q.length>0?v2("ul",{class:"list agent-network-list",children:Q.map((w)=>v2(WL2,{item:w},w.id,!1,void 0,this))},void 0,!1,void 0,this):v2("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function ZL2({skills:A,count:Q,filters:B}){return v2("div",{class:"agent-network-panel","data-agent-network-panel":"skills",children:[v2("div",{class:"agent-network-filter-row",role:"tablist","aria-label":"Filter skills by tag",children:[v2("button",{class:"agent-network-filter is-active",type:"button","data-agent-network-tag-filter":"all","aria-pressed":"true",children:[v2("span",{class:"count",children:Q},void 0,!1,void 0,this),v2("span",{class:"label",children:"all"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.map((w)=>v2("button",{class:`agent-network-filter${w.variant==="gap"?" is-gap":""}`,type:"button","data-agent-network-tag-filter":w.tag,"aria-pressed":"false",children:[v2("span",{class:"count",children:w.count},void 0,!1,void 0,this),v2("span",{class:"label",children:w.tag},void 0,!1,void 0,this)]},w.tag,!0,void 0,this))]},void 0,!0,void 0,this),A.length>0?v2("ul",{class:"list agent-network-list agent-network-skills-list",children:A.map((w)=>v2(GL2,{item:w},w.id,!1,void 0,this))},void 0,!1,void 0,this):v2("p",{class:"agent-network-empty",children:"Nothing to show yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function nJA({data:A}){let Q=Yh0.safeParse(A);if(!Q.success)return v2("p",{class:"muted",children:"Nothing to show yet."},void 0,!1,void 0,this);let B=Q.data;return v2("div",{"data-agent-network-widget":!0,"data-agent-network-view":"overview",children:[v2("div",{class:"agent-network-view-tabs",role:"tablist","aria-label":"Browse the agent network",children:[v2("button",{class:"agent-network-view-tab is-active",type:"button","data-agent-network-view-tab":"overview","aria-pressed":"true",children:"Overview"},void 0,!1,void 0,this),v2("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"agents","aria-pressed":"false",children:["Agents",v2("span",{class:"agent-network-view-count",children:B.counts.agents},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v2("button",{class:"agent-network-view-tab",type:"button","data-agent-network-view-tab":"skills","aria-pressed":"false",children:["Skills",v2("span",{class:"agent-network-view-count",children:B.counts.skills},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),v2("div",{class:"agent-network-kind-tabs",role:"tablist","aria-label":"Filter agents by kind",children:pJA.map((w)=>{let $=w==="all";return v2("button",{class:`agent-network-kind-tab${$?" is-active":""}`,type:"button","data-agent-network-kind-tab":w,"aria-pressed":$?"true":"false",children:[v2("span",{class:"agent-network-kind-count",children:B.agents[w].length},void 0,!1,void 0,this),v2("span",{class:"agent-network-kind-label",children:w},void 0,!1,void 0,this)]},w,!0,void 0,this)})},void 0,!1,void 0,this),v2(JL2,{overview:B.overview},void 0,!1,void 0,this),pJA.map((w)=>v2(FL2,{kind:w,items:B.agents[w],active:!1},w,!1,void 0,this)),v2(ZL2,{skills:B.skills,count:B.counts.skills,filters:B.skillFilters},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var Wz={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.38",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",eval:"cd evals && bun run brain-eval"},dependencies:{"@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 qL2=new V9;class oJA extends HQ{entityType="agent";schema=Uz;adapter=qL2;constructor(){super("agent-discovery",Wz)}async interceptCreate(A,Q,B){if(A.url&&!A.prompt&&!A.content)return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await B.jobs.enqueue("agent:generation",{prompt:A.url,url:A.url,status:"approved"},Q)}}};return{kind:"continue",input:A}}createGenerationHandler(A){return new uJA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return Wh0()}getDataSources(){return[new oi(this.logger.child("AgentDataSource"))]}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send("dashboard:register-widget",{id:"agent-network",pluginId:this.id,title:"Agent Network",section:"secondary",priority:15,rendererName:"AgentNetworkWidget",component:nJA,clientScript:rJA,dataProvider:async()=>Ih0(A)}),{success:!0}})}async getInstructions(){return'## Agent directory\n- Add a new agent contact with `system_create` using `entityType: "agent"` and pass the domain or URL in `url`.\n- List saved agents with `system_list` using `entityType: "agent"`.\n- Approve a discovered agent with `system_update` on the `agent` entity using `fields` (for example `fields: { status: "approved" }`). Do not replace the full content just to change status.\n- When the user explicitly says `approve`, `approve it`, `yes approve`, or `approve <agent-id>`, call `system_update` immediately with `fields: { status: "approved" }` and `confirmed: true`. Do not ask for another confirmation for that explicit approval request.\n- If the previous turn identified one specific discovered agent, treat a short follow-up like `approve`, `approve it`, or `yes approve` as referring to that same agent id.\n- If `system_update` says to use `fields`, or says full content replacement is invalid/empty, retry once immediately with `fields` instead of surfacing that error to the user.\n- If the user gives an exact saved agent id like `old-agent.io`, call that single `system_update` directly instead of listing/searching first.\n- Calling and saving agents are separate actions: if an agent is not saved yet, tell the user it is not saved in the local agent directory yet and ask them to add/save it first.\n- If a user gives an agent URL, do not call it directly. Save the agent first, then use its local agent id.\n- A URL-based or unsaved-domain agent contact request is a save-first directory case, not a wishlist case.\n- If more than one saved agent could match the user\u2019s name-based reference, ask which saved agent they mean before calling anything.\n- Do not create a wish or any other entity for a missing or ambiguous agent unless the user explicitly asks you to add or save that agent.'}}function sJA(){return new oJA}B0();GA();GA();B0();var HJ=NN,Gh0=NN,XE=U2.extend({entityType:Z.literal("skill"),metadata:Gh0});B0();class KJ extends E2{constructor(){super({entityType:"skill",schema:XE,frontmatterSchema:HJ})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,HJ);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}GA();function NL2(A){let Q=[];if(A.topicTitles.length>0)Q.push(`The brain's knowledge domains (from content analysis):
|
|
3997
3998
|
${A.topicTitles.map((w)=>`- ${w}`).join(`
|
|
3998
3999
|
`)}`);if(A.toolDescriptions.length>0)Q.push(`The brain has these capabilities:
|
|
3999
4000
|
${A.toolDescriptions.map((w)=>`- ${w}`).join(`
|
|
@@ -4135,7 +4136,7 @@ Context:
|
|
|
4135
4136
|
${JSON.stringify(w,null,2)}
|
|
4136
4137
|
|
|
4137
4138
|
Draft SWOT:
|
|
4138
|
-
${JSON.stringify(B,null,2)}`}function Xr(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function PL2(A,Q){let B=["strengths","weaknesses","opportunities","threats"];for(let w of B){let $=new Set(A[w].map((D)=>D.theme.trim().toLowerCase()));for(let D of Q[w]){let Y=D.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${D.sourceTheme}" in ${w}`)}}}class Hr{logger;context;adapter=new iY;constructor(A,Q){this.logger=A;this.context=Q}validateAndParse(A){let Q=cJA.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,B){await B.report({progress:0.2,message:"Building SWOT context"});let w=await eJA(this.context),$;if(w.summary.brainSkillCount+w.summary.approvedAgentCount+w.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await B.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:H}=await this.context.ai.generateObject(await RL2(this.context,w),lJA),W=lJA.parse(H);await B.report({progress:0.75,message:"Refining SWOT language"});let J=await this.context.ai.generateObject(await kL2(this.context,w,W),ti);$=ti.parse(J.object),PL2(W,$)}let Y=new Date().toISOString(),I=this.adapter.createSwotContent({strengths:Xr($.strengths),weaknesses:Xr($.weaknesses),opportunities:Xr($.opportunities),threats:Xr($.threats),derivedAt:Y});await B.report({progress:0.9,message:"Saving SWOT entity"});let X=await this.context.entityService.getEntity("swot","swot");if(X)await this.context.entityService.updateEntity({...X,content:I,metadata:{derivedAt:Y}});else await this.context.entityService.createEntity({id:"swot",entityType:"swot",content:I,metadata:{derivedAt:Y}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:w.summary.brainSkillCount,approvedAgentCount:w.summary.approvedAgentCount,discoveredAgentCount:w.summary.discoveredAgentCount}),{entityId:"swot"}}}var _L2=new iY;class B3A extends HQ{entityType="swot";schema=IE;adapter=_L2;initialSyncComplete=!1;constructor(){super("swot",Wz)}async onRegister(A){let Q=new Hr(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q);let B=async(D)=>{try{return await A.jobs.enqueue("derive",{reason:D},null,{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${D}`}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:D}),null}},w=async(D)=>{if(!await A.entityService.getEntity("swot","swot"))await B(D)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await w("initial-missing-entity"),{success:!0}});let $=async(D)=>{let{entityType:Y}=D.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await B("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),A.messaging.subscribe("entity:deleted",$)}}function w3A(){return new B3A}B0();GA();var vIB=new V9,SIB=new KJ,hIB=new iY,gIB=Z.object({skills:Z.array(HJ),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),status:Kz,discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(ni),notes:Z.string().default("")}))});var bL2=Z.object({}).strict();function Kr(A={}){return bL2.parse(A),[sJA(),tJA(),w3A()]}B0();GA();s8();GA();B0();var Ur=$S.extend({expertise:Z.array(Z.string()).optional().describe("Skills, domains, areas of focus"),currentFocus:Z.string().optional().describe("What you're currently working on"),availability:Z.string().optional().describe("What you're open to (consulting, speaking, etc.)")}),UJ=AY.extend(Ur.shape);B0();EW();GA();var xL2=new cI;class Wr{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,B){let w=B.entityService,[$,D,Y,I]=await Promise.all([qN(w),w.listEntities("post",{limit:20}),w.listEntities("deck",{limit:20}),rK(w)]),X=xL2.parseProfileBody($,UJ),H=D.sort(XO).slice(0,3).map(c_),W=Y.sort(XO).slice(0,3).map(i_);if(!I.cta)throw Error("CTA not configured in site-info");let J={profile:X,posts:H,decks:W,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:I.cta};return Q.parse(J)}}B0();EW();var TL2=new cI;class Gr{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,B){let w=await qN(B.entityService),D={profile:TL2.parseProfileBody(w,UJ)};return Q.parse(D)}}import{jsxDEV as c6,Fragment as qh0}from"preact/jsx-dev-runtime";var $3A=({profile:A,posts:Q,decks:B,postsListUrl:w,decksListUrl:$,cta:D})=>{let Y=A.tagline||A.description,I=Q.map((J)=>({id:J.id,url:J.url,title:J.metadata.title,date:J.metadata.publishedAt||J.created,description:J.frontmatter.excerpt,series:J.frontmatter.seriesName&&J.frontmatter.seriesIndex?{name:J.frontmatter.seriesName,index:J.frontmatter.seriesIndex}:void 0})),X=B.map((J)=>({id:J.id,url:J.url,title:J.frontmatter.title||J.id,date:J.frontmatter.publishedAt??J.created,description:J.frontmatter.description})),H=A.name||"Home",W=A.intro||A.description||Y||"Professional site";return c6(qh0,{children:[c6(o2,{title:H,description:W,ogType:"website"},void 0,!1,void 0,this),c6("div",{className:"homepage-list bg-theme",children:[c6("header",{className:"hero-bg-pattern relative w-full min-h-[70vh] flex items-end px-6 md:px-12 bg-theme overflow-hidden",children:c6("div",{className:"relative z-10 max-w-6xl mx-auto w-full pb-16 md:pb-24",children:[Y&&c6("h1",{className:"text-5xl md:text-6xl lg:text-7xl font-semibold text-heading leading-[1.08] tracking-tight",children:Y},void 0,!1,void 0,this),A.intro&&c6(qh0,{children:[c6("div",{className:"w-12 border-t border-theme mt-8 mb-6 md:mt-10 md:mb-8"},void 0,!1,void 0,this),c6("p",{className:"text-lg md:text-xl text-theme-muted leading-relaxed max-w-xl md:max-w-lg",children:A.intro},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),c6("div",{className:"section-divider"},void 0,!1,void 0,this),c6("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"Essays",items:I,viewAllUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),X.length>0&&c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"Presentations",items:X,viewAllUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),(A.description||A.expertise&&A.expertise.length>0)&&c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"About",viewAllUrl:"/about",variant:"stacked",children:c6("div",{className:"space-y-6",children:[A.description&&c6("p",{className:"text-lg text-theme leading-relaxed",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&c6(SG,{tags:A.expertise,variant:"accent",size:"sm"},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),c6(yHA,{cta:D,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 ZB,Fragment as vL2}from"preact/jsx-dev-runtime";var D3A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,B=A.description||A.intro||"About page",w=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return ZB(vL2,{children:[ZB(o2,{title:Q,description:B,ogType:"profile"},void 0,!1,void 0,this),ZB("div",{className:"about-page bg-theme",children:[ZB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:ZB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[ZB("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&&ZB("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),ZB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&ZB("section",{className:"content-section-reveal mb-20 md:mb-28",children:ZB(RY,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&ZB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),ZB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,D)=>ZB("li",{className:CP({variant:"accent",size:"lg"}),children:$},D,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),ZB("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&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),ZB("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)&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),ZB("div",{className:"space-y-4",children:[A.email&&ZB("p",{className:"text-lg",children:ZB("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&&ZB("p",{className:"text-lg",children:ZB("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&&ZB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,D)=>ZB(J5,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label||$.platform},D,!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 M9,Fragment as Nh0}from"preact/jsx-dev-runtime";var Y3A=()=>{return M9(Nh0,{children:[M9(o2,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),M9("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:M9("div",{className:"text-center max-w-md",children:[M9("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),M9("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),M9("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),M9(J5,{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)},I3A=()=>{return M9(Nh0,{children:[M9(o2,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),M9("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:M9("div",{className:"text-center max-w-md",children:[M9("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),M9("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),M9("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),M9(J5,{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)};GA();var Vh0=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),Lh0=Z.object({entityDisplay:Z.object({post:Vh0,deck:Vh0}).describe("Display metadata for post and deck entity types (required for homepage)")});var Mh0={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.37",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-builder-plugin":"workspace:*","@brains/site-composition":"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 X3A extends tB{dependencies=["blog","decks"];constructor(A){super("professional-site",Mh0,A,Lh0)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",Ur);let Q=this.config.entityDisplay.post,B=this.config.entityDisplay.deck,w=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${B.pluralName??B.label.toLowerCase()+"s"}`,D=new Wr(w,$);A.entities.registerDataSource(D);let Y=new Gr;A.entities.registerDataSource(Y);let I=Z.object({profile:UJ,posts:Z.array(tK),decks:Z.array(p_),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:k_}),X=Z.object({profile:UJ}),H=Z.object({});A.templates.register({"homepage-list":M1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:I,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:$3A}}),about:M1({name:"about",description:"About page with full profile information",schema:X,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:D3A}}),"subscribe-thanks":M1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:Y3A}}),"subscribe-error":M1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:I3A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Eh0(A){return new X3A(A??{})}var Ch0=[{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 HE}from"preact/jsx-dev-runtime";function Oh0({sections:A,siteInfo:Q,slots:B}){return HE("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[HE(lHA,{title:Q.title,navigation:Q.navigation.primary,...Q.logo!==void 0?{logo:Q.logo}:{}},void 0,!1,void 0,this),HE("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),HE("div",{className:"section-divider"},void 0,!1,void 0,this),HE(uHA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,children:HE(BGA,{name:"footer-top",slots:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var hL2={layouts:{default:Oh0},routes:Ch0,plugin:Eh0,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"}}}},Zb=hL2;var fh0=`/* Default font imports */
|
|
4139
|
+
${JSON.stringify(B,null,2)}`}function Xr(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function PL2(A,Q){let B=["strengths","weaknesses","opportunities","threats"];for(let w of B){let $=new Set(A[w].map((D)=>D.theme.trim().toLowerCase()));for(let D of Q[w]){let Y=D.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${D.sourceTheme}" in ${w}`)}}}class Hr{logger;context;adapter=new iY;constructor(A,Q){this.logger=A;this.context=Q}validateAndParse(A){let Q=cJA.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,B){await B.report({progress:0.2,message:"Building SWOT context"});let w=await eJA(this.context),$;if(w.summary.brainSkillCount+w.summary.approvedAgentCount+w.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await B.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:H}=await this.context.ai.generateObject(await RL2(this.context,w),lJA),W=lJA.parse(H);await B.report({progress:0.75,message:"Refining SWOT language"});let J=await this.context.ai.generateObject(await kL2(this.context,w,W),ti);$=ti.parse(J.object),PL2(W,$)}let Y=new Date().toISOString(),I=this.adapter.createSwotContent({strengths:Xr($.strengths),weaknesses:Xr($.weaknesses),opportunities:Xr($.opportunities),threats:Xr($.threats),derivedAt:Y});await B.report({progress:0.9,message:"Saving SWOT entity"});let X=await this.context.entityService.getEntity("swot","swot");if(X)await this.context.entityService.updateEntity({...X,content:I,metadata:{derivedAt:Y}});else await this.context.entityService.createEntity({id:"swot",entityType:"swot",content:I,metadata:{derivedAt:Y}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:w.summary.brainSkillCount,approvedAgentCount:w.summary.approvedAgentCount,discoveredAgentCount:w.summary.discoveredAgentCount}),{entityId:"swot"}}}var _L2=new iY;class B3A extends HQ{entityType="swot";schema=IE;adapter=_L2;initialSyncComplete=!1;constructor(){super("swot",Wz)}async onRegister(A){let Q=new Hr(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q);let B=async(D)=>{try{return await A.jobs.enqueue("derive",{reason:D},null,{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${D}`}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:D}),null}},w=async(D)=>{if(!await A.entityService.getEntity("swot","swot"))await B(D)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await w("initial-missing-entity"),{success:!0}});let $=async(D)=>{let{entityType:Y}=D.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await B("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),A.messaging.subscribe("entity:deleted",$)}}function w3A(){return new B3A}B0();GA();var vIB=new V9,SIB=new KJ,hIB=new iY,gIB=Z.object({skills:Z.array(HJ),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),status:Kz,discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(ni),notes:Z.string().default("")}))});var bL2=Z.object({}).strict();function Kr(A={}){return bL2.parse(A),[sJA(),tJA(),w3A()]}B0();GA();s8();GA();B0();var Ur=$S.extend({expertise:Z.array(Z.string()).optional().describe("Skills, domains, areas of focus"),currentFocus:Z.string().optional().describe("What you're currently working on"),availability:Z.string().optional().describe("What you're open to (consulting, speaking, etc.)")}),UJ=AY.extend(Ur.shape);B0();EW();GA();var xL2=new cI;class Wr{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,B){let w=B.entityService,[$,D,Y,I]=await Promise.all([qN(w),w.listEntities("post",{limit:20}),w.listEntities("deck",{limit:20}),rK(w)]),X=xL2.parseProfileBody($,UJ),H=D.sort(XO).slice(0,3).map(c_),W=Y.sort(XO).slice(0,3).map(i_);if(!I.cta)throw Error("CTA not configured in site-info");let J={profile:X,posts:H,decks:W,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:I.cta};return Q.parse(J)}}B0();EW();var TL2=new cI;class Gr{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,B){let w=await qN(B.entityService),D={profile:TL2.parseProfileBody(w,UJ)};return Q.parse(D)}}import{jsxDEV as c6,Fragment as qh0}from"preact/jsx-dev-runtime";var $3A=({profile:A,posts:Q,decks:B,postsListUrl:w,decksListUrl:$,cta:D})=>{let Y=A.tagline||A.description,I=Q.map((J)=>({id:J.id,url:J.url,title:J.metadata.title,date:J.metadata.publishedAt||J.created,description:J.frontmatter.excerpt,series:J.frontmatter.seriesName&&J.frontmatter.seriesIndex?{name:J.frontmatter.seriesName,index:J.frontmatter.seriesIndex}:void 0})),X=B.map((J)=>({id:J.id,url:J.url,title:J.frontmatter.title||J.id,date:J.frontmatter.publishedAt??J.created,description:J.frontmatter.description})),H=A.name||"Home",W=A.intro||A.description||Y||"Professional site";return c6(qh0,{children:[c6(o2,{title:H,description:W,ogType:"website"},void 0,!1,void 0,this),c6("div",{className:"homepage-list bg-theme",children:[c6("header",{className:"hero-bg-pattern relative w-full min-h-[70vh] flex items-end px-6 md:px-12 bg-theme overflow-hidden",children:c6("div",{className:"relative z-10 max-w-6xl mx-auto w-full pb-16 md:pb-24",children:[Y&&c6("h1",{className:"text-5xl md:text-6xl lg:text-7xl font-semibold text-heading leading-[1.08] tracking-tight",children:Y},void 0,!1,void 0,this),A.intro&&c6(qh0,{children:[c6("div",{className:"w-12 border-t border-theme mt-8 mb-6 md:mt-10 md:mb-8"},void 0,!1,void 0,this),c6("p",{className:"text-lg md:text-xl text-theme-muted leading-relaxed max-w-xl md:max-w-lg",children:A.intro},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),c6("div",{className:"section-divider"},void 0,!1,void 0,this),c6("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"Essays",items:I,viewAllUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),X.length>0&&c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"Presentations",items:X,viewAllUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),(A.description||A.expertise&&A.expertise.length>0)&&c6("div",{className:"content-section-reveal mb-20 md:mb-32",children:c6(xK,{title:"About",viewAllUrl:"/about",variant:"stacked",children:c6("div",{className:"space-y-6",children:[A.description&&c6("p",{className:"text-lg text-theme leading-relaxed",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&c6(SG,{tags:A.expertise,variant:"accent",size:"sm"},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),c6(yHA,{cta:D,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 ZB,Fragment as vL2}from"preact/jsx-dev-runtime";var D3A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,B=A.description||A.intro||"About page",w=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return ZB(vL2,{children:[ZB(o2,{title:Q,description:B,ogType:"profile"},void 0,!1,void 0,this),ZB("div",{className:"about-page bg-theme",children:[ZB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:ZB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[ZB("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&&ZB("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),ZB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&ZB("section",{className:"content-section-reveal mb-20 md:mb-28",children:ZB(RY,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&ZB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),ZB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,D)=>ZB("li",{className:CP({variant:"accent",size:"lg"}),children:$},D,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),ZB("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&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),ZB("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)&&ZB("section",{children:[ZB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),ZB("div",{className:"space-y-4",children:[A.email&&ZB("p",{className:"text-lg",children:ZB("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&&ZB("p",{className:"text-lg",children:ZB("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&&ZB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,D)=>ZB(J5,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label||$.platform},D,!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 M9,Fragment as Nh0}from"preact/jsx-dev-runtime";var Y3A=()=>{return M9(Nh0,{children:[M9(o2,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),M9("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:M9("div",{className:"text-center max-w-md",children:[M9("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),M9("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),M9("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),M9(J5,{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)},I3A=()=>{return M9(Nh0,{children:[M9(o2,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),M9("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:M9("div",{className:"text-center max-w-md",children:[M9("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),M9("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),M9("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),M9(J5,{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)};GA();var Vh0=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),Lh0=Z.object({entityDisplay:Z.object({post:Vh0,deck:Vh0}).describe("Display metadata for post and deck entity types (required for homepage)")});var Mh0={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.38",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-builder-plugin":"workspace:*","@brains/site-composition":"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 X3A extends tB{dependencies=["blog","decks"];constructor(A){super("professional-site",Mh0,A,Lh0)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",Ur);let Q=this.config.entityDisplay.post,B=this.config.entityDisplay.deck,w=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${B.pluralName??B.label.toLowerCase()+"s"}`,D=new Wr(w,$);A.entities.registerDataSource(D);let Y=new Gr;A.entities.registerDataSource(Y);let I=Z.object({profile:UJ,posts:Z.array(tK),decks:Z.array(p_),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:k_}),X=Z.object({profile:UJ}),H=Z.object({});A.templates.register({"homepage-list":M1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:I,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:$3A}}),about:M1({name:"about",description:"About page with full profile information",schema:X,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:D3A}}),"subscribe-thanks":M1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:H,requiredPermission:"public",layout:{component:Y3A}}),"subscribe-error":M1({name:"subscribe-error",description:"Newsletter subscription error page",schema:H,requiredPermission:"public",layout:{component:I3A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Eh0(A){return new X3A(A??{})}var Ch0=[{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 HE}from"preact/jsx-dev-runtime";function Oh0({sections:A,siteInfo:Q,slots:B}){return HE("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[HE(lHA,{title:Q.title,navigation:Q.navigation.primary,...Q.logo!==void 0?{logo:Q.logo}:{}},void 0,!1,void 0,this),HE("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),HE("div",{className:"section-divider"},void 0,!1,void 0,this),HE(uHA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,children:HE(BGA,{name:"footer-top",slots:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var hL2={layouts:{default:Oh0},routes:Ch0,plugin:Eh0,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"}}}},Zb=hL2;var fh0=`/* Default font imports */
|
|
4139
4140
|
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap');
|
|
4140
4141
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap');
|
|
4141
4142
|
|
|
@@ -4439,7 +4440,7 @@ ${JSON.stringify(B,null,2)}`}function Xr(A){return A.map((Q)=>Q.detail===null?{t
|
|
|
4439
4440
|
.btn-primary:hover { background-color: var(--color-brand-dark); }
|
|
4440
4441
|
.btn-primary:disabled { opacity: 0.5; }
|
|
4441
4442
|
}
|
|
4442
|
-
`;var Jr=fh0;import{join as mL2}from"path";var Rh0={name:"@brains/rover",version:"0.2.0-alpha.37",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"ensure:test-remote":"bun ./scripts/ensure-test-remote.ts","prestart:core":"bun run ensure:test-remote","start:core":"cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","prestart:default":"bun run ensure:test-remote","start:default":"cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","prestart:full":"bun run ensure:test-remote","start:full":"cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",typecheck:"tsc --noEmit",eval:"brain-eval",lint:"eslint .","lint:fix":"eslint . --fix"},dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/blog":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"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/topics":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^5.3.3"}};var jh0=["prompt","note","link","wishlist","topics","directory-sync","agents","admin","dashboard","mcp","webserver","discord","a2a"],kh0=[...jh0,"image","dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],uL2=[...kh0,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],Ph0=uW({name:"rover",version:Rh0.version,model:"gpt-5.4-mini",site:Zb,theme:Jr,presets:{core:jh0,default:kh0,full:uL2},evalDisable:["discord","webserver","mcp","analytics","dashboard"],capabilities:[["prompt",Hz,void 0],["image",Yj,void 0],["admin",IJ,{}],["dashboard",Xz,void 0],["blog",HGA,{}],["series",JGA,void 0],["decks",r_,void 0],["note",wz,{}],["link",Dz,{}],["portfolio",dGA,{}],["topics",Ri,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",FJA,{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",wb,{autoGenerateOnBlogPublish:!0}],["newsletter",kS0,{doubleOptIn:!0}],["obsidian-vault",bJA,{autoSync:!0}],["wishlist",di,{}],["stock-photo",mJA,{}],["agents",Kr,void 0],["directory-sync",LZ,{seedContent:!0,seedContentPath:mL2(import.meta.dir,"..","seed-content"),initialSync:!0}],["analytics",gi,{}],["site-info",nZ,void 0],["site-builder",Az,{cms:{}}]],interfaces:[["mcp",oW,()=>({})],["discord",PG,()=>({})],["webserver",_G,()=>({})],["a2a",tL,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"public"},{pattern:"discord:*",level:"public"}]},deployment:{cdn:{enabled:!0,provider:"bunny"},dns:{enabled:!0,provider:"bunny"}}});dW();B0();GA();GA();B0();var Fr=Z.object({routeId:Z.string(),sectionId:Z.string()}),zb=U2.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:Fr});B0();class _h0 extends E2{constructor(){super({entityType:"site-content",schema:zb,frontmatterSchema:Fr})}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 H3A=new _h0;GA();var Zr=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),BKB=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});class K3A{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("site-builder:routes:list",{});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,B){let w=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),D=$;if(A.routeId){if(D=$.filter((W)=>W.id===A.routeId),D.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let W of D)for(let J of W.sections){if(A.sectionId&&J.id!==A.sectionId)continue;if(J.content){w.debug("Section has static content, skipping",{routeId:W.id,sectionId:J.id});continue}if(J.template){let F=this.context.templates.getCapabilities(J.template);if(!F){w.warn("Template not found, skipping section",{routeId:W.id,sectionId:J.id,templateName:J.template});continue}if(!F.canGenerate){w.debug("Template doesn't support generation, skipping",{routeId:W.id,sectionId:J.id,templateName:J.template,capabilities:F});continue}}else{w.debug("Section has no template, skipping",{routeId:W.id,sectionId:J.id});continue}if(!A.force&&!A.dryRun){let F=`${W.id}:${J.id}`;if(await this.context.entityService.getEntity("site-content",F)){w.debug("Content already exists, skipping",{routeId:W.id,sectionId:J.id});continue}}Y.push({route:W,section:J})}let I=Y.length;if(A.dryRun)return{jobs:[],totalSections:I,queuedSections:I,batchId:`dry-run-${Date.now()}`};let X=[],H=[];for(let{route:W,section:J}of Y){let F=`${W.id}:${J.id}`,z=J.template,V={routeId:W.id,sectionId:J.id,entityId:F,entityType:"site-content",templateName:z,context:{prompt:typeof J.content==="string"?J.content:void 0,data:{routeId:W.id,sectionId:J.id,routeTitle:W.title||Q?.title||"",routeDescription:W.description||Q?.description||"",sectionContent:J.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:V})}if(H.length>0){let W=this.createJobOptions(B,"site:content-generation"),J=await this.context.jobs.enqueueBatch(H,W);for(let F=0;F<Y.length;F++){let z=Y[F];if(z)X.push({jobId:`${J}-${F}`,routeId:z.route.id,sectionId:z.section.id})}return{jobs:X,totalSections:I,queuedSections:X.length,batchId:J}}return{jobs:[],totalSections:I,queuedSections:0,batchId:`empty-${Date.now()}`}}}class U3A{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new K3A(A)}async generateContent(A,Q){let B=Zr.parse(A);return this.operations.generate(B,this.siteConfig,Q)}}GA();function qb(A,Q){return Q?A.optional():A}function G3A(A){switch(A.type){case"string":return qb(Z.string(),A.optional);case"number":return qb(Z.number(),A.optional);case"enum":{let Q=[...A.options];return qb(Z.enum(Q),A.optional)}case"object":{let Q={};for(let[B,w]of Object.entries(A.fields))Q[B]=G3A(w);return qb(Z.object(Q),A.optional)}case"array":{let Q=Z.array(cL2(A));if(A.minItems!==void 0)Q=Q.min(A.minItems);if(A.length!==void 0)Q=Q.length(A.length);return qb(Q,A.optional)}}}function cL2(A){let{items:Q}=A;switch(Q.type){case"string":return Z.string();case"number":return Z.number();case"enum":{let B=[...Q.options];return Z.enum(B)}case"object":{let B={};for(let[w,$]of Object.entries(Q.fields))B[w]=G3A($);return Z.object(B)}}}function W3A(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(([B,w])=>W3A(B,w))};case"array":{let B={key:A,label:Q.label,type:"array"};switch(Q.items.type){case"string":case"enum":return B.itemType="string",B;case"number":return B.itemType="number",B;case"object":return B.itemType="object",B.itemMappings=Object.entries(Q.items.fields).map(([w,$])=>W3A(w,$)),B}}}}function lL2(A,Q){let B={};for(let[D,Y]of Object.entries(Q.fields))B[D]=G3A(Y);let w=Z.object(B),$=new dB(w,{title:Q.title,mappings:Object.entries(Q.fields).map(([D,Y])=>W3A(D,Y))});return{name:A,description:Q.description,schema:w,formatter:$,requiredPermission:Q.requiredPermission??"public",layout:{component:Q.layout,...Q.fullscreen!==void 0?{fullscreen:Q.fullscreen}:{}},...Q.runtimeScripts?{runtimeScripts:Q.runtimeScripts}:{}}}function J3A(A){return Object.fromEntries(Object.entries(A.sections).map(([Q,B])=>[Q,lL2(Q,B)]))}GA();var bh0=Z.object({namespace:Z.string(),sections:Z.record(Z.any())}),xh0=Z.object({definitions:Z.union([bh0,Z.array(bh0)]).optional()});B0();function Th0(A,Q){return[yQ(Q,"generate","Generate content for all routes, a specific route, or a specific section",Zr,async(B,w)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(B.sectionId&&!B.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let D={rootJobId:`generate-${Date.now()}`,progressToken:w.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:w.interfaceType,channelId:w.channelId},Y=await $.generateContent(B,D);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var vh0={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.37",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/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 F3A extends tB{siteContentService;constructor(A={}){super("site-content",vh0,A,xh0)}async onRegister(A){A.entities.register("site-content",zb,H3A);for(let Q of SH(this.config.definitions))A.templates.register(J3A(Q),Q.namespace);this.siteContentService=new U3A(A)}async getTools(){return Th0(()=>this.siteContentService,this.id)}}function Nb(A={}){return new F3A(A)}B0();GA();s8();GA();B0();var Sh0=Z.enum(["available","early access","coming soon","planned"]),hh0=Z.object({title:Z.string(),description:Z.string()}),$U=Z.object({name:Z.string(),availability:Sh0,order:Z.number()}),zr=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(hh0).min(1).max(6),story:Z.string()}),dL2=$U.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),KE=U2.extend({entityType:Z.literal("product"),metadata:dL2}),qr=KE.extend({frontmatter:$U,body:zr,labels:Z.record(Z.string(),Z.string())}),Nr=qr.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional()});B0();GA();GA();class UE extends dB{constructor(){super(zr,{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 Z3A extends E2{constructor(){super({entityType:"product",schema:KE,frontmatterSchema:$U,bodyFormatter:new UE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,$U);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,$U),B=e1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:B,availability:Q.availability,order:Q.order}}}}var Vr=new Z3A;GA();B0();var gh0=Z.object({title:Z.string(),description:Z.string()}),yh0=Z.object({title:Z.string(),description:Z.string()}),iL2=Z.object({title:Z.string(),description:Z.string()}),mh0=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),DU=Z.object({headline:Z.string(),tagline:Z.string()}),rL2=Z.object({title:Z.string(),description:Z.string()}),Lr=Z.object({vision:Z.string(),pillars:Z.array(gh0).min(1).max(6),approach:Z.array(rL2).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(iL2).min(1).max(6),benefits:Z.array(yh0).min(1).max(6),cta:mh0}),uh0=DU.pick({headline:!0}).extend({slug:Z.string()}),WE=U2.extend({entityType:Z.literal("products-overview"),metadata:uh0}),Vb=WE.extend({frontmatter:DU,body:Lr,labels:Z.record(Z.string(),Z.string())});B0();GA();GA();class GE extends dB{constructor(){super(Lr,{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 z3A extends E2{constructor(){super({entityType:"products-overview",schema:WE,frontmatterSchema:DU,bodyFormatter:new GE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,DU);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,DU),B=e1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:B}}}}var q3A=new z3A;B0();GA();var nL2=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function ch0(A,Q){let B=F2(A.content,$U),w=Q.parse(B.content),$=Q.getLabels();return qr.parse({...A,frontmatter:B.metadata,body:w,labels:$})}function lh0(A,Q){let B=F2(A.content,DU),w=Q.parse(B.content),$=Q.getLabels();return Vb.parse({...A,frontmatter:B.metadata,body:w,labels:$})}class Mr{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new GE;productFormatter=new UE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,B){let w=nL2.parse(A),$=B.entityService;if(w.entityType==="products-overview"){let H=(await $.listEntities("products-overview",{limit:1}))[0];if(!H)throw Error("Products overview entity not found");let W=lh0(H,this.overviewFormatter);return Q.parse(W)}if(w.query?.id){let H=(await $.listEntities("product",{filter:{metadata:{slug:w.query.id}},limit:1}))[0];if(!H)throw Error(`Product not found: ${w.query.id}`);return Q.parse({product:ch0(H,this.productFormatter)})}let[D,Y]=await Promise.all([$.listEntities("products-overview",{limit:1}),$.listEntities("product",{sortFields:[{field:"order",direction:"asc"}]})]),I=D[0];if(!I)throw Error("Products overview entity not found");return Q.parse({overview:lh0(I,this.overviewFormatter),products:Y.map((X)=>ch0(X,this.productFormatter))})}}import{jsxDEV as l0,Fragment as aL2}from"preact/jsx-dev-runtime";var ph0=({overview:A,products:Q})=>{let{frontmatter:B,body:w,labels:$}=A;return l0(aL2,{children:[l0(o2,{title:B.headline,description:B.tagline},void 0,!1,void 0,this),l0("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[l0("style",{children:`
|
|
4443
|
+
`;var Jr=fh0;import{join as mL2}from"path";var Rh0={name:"@brains/rover",version:"0.2.0-alpha.38",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"ensure:test-remote":"bun ./scripts/ensure-test-remote.ts","prestart:core":"bun run ensure:test-remote","start:core":"cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","prestart:default":"bun run ensure:test-remote","start:default":"cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","prestart:full":"bun run ensure:test-remote","start:full":"cd test-apps/full && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start",typecheck:"tsc --noEmit",eval:"brain-eval",lint:"eslint .","lint:fix":"eslint . --fix"},dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/blog":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/portfolio":"workspace:*","@brains/prompt":"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/topics":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^5.3.3"}};var jh0=["prompt","note","link","wishlist","topics","directory-sync","agents","admin","dashboard","mcp","webserver","discord","a2a"],kh0=[...jh0,"image","dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],uL2=[...kh0,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],Ph0=uW({name:"rover",version:Rh0.version,model:"gpt-5.4-mini",site:Zb,theme:Jr,presets:{core:jh0,default:kh0,full:uL2},evalDisable:["discord","webserver","mcp","analytics","dashboard"],capabilities:[["prompt",Hz,void 0],["image",Yj,void 0],["admin",IJ,{}],["dashboard",Xz,void 0],["blog",HGA,{}],["series",JGA,void 0],["decks",r_,void 0],["note",wz,{}],["link",Dz,{}],["portfolio",dGA,{}],["topics",Ri,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",FJA,{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",wb,{autoGenerateOnBlogPublish:!0}],["newsletter",kS0,{doubleOptIn:!0}],["obsidian-vault",bJA,{autoSync:!0}],["wishlist",di,{}],["stock-photo",mJA,{}],["agents",Kr,void 0],["directory-sync",LZ,{seedContent:!0,seedContentPath:mL2(import.meta.dir,"..","seed-content"),initialSync:!0}],["analytics",gi,{}],["site-info",nZ,void 0],["site-builder",Az,{cms:{}}]],interfaces:[["mcp",oW,()=>({})],["discord",PG,()=>({})],["webserver",_G,()=>({})],["a2a",tL,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"public"},{pattern:"discord:*",level:"public"}]},deployment:{cdn:{enabled:!0,provider:"bunny"},dns:{enabled:!0,provider:"bunny"}}});dW();B0();GA();GA();B0();var Fr=Z.object({routeId:Z.string(),sectionId:Z.string()}),zb=U2.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:Fr});B0();class _h0 extends E2{constructor(){super({entityType:"site-content",schema:zb,frontmatterSchema:Fr})}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 H3A=new _h0;GA();var Zr=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),BKB=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});class K3A{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("site-builder:routes:list",{});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,B){let w=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),D=$;if(A.routeId){if(D=$.filter((W)=>W.id===A.routeId),D.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let W of D)for(let J of W.sections){if(A.sectionId&&J.id!==A.sectionId)continue;if(J.content){w.debug("Section has static content, skipping",{routeId:W.id,sectionId:J.id});continue}if(J.template){let F=this.context.templates.getCapabilities(J.template);if(!F){w.warn("Template not found, skipping section",{routeId:W.id,sectionId:J.id,templateName:J.template});continue}if(!F.canGenerate){w.debug("Template doesn't support generation, skipping",{routeId:W.id,sectionId:J.id,templateName:J.template,capabilities:F});continue}}else{w.debug("Section has no template, skipping",{routeId:W.id,sectionId:J.id});continue}if(!A.force&&!A.dryRun){let F=`${W.id}:${J.id}`;if(await this.context.entityService.getEntity("site-content",F)){w.debug("Content already exists, skipping",{routeId:W.id,sectionId:J.id});continue}}Y.push({route:W,section:J})}let I=Y.length;if(A.dryRun)return{jobs:[],totalSections:I,queuedSections:I,batchId:`dry-run-${Date.now()}`};let X=[],H=[];for(let{route:W,section:J}of Y){let F=`${W.id}:${J.id}`,z=J.template,V={routeId:W.id,sectionId:J.id,entityId:F,entityType:"site-content",templateName:z,context:{prompt:typeof J.content==="string"?J.content:void 0,data:{routeId:W.id,sectionId:J.id,routeTitle:W.title||Q?.title||"",routeDescription:W.description||Q?.description||"",sectionContent:J.content},conversationId:"system"},siteConfig:Q};H.push({type:"shell:content-generation",data:V})}if(H.length>0){let W=this.createJobOptions(B,"site:content-generation"),J=await this.context.jobs.enqueueBatch(H,W);for(let F=0;F<Y.length;F++){let z=Y[F];if(z)X.push({jobId:`${J}-${F}`,routeId:z.route.id,sectionId:z.section.id})}return{jobs:X,totalSections:I,queuedSections:X.length,batchId:J}}return{jobs:[],totalSections:I,queuedSections:0,batchId:`empty-${Date.now()}`}}}class U3A{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new K3A(A)}async generateContent(A,Q){let B=Zr.parse(A);return this.operations.generate(B,this.siteConfig,Q)}}GA();function qb(A,Q){return Q?A.optional():A}function G3A(A){switch(A.type){case"string":return qb(Z.string(),A.optional);case"number":return qb(Z.number(),A.optional);case"enum":{let Q=[...A.options];return qb(Z.enum(Q),A.optional)}case"object":{let Q={};for(let[B,w]of Object.entries(A.fields))Q[B]=G3A(w);return qb(Z.object(Q),A.optional)}case"array":{let Q=Z.array(cL2(A));if(A.minItems!==void 0)Q=Q.min(A.minItems);if(A.length!==void 0)Q=Q.length(A.length);return qb(Q,A.optional)}}}function cL2(A){let{items:Q}=A;switch(Q.type){case"string":return Z.string();case"number":return Z.number();case"enum":{let B=[...Q.options];return Z.enum(B)}case"object":{let B={};for(let[w,$]of Object.entries(Q.fields))B[w]=G3A($);return Z.object(B)}}}function W3A(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(([B,w])=>W3A(B,w))};case"array":{let B={key:A,label:Q.label,type:"array"};switch(Q.items.type){case"string":case"enum":return B.itemType="string",B;case"number":return B.itemType="number",B;case"object":return B.itemType="object",B.itemMappings=Object.entries(Q.items.fields).map(([w,$])=>W3A(w,$)),B}}}}function lL2(A,Q){let B={};for(let[D,Y]of Object.entries(Q.fields))B[D]=G3A(Y);let w=Z.object(B),$=new dB(w,{title:Q.title,mappings:Object.entries(Q.fields).map(([D,Y])=>W3A(D,Y))});return{name:A,description:Q.description,schema:w,formatter:$,requiredPermission:Q.requiredPermission??"public",layout:{component:Q.layout,...Q.fullscreen!==void 0?{fullscreen:Q.fullscreen}:{}},...Q.runtimeScripts?{runtimeScripts:Q.runtimeScripts}:{}}}function J3A(A){return Object.fromEntries(Object.entries(A.sections).map(([Q,B])=>[Q,lL2(Q,B)]))}GA();var bh0=Z.object({namespace:Z.string(),sections:Z.record(Z.any())}),xh0=Z.object({definitions:Z.union([bh0,Z.array(bh0)]).optional()});B0();function Th0(A,Q){return[yQ(Q,"generate","Generate content for all routes, a specific route, or a specific section",Zr,async(B,w)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(B.sectionId&&!B.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let D={rootJobId:`generate-${Date.now()}`,progressToken:w.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:w.interfaceType,channelId:w.channelId},Y=await $.generateContent(B,D);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var vh0={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.38",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/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 F3A extends tB{siteContentService;constructor(A={}){super("site-content",vh0,A,xh0)}async onRegister(A){A.entities.register("site-content",zb,H3A);for(let Q of SH(this.config.definitions))A.templates.register(J3A(Q),Q.namespace);this.siteContentService=new U3A(A)}async getTools(){return Th0(()=>this.siteContentService,this.id)}}function Nb(A={}){return new F3A(A)}B0();GA();s8();GA();B0();var Sh0=Z.enum(["available","early access","coming soon","planned"]),hh0=Z.object({title:Z.string(),description:Z.string()}),$U=Z.object({name:Z.string(),availability:Sh0,order:Z.number()}),zr=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(hh0).min(1).max(6),story:Z.string()}),dL2=$U.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),KE=U2.extend({entityType:Z.literal("product"),metadata:dL2}),qr=KE.extend({frontmatter:$U,body:zr,labels:Z.record(Z.string(),Z.string())}),Nr=qr.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional()});B0();GA();GA();class UE extends dB{constructor(){super(zr,{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 Z3A extends E2{constructor(){super({entityType:"product",schema:KE,frontmatterSchema:$U,bodyFormatter:new UE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,$U);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,$U),B=e1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:B,availability:Q.availability,order:Q.order}}}}var Vr=new Z3A;GA();B0();var gh0=Z.object({title:Z.string(),description:Z.string()}),yh0=Z.object({title:Z.string(),description:Z.string()}),iL2=Z.object({title:Z.string(),description:Z.string()}),mh0=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),DU=Z.object({headline:Z.string(),tagline:Z.string()}),rL2=Z.object({title:Z.string(),description:Z.string()}),Lr=Z.object({vision:Z.string(),pillars:Z.array(gh0).min(1).max(6),approach:Z.array(rL2).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(iL2).min(1).max(6),benefits:Z.array(yh0).min(1).max(6),cta:mh0}),uh0=DU.pick({headline:!0}).extend({slug:Z.string()}),WE=U2.extend({entityType:Z.literal("products-overview"),metadata:uh0}),Vb=WE.extend({frontmatter:DU,body:Lr,labels:Z.record(Z.string(),Z.string())});B0();GA();GA();class GE extends dB{constructor(){super(Lr,{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 z3A extends E2{constructor(){super({entityType:"products-overview",schema:WE,frontmatterSchema:DU,bodyFormatter:new GE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,DU);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,DU),B=e1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:B}}}}var q3A=new z3A;B0();GA();var nL2=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function ch0(A,Q){let B=F2(A.content,$U),w=Q.parse(B.content),$=Q.getLabels();return qr.parse({...A,frontmatter:B.metadata,body:w,labels:$})}function lh0(A,Q){let B=F2(A.content,DU),w=Q.parse(B.content),$=Q.getLabels();return Vb.parse({...A,frontmatter:B.metadata,body:w,labels:$})}class Mr{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new GE;productFormatter=new UE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,B){let w=nL2.parse(A),$=B.entityService;if(w.entityType==="products-overview"){let H=(await $.listEntities("products-overview",{limit:1}))[0];if(!H)throw Error("Products overview entity not found");let W=lh0(H,this.overviewFormatter);return Q.parse(W)}if(w.query?.id){let H=(await $.listEntities("product",{filter:{metadata:{slug:w.query.id}},limit:1}))[0];if(!H)throw Error(`Product not found: ${w.query.id}`);return Q.parse({product:ch0(H,this.productFormatter)})}let[D,Y]=await Promise.all([$.listEntities("products-overview",{limit:1}),$.listEntities("product",{sortFields:[{field:"order",direction:"asc"}]})]),I=D[0];if(!I)throw Error("Products overview entity not found");return Q.parse({overview:lh0(I,this.overviewFormatter),products:Y.map((X)=>ch0(X,this.productFormatter))})}}import{jsxDEV as l0,Fragment as aL2}from"preact/jsx-dev-runtime";var ph0=({overview:A,products:Q})=>{let{frontmatter:B,body:w,labels:$}=A;return l0(aL2,{children:[l0(o2,{title:B.headline,description:B.tagline},void 0,!1,void 0,this),l0("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[l0("style",{children:`
|
|
4443
4444
|
@keyframes wave-drift {
|
|
4444
4445
|
from { transform: translateX(0); }
|
|
4445
4446
|
to { transform: translateX(-50%); }
|
|
@@ -4467,7 +4468,7 @@ ${JSON.stringify(B,null,2)}`}function Xr(A){return A.map((Q)=>Q.detail===null?{t
|
|
|
4467
4468
|
@media (prefers-reduced-motion: reduce) {
|
|
4468
4469
|
.detail-wave { animation: none; }
|
|
4469
4470
|
}
|
|
4470
|
-
`},void 0,!1,void 0,this),b1("div",{className:"absolute inset-0 overflow-hidden pointer-events-none",children:b1("svg",{preserveAspectRatio:"none",width:"200%",height:"100%",viewBox:"0 0 1600 400",className:"block absolute inset-0 detail-wave",children:[b1("path",{d:"M0,200 C67,140 133,140 200,200 C267,260 333,260 400,200 C467,140 533,140 600,200 C667,260 733,260 800,200 C867,140 933,140 1000,200 C1067,260 1133,260 1200,200 C1267,140 1333,140 1400,200 C1467,260 1533,260 1600,200",className:"stroke-accent",strokeWidth:"2",strokeMiterlimit:"10",fill:"none",opacity:"0.15"},void 0,!1,void 0,this),b1("path",{d:"M0,230 C67,170 133,170 200,230 C267,290 333,290 400,230 C467,170 533,170 600,230 C667,290 733,290 800,230 C867,170 933,170 1000,230 C1067,290 1133,290 1200,230 C1267,170 1333,170 1400,230 C1467,290 1533,290 1600,230",className:"stroke-accent",strokeWidth:"1.5",strokeMiterlimit:"10",fill:"none",opacity:"0.06"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("div",{className:"absolute inset-0 cta-bg-pattern pointer-events-none"},void 0,!1,void 0,this),b1("div",{className:"relative z-10 max-w-5xl mx-auto w-full px-6 md:px-12 pt-12 md:pt-20 pb-16 md:pb-24",children:[b1("nav",{"aria-label":"Breadcrumb",className:"text-sm text-white/50 mb-8 hero-stagger-1",children:b1("ol",{className:"flex flex-wrap items-center gap-1",children:[b1("li",{className:"flex items-center gap-1",children:b1("a",{href:"/",className:"hover:text-white transition-colors",children:"Home"},void 0,!1,void 0,this)},void 0,!1,void 0,this),b1("li",{className:"flex items-center gap-1",children:[b1("span",{className:"mx-1","aria-hidden":"true",children:"/"},void 0,!1,void 0,this),b1("a",{href:$,className:"hover:text-white transition-colors",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("li",{className:"flex items-center gap-1",children:[b1("span",{className:"mx-1","aria-hidden":"true",children:"/"},void 0,!1,void 0,this),b1("span",{className:"text-white font-medium",children:Q.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("div",{className:"mb-6 hero-stagger-1",children:b1(n7,{status:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this),b1("h1",{className:"text-5xl md:text-6xl lg:text-[7rem] font-bold text-white tracking-tighter leading-[0.95] mb-6 md:mb-8 hero-stagger-1",children:Q.name},void 0,!1,void 0,this),b1("div",{className:"w-20 h-1.5 bg-accent mb-6 md:mb-8 hero-stagger-2"},void 0,!1,void 0,this),b1("p",{className:"text-lg md:text-xl text-white/70 leading-relaxed max-w-xl hero-stagger-3",children:B.tagline},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("section",{className:"bg-theme-subtle py-20 md:py-28 px-6 md:px-12",children:b1("div",{className:"max-w-4xl mx-auto space-y-16",children:[b1("div",{children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:w.promise},void 0,!1,void 0,this),b1("p",{className:"text-2xl md:text-3xl lg:text-4xl leading-relaxed text-heading font-light",children:B.promise},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-12 md:gap-16",children:[b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.role},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.role},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.purpose},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.purpose},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.audience},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.audience},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex flex-col md:flex-row md:items-center gap-6 md:gap-12",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted whitespace-nowrap",children:w.values},void 0,!1,void 0,this),b1(SG,{tags:B.values,variant:"accent",size:"md"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"cta-bg-pattern bg-brand py-20 md:py-32 px-6 md:px-12",children:b1("div",{className:"container mx-auto max-w-5xl",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-white/50 mb-16",children:w.features},void 0,!1,void 0,this),b1("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-12 md:gap-16",children:B.features.map((I,X)=>b1("div",{children:b1("div",{className:"flex items-start gap-6",children:[b1("span",{className:"text-5xl md:text-6xl font-black text-white/10 leading-none shrink-0",children:String(X+1).padStart(2,"0")},void 0,!1,void 0,this),b1("div",{className:"pt-2",children:[b1("div",{className:"w-8 h-1 bg-accent mb-4"},void 0,!1,void 0,this),b1("h3",{className:"text-xl font-bold text-white mb-3",children:I.title},void 0,!1,void 0,this),b1("p",{className:"text-white/70 leading-relaxed",children:I.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},I.title,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"py-20 md:py-32 px-6 md:px-12",children:b1("div",{className:"max-w-3xl mx-auto",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-12",children:w.story},void 0,!1,void 0,this),b1("div",{className:"space-y-6",children:Y.map((I,X)=>b1("p",{className:X===0?"text-2xl md:text-3xl leading-relaxed text-heading font-light":"text-lg leading-relaxed text-theme-muted",children:I},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"cta-bg-pattern bg-brand-dark pt-24 md:pt-32 pb-40 md:pb-48 -mb-[60px] px-6 md:px-12",children:b1("div",{className:"max-w-4xl mx-auto",children:[b1("p",{className:"text-sm tracking-widest uppercase text-white/60 mb-4",children:Q.name},void 0,!1,void 0,this),b1("h2",{className:"text-3xl md:text-5xl font-bold text-white max-w-2xl mb-4",children:B.tagline},void 0,!1,void 0,this),b1("p",{className:"text-lg text-white/60 mb-10 max-w-xl",children:B.promise},void 0,!1,void 0,this),b1(J5,{href:$,variant:"outline-light",size:"lg",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();var N3A=Z.object({route:Z.string().default("/products")});var ih0={name:"@brains/products",private:!0,version:"0.2.0-alpha.
|
|
4471
|
+
`},void 0,!1,void 0,this),b1("div",{className:"absolute inset-0 overflow-hidden pointer-events-none",children:b1("svg",{preserveAspectRatio:"none",width:"200%",height:"100%",viewBox:"0 0 1600 400",className:"block absolute inset-0 detail-wave",children:[b1("path",{d:"M0,200 C67,140 133,140 200,200 C267,260 333,260 400,200 C467,140 533,140 600,200 C667,260 733,260 800,200 C867,140 933,140 1000,200 C1067,260 1133,260 1200,200 C1267,140 1333,140 1400,200 C1467,260 1533,260 1600,200",className:"stroke-accent",strokeWidth:"2",strokeMiterlimit:"10",fill:"none",opacity:"0.15"},void 0,!1,void 0,this),b1("path",{d:"M0,230 C67,170 133,170 200,230 C267,290 333,290 400,230 C467,170 533,170 600,230 C667,290 733,290 800,230 C867,170 933,170 1000,230 C1067,290 1133,290 1200,230 C1267,170 1333,170 1400,230 C1467,290 1533,290 1600,230",className:"stroke-accent",strokeWidth:"1.5",strokeMiterlimit:"10",fill:"none",opacity:"0.06"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("div",{className:"absolute inset-0 cta-bg-pattern pointer-events-none"},void 0,!1,void 0,this),b1("div",{className:"relative z-10 max-w-5xl mx-auto w-full px-6 md:px-12 pt-12 md:pt-20 pb-16 md:pb-24",children:[b1("nav",{"aria-label":"Breadcrumb",className:"text-sm text-white/50 mb-8 hero-stagger-1",children:b1("ol",{className:"flex flex-wrap items-center gap-1",children:[b1("li",{className:"flex items-center gap-1",children:b1("a",{href:"/",className:"hover:text-white transition-colors",children:"Home"},void 0,!1,void 0,this)},void 0,!1,void 0,this),b1("li",{className:"flex items-center gap-1",children:[b1("span",{className:"mx-1","aria-hidden":"true",children:"/"},void 0,!1,void 0,this),b1("a",{href:$,className:"hover:text-white transition-colors",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("li",{className:"flex items-center gap-1",children:[b1("span",{className:"mx-1","aria-hidden":"true",children:"/"},void 0,!1,void 0,this),b1("span",{className:"text-white font-medium",children:Q.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("div",{className:"mb-6 hero-stagger-1",children:b1(n7,{status:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this),b1("h1",{className:"text-5xl md:text-6xl lg:text-[7rem] font-bold text-white tracking-tighter leading-[0.95] mb-6 md:mb-8 hero-stagger-1",children:Q.name},void 0,!1,void 0,this),b1("div",{className:"w-20 h-1.5 bg-accent mb-6 md:mb-8 hero-stagger-2"},void 0,!1,void 0,this),b1("p",{className:"text-lg md:text-xl text-white/70 leading-relaxed max-w-xl hero-stagger-3",children:B.tagline},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("section",{className:"bg-theme-subtle py-20 md:py-28 px-6 md:px-12",children:b1("div",{className:"max-w-4xl mx-auto space-y-16",children:[b1("div",{children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:w.promise},void 0,!1,void 0,this),b1("p",{className:"text-2xl md:text-3xl lg:text-4xl leading-relaxed text-heading font-light",children:B.promise},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-12 md:gap-16",children:[b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.role},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.role},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.purpose},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.purpose},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{children:[b1("div",{className:"w-8 h-1 bg-accent mb-6"},void 0,!1,void 0,this),b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-4",children:w.audience},void 0,!1,void 0,this),b1("p",{className:"text-lg leading-relaxed text-theme-muted",children:B.audience},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex flex-col md:flex-row md:items-center gap-6 md:gap-12",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted whitespace-nowrap",children:w.values},void 0,!1,void 0,this),b1(SG,{tags:B.values,variant:"accent",size:"md"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"cta-bg-pattern bg-brand py-20 md:py-32 px-6 md:px-12",children:b1("div",{className:"container mx-auto max-w-5xl",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-white/50 mb-16",children:w.features},void 0,!1,void 0,this),b1("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-12 md:gap-16",children:B.features.map((I,X)=>b1("div",{children:b1("div",{className:"flex items-start gap-6",children:[b1("span",{className:"text-5xl md:text-6xl font-black text-white/10 leading-none shrink-0",children:String(X+1).padStart(2,"0")},void 0,!1,void 0,this),b1("div",{className:"pt-2",children:[b1("div",{className:"w-8 h-1 bg-accent mb-4"},void 0,!1,void 0,this),b1("h3",{className:"text-xl font-bold text-white mb-3",children:I.title},void 0,!1,void 0,this),b1("p",{className:"text-white/70 leading-relaxed",children:I.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},I.title,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"py-20 md:py-32 px-6 md:px-12",children:b1("div",{className:"max-w-3xl mx-auto",children:[b1("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-12",children:w.story},void 0,!1,void 0,this),b1("div",{className:"space-y-6",children:Y.map((I,X)=>b1("p",{className:X===0?"text-2xl md:text-3xl leading-relaxed text-heading font-light":"text-lg leading-relaxed text-theme-muted",children:I},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),b1("section",{className:"cta-bg-pattern bg-brand-dark pt-24 md:pt-32 pb-40 md:pb-48 -mb-[60px] px-6 md:px-12",children:b1("div",{className:"max-w-4xl mx-auto",children:[b1("p",{className:"text-sm tracking-widest uppercase text-white/60 mb-4",children:Q.name},void 0,!1,void 0,this),b1("h2",{className:"text-3xl md:text-5xl font-bold text-white max-w-2xl mb-4",children:B.tagline},void 0,!1,void 0,this),b1("p",{className:"text-lg text-white/60 mb-10 max-w-xl",children:B.promise},void 0,!1,void 0,this),b1(J5,{href:$,variant:"outline-light",size:"lg",children:D},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};GA();var N3A=Z.object({route:Z.string().default("/products")});var ih0={name:"@brains/products",private:!0,version:"0.2.0-alpha.38",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/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 AM2=Z.object({overview:Vb,products:Z.array(Nr)}),QM2=Z.object({product:Nr});class V3A extends HQ{entityType=Vr.entityType;schema=KE;adapter=Vr;constructor(A={}){super("products",ih0,A,N3A)}getTemplates(){return{"product-list":M1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:AM2,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ph0}}),"product-detail":M1({name:"product-detail",description:"Individual product detail page",schema:QM2,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:dh0}})}}getDataSources(){return[new Mr(this.logger.child("ProductsDataSource"))]}async onRegister(A){A.entities.register("products-overview",WE,q3A)}}function L3A(A={}){return new V3A(A)}import{join as LM2}from"path";import{jsxDEV as Er,Fragment as BM2}from"preact/jsx-dev-runtime";var Cr=({children:A})=>Er(BM2,{children:[Er("div",{id:"bgCanvasWrap",className:"rizom-frame-canvas-wrap fixed top-0 left-0 w-full h-full pointer-events-none",children:Er("canvas",{id:"heroCanvas",className:"w-full h-full block"},void 0,!1,void 0,this)},void 0,!1,void 0,this),Er("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 uUB}from"preact/jsx-dev-runtime";import{jsxDEV as iUB}from"preact/jsx-dev-runtime";var Or="px-6 md:px-10 xl:px-20",pUB=`${Or} relative z-[1]`;import{jsxDEV as aUB}from"preact/jsx-dev-runtime";import{jsxDEV as AWB}from"preact/jsx-dev-runtime";import{jsxDEV as $WB}from"preact/jsx-dev-runtime";import{jsxDEV as XWB}from"preact/jsx-dev-runtime";import{jsxDEV as WWB}from"preact/jsx-dev-runtime";import{Fragment as FWB}from"preact";import{jsxDEV as zWB}from"preact/jsx-dev-runtime";import{jsxDEV as VWB}from"preact/jsx-dev-runtime";import{jsxDEV as RWB}from"preact/jsx-dev-runtime";var wM2="pointer-events-none absolute h-[14px] w-[14px] opacity-85 before:content-[''] before:absolute before:left-0 before:top-0 before:h-[1.5px] before:w-full before:bg-current after:content-[''] after:absolute after:left-0 after:top-0 after:h-full after:w-[1.5px] after:bg-current",OWB=`${wM2} z-[2]`;import{jsxDEV as nh0}from"preact/jsx-dev-runtime";var fr=({sections:A})=>nh0(Cr,{children:nh0("main",{children:A},void 0,!1,void 0,this)},void 0,!1,void 0,this);B0();GA();var oh0=`/*
|
|
4471
4472
|
* Shared globals + helpers used by tree / constellation / roots canvas
|
|
4472
4473
|
* scripts. Loaded as a shared static asset by the Rizom runtime package
|
|
4473
4474
|
* so the variant canvases
|
|
@@ -6900,7 +6901,7 @@ Your task is to:
|
|
|
6900
6901
|
2. Generate a clear, natural summary that captures key points, decisions, and action items
|
|
6901
6902
|
3. Return structured data in the required JSON format
|
|
6902
6903
|
|
|
6903
|
-
Be concise but comprehensive, focusing on the most important information.`});B0();GA();var RM2=Z.object({entityType:Z.literal("summary"),query:Z.object({id:Z.string().optional(),conversationId:Z.string().optional(),limit:Z.number().optional()}).optional()});class R3A{logger;id="summary:entities";name="Summary Entity DataSource";description="Fetches and transforms summary entities for rendering";adapter;constructor(A){this.logger=A;this.adapter=new uX,this.logger.debug("SummaryDataSource initialized")}async fetch(A,Q,B){let w=RM2.parse(A),$=B.entityService,D=w.query?.conversationId??w.query?.id;if(D){let H=await $.getEntity(w.query?.conversationId?"summary":w.entityType,D);if(!H)throw Error(`Summary not found: ${D}`);let W;try{let F=F2(H.content,Z.record(Z.string(),Z.unknown()));W=this.adapter.parseEntriesFromContent(F.content)}catch{W=this.adapter.parseEntriesFromContent(H.content)}let J={conversationId:H.metadata.conversationId,channelName:H.metadata.channelName,entries:W,totalMessages:H.metadata.totalMessages,entryCount:W.length,updated:H.updated};return Q.parse(J)}let I=(await $.listEntities(w.entityType,{limit:w.query?.limit??100})).map((H)=>{let W;try{let F=F2(H.content,Z.record(Z.string(),Z.unknown()));W=this.adapter.parseEntriesFromContent(F.content)}catch{W=this.adapter.parseEntriesFromContent(H.content)}let J=W[0];return{id:H.id,conversationId:H.metadata.conversationId,channelName:H.metadata.channelName,entryCount:W.length,totalMessages:H.metadata.totalMessages,latestEntry:J?.title??"No entries",updated:H.updated,created:H.created}}),X={summaries:I,totalCount:I.length};return this.logger.debug("Creating list data",{summaryCount:I.length,firstSummary:I[0]?.id}),Q.parse(X)}}var Dg0={name:"@brains/summary",private:!0,version:"0.2.0-alpha.
|
|
6904
|
+
Be concise but comprehensive, focusing on the most important information.`});B0();GA();var RM2=Z.object({entityType:Z.literal("summary"),query:Z.object({id:Z.string().optional(),conversationId:Z.string().optional(),limit:Z.number().optional()}).optional()});class R3A{logger;id="summary:entities";name="Summary Entity DataSource";description="Fetches and transforms summary entities for rendering";adapter;constructor(A){this.logger=A;this.adapter=new uX,this.logger.debug("SummaryDataSource initialized")}async fetch(A,Q,B){let w=RM2.parse(A),$=B.entityService,D=w.query?.conversationId??w.query?.id;if(D){let H=await $.getEntity(w.query?.conversationId?"summary":w.entityType,D);if(!H)throw Error(`Summary not found: ${D}`);let W;try{let F=F2(H.content,Z.record(Z.string(),Z.unknown()));W=this.adapter.parseEntriesFromContent(F.content)}catch{W=this.adapter.parseEntriesFromContent(H.content)}let J={conversationId:H.metadata.conversationId,channelName:H.metadata.channelName,entries:W,totalMessages:H.metadata.totalMessages,entryCount:W.length,updated:H.updated};return Q.parse(J)}let I=(await $.listEntities(w.entityType,{limit:w.query?.limit??100})).map((H)=>{let W;try{let F=F2(H.content,Z.record(Z.string(),Z.unknown()));W=this.adapter.parseEntriesFromContent(F.content)}catch{W=this.adapter.parseEntriesFromContent(H.content)}let J=W[0];return{id:H.id,conversationId:H.metadata.conversationId,channelName:H.metadata.channelName,entryCount:W.length,totalMessages:H.metadata.totalMessages,latestEntry:J?.title??"No entries",updated:H.updated,created:H.created}}),X={summaries:I,totalCount:I.length};return this.logger.debug("Creating list data",{summaryCount:I.length,firstSummary:I[0]?.id}),Q.parse(X)}}var Dg0={name:"@brains/summary",private:!0,version:"0.2.0-alpha.38",description:"Plugin for generating entity summaries and digests",type:"module",main:"./src/index.ts",exports:{".":"./src/index.ts"},scripts:{test:"bun test",typecheck:"tsc --noEmit",lint:"eslint src test --ext .ts,.tsx","lint:fix":"eslint src test --ext .ts,.tsx --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/node":"^20.0.0",eslint:"^8.56.0",typescript:"^5.3.3"}};var kM2=new uX;class j3A extends HQ{entityType="summary";schema=Lb;adapter=kM2;digestHandler=null;constructor(A){super("summary",Dg0,A??{},C3A)}getConfig(){return this.config}getTemplates(){return{"summary-list":Bg0,"summary-detail":wg0,"ai-response":$g0}}getDataSources(){return[new R3A(this.logger)]}async onRegister(A){if(this.digestHandler=IU.getInstance(A,this.logger),this.config.enableAutoSummary)A.messaging.subscribe("conversation:digest",async(Q)=>{let B=QS.parse(Q.payload);return await this.handleDigestMessage({...Q,payload:B}),{success:!0}}),this.logger.debug("Summary plugin subscribed to digest events")}async derive(A,Q,B){}async handleDigestMessage(A){if(!this.digestHandler){this.logger.error("Digest handler not initialized");return}try{await this.digestHandler.handleDigest(A.payload)}catch(Q){this.logger.error("Failed to handle digest message",{messageId:A.id,error:L0(Q)})}}}function k3A(A){return new j3A(A)}var Yg0=["prompt","directory-sync","note","link","topics","agents","admin","dashboard","mcp","webserver","discord","a2a"],_M2=[...Yg0,"image","site-info","site-content","site-builder"],Ig0=uW({name:"relay",version:"0.1.0",model:"gpt-5.4-mini",site:WJ,theme:FE,presets:{core:Yg0,default:_M2},evalDisable:["webserver","discord"],capabilities:[["prompt",Hz,void 0],["note",wz,{}],["link",Dz,{}],["image",Yj,void 0],["topics",Ri,{}],["summary",k3A,{}],["decks",r_,void 0],["agents",Kr,void 0],["admin",IJ,{}],["dashboard",Xz,void 0],["directory-sync",LZ,{seedContent:!0,seedContentPath:PM2(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Nb,void 0],["site-info",nZ,void 0],["site-builder",Az,{}]],interfaces:[["mcp",oW,()=>({})],["discord",PG,()=>({captureUrls:!0})],["a2a",tL,()=>({})],["webserver",_G,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"anchor"},{pattern:"discord:*",level:"public"}]},deployment:{cdn:{enabled:!0,provider:"bunny"}}});import{readFileSync as aO2}from"fs";import{join as tO2}from"path";import{execSync as eO2}from"child_process";import{parseArgs as TM2}from"util";var vM2={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"},remote:{type:"string"},token:{type:"string"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}};function XU(A,Q){let B=A[Q];return typeof B==="string"?B:void 0}function ZE(A,Q){let B=A[Q];return typeof B==="boolean"?B:void 0}function Xg0(A){let{values:Q,positionals:B}=TM2({args:A,options:vM2,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:B[0]??"help",args:B.slice(1),flags:{model:XU(Q,"model"),domain:XU(Q,"domain"),"content-repo":XU(Q,"content-repo"),backend:XU(Q,"backend"),"push-to":XU(Q,"push-to"),"ai-api-key":XU(Q,"ai-api-key"),"no-interactive":ZE(Q,"no-interactive"),preview:ZE(Q,"preview"),deploy:ZE(Q,"deploy"),regen:ZE(Q,"regen"),all:ZE(Q,"all"),only:XU(Q,"only"),"dry-run":ZE(Q,"dry-run"),remote:XU(Q,"remote"),token:XU(Q,"token")}}}Cb();import{mkdirSync as mO2}from"fs";import{join as uO2}from"path";import{execSync as cO2}from"child_process";var br={name:"@rizom/brain",version:"0.2.0-alpha.38",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",type:"module",bin:{brain:"./dist/brain.js"},exports:{"./cli":"./dist/brain.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 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:{"@libsql/client":"^0.15.7","@tailwindcss/oxide":"^4.1.4","better-sqlite3":"^11.8.1",lightningcss:"^1.29.2","react-devtools-core":"^6.1.1",sharp:"^0.34.5"},devDependencies:{"@brains/app":"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",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 Jg0,writeFileSync as fb,chmodSync as Rb,existsSync as vr,readFileSync as Sr,unlinkSync as DE2}from"fs";import{basename as T3A,dirname as v3A,join as O8,resolve as YE2}from"path";import{fileURLToPath as IE2}from"url";var b3A=`ARG BUN_VERSION=1.3.10
|
|
6904
6905
|
FROM oven/bun:\${BUN_VERSION}-slim AS runtime
|
|
6905
6906
|
|
|
6906
6907
|
WORKDIR /app
|