@rizom/brain 0.2.0-alpha.31 → 0.2.0-alpha.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/brain.js CHANGED
@@ -519,7 +519,7 @@ This will delete existing topics and regenerate them from scratch.`,args:{...D,c
519
519
  hash text NOT NULL,
520
520
  created_at numeric
521
521
  )
522
- `;await A.session.run(w);let Y=(await A.values(fA`SELECT id, hash, created_at FROM ${fA.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let I of B)if(!Y||Number(Y[2])<I.folderMillis){for(let K of I.sql)X.push(A.run(fA.raw(K)));X.push(A.run(fA`INSERT INTO ${fA.identifier($)} ("hash", "created_at") VALUES(${I.hash}, ${I.folderMillis})`))}await A.session.migrate(X)}var ih=l(()=>{ouA();C9()});async function suA(A,Q){let B=Q?.child("entity-migrate")??TQ.getInstance().child("entity-migrate"),{db:$,client:w,url:D}=Ov(A);B.debug("Running entity database migrations...");try{await jv(w,D);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),await Rv(w),B.debug("Entity database migrations completed successfully")}catch(Y){throw B.error("Entity database migration failed:",Y),Y}finally{w.close()}}var auA=l(()=>{ih();Et();ZA()});async function tuA(A,Q){let B=Q?.child("job-queue-migrate")??TQ.getInstance().child("job-queue-migrate"),{db:$,client:w,url:D}=Mv(A);B.debug("Running job queue migrations...");try{await Cv(w,D);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),B.debug("Job queue migrations completed successfully")}catch(Y){throw B.error("Job queue migration failed:",Y),Y}finally{w.close()}}var euA=l(()=>{ih();Vt();ZA()});async function AcA(A,Q){let B=Q?.child("conversation-migrate")??TQ.getInstance().child("conversation-migrate"),{db:$,client:w,url:D}=vv(A);B.debug("Running conversation database migrations...");try{if(D.startsWith("file:"))await w.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),B.debug("Conversation database migrations completed successfully")}catch(Y){throw B.error("Conversation database migration failed:",Y),Y}finally{w.close()}}var QcA=l(()=>{ih();st();ZA()});class ej{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:_O,migrateEntities:suA,migrateJobQueue:tuA,migrateConversations:AcA}}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 x8A=l(()=>{ph();auA();euA();QcA()});var rh;var v8A=l(()=>{ZA();rh=F.object({theme:F.object({primaryColor:F.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:F.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var $cA;var BcA=l(()=>{$cA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.31",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 G2=b((zK1,nh)=>{(function(){function A(QA,WA){Object.defineProperty($.prototype,QA,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",WA[0],WA[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,WA){QA=(QA=QA.constructor)&&(QA.displayName||QA.name)||"ReactClass";var nA=QA+"."+WA;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.",WA,QA),JA[nA]=!0)}function $(QA,WA,nA){this.props=QA,this.context=WA,this.refs=vA,this.updater=nA||EA}function w(){}function D(QA,WA,nA){this.props=QA,this.context=WA,this.refs=vA,this.updater=nA||EA}function Y(){}function X(QA){return""+QA}function I(QA){try{X(QA);var WA=!1}catch(m0){WA=!0}if(WA){WA=console;var nA=WA.error,y0=typeof Symbol==="function"&&Symbol.toStringTag&&QA[Symbol.toStringTag]||QA.constructor.name||"Object";return nA.call(WA,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y0),X(QA)}}function K(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 HA:return"Profiler";case i:return"StrictMode";case h0:return"Suspense";case VA:return"SuspenseList";case NA: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 KA:return QA.displayName||"Context";case hA:return(QA._context.displayName||"Context")+".Consumer";case X0:var WA=QA.render;return QA=QA.displayName,QA||(QA=WA.displayName||WA.name||"",QA=QA!==""?"ForwardRef("+QA+")":"ForwardRef"),QA;case f0:return WA=QA.displayName||null,WA!==null?WA:K(QA.type)||"Memo";case I0:WA=QA._payload,QA=QA._init;try{return K(QA(WA))}catch(nA){}}return null}function G(QA){if(QA===e)return"<>";if(typeof QA==="object"&&QA!==null&&QA.$$typeof===I0)return"<...>";try{var WA=K(QA);return WA?"<"+WA+">":"<...>"}catch(nA){return"<...>"}}function W(){var QA=rA.A;return QA===null?null:QA.getOwner()}function Z(){return Error("react-stack-top-frame")}function q(QA){if(CA.call(QA,"key")){var WA=Object.getOwnPropertyDescriptor(QA,"key").get;if(WA&&WA.isReactWarning)return!1}return QA.key!==void 0}function N(QA,WA){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)",WA))}nA.isReactWarning=!0,Object.defineProperty(QA,"key",{get:nA,configurable:!0})}function M(){var QA=K(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,WA,nA,y0,m0,G1){var M0=nA.ref;return QA={$$typeof:s,type:QA,key:WA,props:nA,_owner:y0},(M0!==void 0?M0:null)!==null?Object.defineProperty(QA,"ref",{enumerable:!1,get:M}):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:G1}),Object.freeze&&(Object.freeze(QA.props),Object.freeze(QA)),QA}function _(QA,WA){return WA=L(QA.type,WA,QA.props,QA._owner,QA._debugStack,QA._debugTask),QA._store&&(WA._store.validated=QA._store.validated),WA}function T(QA){P(QA)?QA._store&&(QA._store.validated=1):typeof QA==="object"&&QA!==null&&QA.$$typeof===I0&&(QA._payload.status==="fulfilled"?P(QA._payload.value)&&QA._payload.value._store&&(QA._payload.value._store.validated=1):QA._store&&(QA._store.validated=1))}function P(QA){return typeof QA==="object"&&QA!==null&&QA.$$typeof===s}function r(QA){var WA={"=":"=0",":":"=2"};return"$"+QA.replace(/[=:]/g,function(nA){return WA[nA]})}function n(QA,WA){return typeof QA==="object"&&QA!==null&&QA.key!=null?(I(QA.key),r(""+QA.key)):WA.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(WA){QA.status==="pending"&&(QA.status="fulfilled",QA.value=WA)},function(WA){QA.status==="pending"&&(QA.status="rejected",QA.reason=WA)})),QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason}}throw QA}function x(QA,WA,nA,y0,m0){var G1=typeof QA;if(G1==="undefined"||G1==="boolean")QA=null;var M0=!1;if(QA===null)M0=!0;else switch(G1){case"bigint":case"string":case"number":M0=!0;break;case"object":switch(QA.$$typeof){case s:case d:M0=!0;break;case I0:return M0=QA._init,x(M0(QA._payload),WA,nA,y0,m0)}}if(M0){M0=QA,m0=m0(M0);var M1=y0===""?"."+n(M0,0):y0;return D0(m0)?(nA="",M1!=null&&(nA=M1.replace(kA,"$&/")+"/"),x(m0,WA,nA,"",function(CQ){return CQ})):m0!=null&&(P(m0)&&(m0.key!=null&&(M0&&M0.key===m0.key||I(m0.key)),nA=_(m0,nA+(m0.key==null||M0&&M0.key===m0.key?"":(""+m0.key).replace(kA,"$&/")+"/")+M1),y0!==""&&M0!=null&&P(M0)&&M0.key==null&&M0._store&&!M0._store.validated&&(nA._store.validated=2),m0=nA),WA.push(m0)),1}if(M0=0,M1=y0===""?".":y0+":",D0(QA))for(var N1=0;N1<QA.length;N1++)y0=QA[N1],G1=M1+n(y0,N1),M0+=x(y0,WA,nA,G1,m0);else if(N1=Q(QA),typeof N1==="function")for(N1===QA.entries&&(xA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),xA=!0),QA=N1.call(QA),N1=0;!(y0=QA.next()).done;)y0=y0.value,G1=M1+n(y0,N1++),M0+=x(y0,WA,nA,G1,m0);else if(G1==="object"){if(typeof QA.then==="function")return x(g(QA),WA,nA,y0,m0);throw WA=String(QA),Error("Objects are not valid as a React child (found: "+(WA==="[object Object]"?"object with keys {"+Object.keys(QA).join(", ")+"}":WA)+"). If you meant to render a collection of children, use an array instead.")}return M0}function S(QA,WA,nA){if(QA==null)return QA;var y0=[],m0=0;return x(QA,y0,"","",function(G1){return WA.call(nA,G1,m0++)}),y0}function h(QA){if(QA._status===-1){var WA=QA._ioInfo;WA!=null&&(WA.start=WA.end=performance.now()),WA=QA._result;var nA=WA();if(nA.then(function(m0){if(QA._status===0||QA._status===-1){QA._status=1,QA._result=m0;var G1=QA._ioInfo;G1!=null&&(G1.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 G1=QA._ioInfo;G1!=null&&(G1.end=performance.now()),nA.status===void 0&&(nA.status="rejected",nA.reason=m0)}}),WA=QA._ioInfo,WA!=null){WA.value=nA;var y0=nA.displayName;typeof y0==="string"&&(WA.name=y0)}QA._status===-1&&(QA._status=0,QA._result=nA)}if(QA._status===1)return WA=QA._result,WA===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
522
+ `;await A.session.run(w);let Y=(await A.values(fA`SELECT id, hash, created_at FROM ${fA.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let I of B)if(!Y||Number(Y[2])<I.folderMillis){for(let K of I.sql)X.push(A.run(fA.raw(K)));X.push(A.run(fA`INSERT INTO ${fA.identifier($)} ("hash", "created_at") VALUES(${I.hash}, ${I.folderMillis})`))}await A.session.migrate(X)}var ih=l(()=>{ouA();C9()});async function suA(A,Q){let B=Q?.child("entity-migrate")??TQ.getInstance().child("entity-migrate"),{db:$,client:w,url:D}=Ov(A);B.debug("Running entity database migrations...");try{await jv(w,D);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),await Rv(w),B.debug("Entity database migrations completed successfully")}catch(Y){throw B.error("Entity database migration failed:",Y),Y}finally{w.close()}}var auA=l(()=>{ih();Et();ZA()});async function tuA(A,Q){let B=Q?.child("job-queue-migrate")??TQ.getInstance().child("job-queue-migrate"),{db:$,client:w,url:D}=Mv(A);B.debug("Running job queue migrations...");try{await Cv(w,D);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),B.debug("Job queue migrations completed successfully")}catch(Y){throw B.error("Job queue migration failed:",Y),Y}finally{w.close()}}var euA=l(()=>{ih();Vt();ZA()});async function AcA(A,Q){let B=Q?.child("conversation-migrate")??TQ.getInstance().child("conversation-migrate"),{db:$,client:w,url:D}=vv(A);B.debug("Running conversation database migrations...");try{if(D.startsWith("file:"))await w.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await oV($,{migrationsFolder:X}),B.debug("Conversation database migrations completed successfully")}catch(Y){throw B.error("Conversation database migration failed:",Y),Y}finally{w.close()}}var QcA=l(()=>{ih();st();ZA()});class ej{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:_O,migrateEntities:suA,migrateJobQueue:tuA,migrateConversations:AcA}}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 x8A=l(()=>{ph();auA();euA();QcA()});var rh;var v8A=l(()=>{ZA();rh=F.object({theme:F.object({primaryColor:F.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:F.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var $cA;var BcA=l(()=>{$cA={name:"@brains/chat-repl",private:!0,version:"0.2.0-alpha.32",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 G2=b((zK1,nh)=>{(function(){function A(QA,WA){Object.defineProperty($.prototype,QA,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",WA[0],WA[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,WA){QA=(QA=QA.constructor)&&(QA.displayName||QA.name)||"ReactClass";var nA=QA+"."+WA;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.",WA,QA),JA[nA]=!0)}function $(QA,WA,nA){this.props=QA,this.context=WA,this.refs=vA,this.updater=nA||EA}function w(){}function D(QA,WA,nA){this.props=QA,this.context=WA,this.refs=vA,this.updater=nA||EA}function Y(){}function X(QA){return""+QA}function I(QA){try{X(QA);var WA=!1}catch(m0){WA=!0}if(WA){WA=console;var nA=WA.error,y0=typeof Symbol==="function"&&Symbol.toStringTag&&QA[Symbol.toStringTag]||QA.constructor.name||"Object";return nA.call(WA,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y0),X(QA)}}function K(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 HA:return"Profiler";case i:return"StrictMode";case h0:return"Suspense";case VA:return"SuspenseList";case NA: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 KA:return QA.displayName||"Context";case hA:return(QA._context.displayName||"Context")+".Consumer";case X0:var WA=QA.render;return QA=QA.displayName,QA||(QA=WA.displayName||WA.name||"",QA=QA!==""?"ForwardRef("+QA+")":"ForwardRef"),QA;case f0:return WA=QA.displayName||null,WA!==null?WA:K(QA.type)||"Memo";case I0:WA=QA._payload,QA=QA._init;try{return K(QA(WA))}catch(nA){}}return null}function G(QA){if(QA===e)return"<>";if(typeof QA==="object"&&QA!==null&&QA.$$typeof===I0)return"<...>";try{var WA=K(QA);return WA?"<"+WA+">":"<...>"}catch(nA){return"<...>"}}function W(){var QA=rA.A;return QA===null?null:QA.getOwner()}function Z(){return Error("react-stack-top-frame")}function q(QA){if(CA.call(QA,"key")){var WA=Object.getOwnPropertyDescriptor(QA,"key").get;if(WA&&WA.isReactWarning)return!1}return QA.key!==void 0}function N(QA,WA){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)",WA))}nA.isReactWarning=!0,Object.defineProperty(QA,"key",{get:nA,configurable:!0})}function M(){var QA=K(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,WA,nA,y0,m0,G1){var M0=nA.ref;return QA={$$typeof:s,type:QA,key:WA,props:nA,_owner:y0},(M0!==void 0?M0:null)!==null?Object.defineProperty(QA,"ref",{enumerable:!1,get:M}):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:G1}),Object.freeze&&(Object.freeze(QA.props),Object.freeze(QA)),QA}function _(QA,WA){return WA=L(QA.type,WA,QA.props,QA._owner,QA._debugStack,QA._debugTask),QA._store&&(WA._store.validated=QA._store.validated),WA}function T(QA){P(QA)?QA._store&&(QA._store.validated=1):typeof QA==="object"&&QA!==null&&QA.$$typeof===I0&&(QA._payload.status==="fulfilled"?P(QA._payload.value)&&QA._payload.value._store&&(QA._payload.value._store.validated=1):QA._store&&(QA._store.validated=1))}function P(QA){return typeof QA==="object"&&QA!==null&&QA.$$typeof===s}function r(QA){var WA={"=":"=0",":":"=2"};return"$"+QA.replace(/[=:]/g,function(nA){return WA[nA]})}function n(QA,WA){return typeof QA==="object"&&QA!==null&&QA.key!=null?(I(QA.key),r(""+QA.key)):WA.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(WA){QA.status==="pending"&&(QA.status="fulfilled",QA.value=WA)},function(WA){QA.status==="pending"&&(QA.status="rejected",QA.reason=WA)})),QA.status){case"fulfilled":return QA.value;case"rejected":throw QA.reason}}throw QA}function x(QA,WA,nA,y0,m0){var G1=typeof QA;if(G1==="undefined"||G1==="boolean")QA=null;var M0=!1;if(QA===null)M0=!0;else switch(G1){case"bigint":case"string":case"number":M0=!0;break;case"object":switch(QA.$$typeof){case s:case d:M0=!0;break;case I0:return M0=QA._init,x(M0(QA._payload),WA,nA,y0,m0)}}if(M0){M0=QA,m0=m0(M0);var M1=y0===""?"."+n(M0,0):y0;return D0(m0)?(nA="",M1!=null&&(nA=M1.replace(kA,"$&/")+"/"),x(m0,WA,nA,"",function(CQ){return CQ})):m0!=null&&(P(m0)&&(m0.key!=null&&(M0&&M0.key===m0.key||I(m0.key)),nA=_(m0,nA+(m0.key==null||M0&&M0.key===m0.key?"":(""+m0.key).replace(kA,"$&/")+"/")+M1),y0!==""&&M0!=null&&P(M0)&&M0.key==null&&M0._store&&!M0._store.validated&&(nA._store.validated=2),m0=nA),WA.push(m0)),1}if(M0=0,M1=y0===""?".":y0+":",D0(QA))for(var N1=0;N1<QA.length;N1++)y0=QA[N1],G1=M1+n(y0,N1),M0+=x(y0,WA,nA,G1,m0);else if(N1=Q(QA),typeof N1==="function")for(N1===QA.entries&&(xA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),xA=!0),QA=N1.call(QA),N1=0;!(y0=QA.next()).done;)y0=y0.value,G1=M1+n(y0,N1++),M0+=x(y0,WA,nA,G1,m0);else if(G1==="object"){if(typeof QA.then==="function")return x(g(QA),WA,nA,y0,m0);throw WA=String(QA),Error("Objects are not valid as a React child (found: "+(WA==="[object Object]"?"object with keys {"+Object.keys(QA).join(", ")+"}":WA)+"). If you meant to render a collection of children, use an array instead.")}return M0}function S(QA,WA,nA){if(QA==null)return QA;var y0=[],m0=0;return x(QA,y0,"","",function(G1){return WA.call(nA,G1,m0++)}),y0}function h(QA){if(QA._status===-1){var WA=QA._ioInfo;WA!=null&&(WA.start=WA.end=performance.now()),WA=QA._result;var nA=WA();if(nA.then(function(m0){if(QA._status===0||QA._status===-1){QA._status=1,QA._result=m0;var G1=QA._ioInfo;G1!=null&&(G1.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 G1=QA._ioInfo;G1!=null&&(G1.end=performance.now()),nA.status===void 0&&(nA.status="rejected",nA.reason=m0)}}),WA=QA._ioInfo,WA!=null){WA.value=nA;var y0=nA.displayName;typeof y0==="string"&&(WA.name=y0)}QA._status===-1&&(QA._status=0,QA._result=nA)}if(QA._status===1)return WA=QA._result,WA===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
523
523
 
524
524
  Your code should look like:
525
525
  const MyComponent = lazy(() => import('./MyComponent'))
@@ -1573,7 +1573,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
1573
1573
  Title: "${A.entityTitle??X}"
1574
1574
 
1575
1575
  Content:
1576
- ${A.entityContent}`,lW1);I=$+_.imagePrompt}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:L0(_)})}}await this.reportProgress(B,{progress:GQ.PROCESS,message:"Generating image"});let K=this.context.identity.get(),G=this.context.identity.getProfile(),Z=DrA(K,G)+I,q;try{q=await this.context.ai.generateImage(Z,{...w&&{aspectRatio:w}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:L0(_)}),I6.failure(_)}await this.reportProgress(B,{progress:GQ.GENERATE,message:"Creating image entity"});let N=a1(X),M=yG.createImageEntity({dataUrl:q.dataUrl,title:X});if(await this.context.entityService.getEntity("image",N))this.logger.debug("Deleting existing image for regeneration",{imageId:N}),await this.context.entityService.deleteEntity("image",N);if(await this.context.entityService.createEntity({...M,id:N}),this.logger.debug("Created image entity",{imageId:N}),D&&Y){await this.reportProgress(B,{progress:GQ.SAVE,message:`Updating ${D} with cover image`});let _=await Tv(this.context.entityService,D,Y,this.logger);if(!_)return I6.failure(Error(`Target entity not found: ${D}/${Y}`));let T=jz(_,N);await this.context.entities.update(T),this.logger.debug("Updated target entity with cover image",{targetEntityType:D,targetEntityId:Y,imageId:N})}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:N,targetEntityType:D,targetEntityId:Y}),{success:!0,imageId:N}}catch(I){return this.logger.error("Image generation job failed",{jobId:Q,error:L0(I)}),I6.failure(I)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}var YrA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.31",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 iW1=F.object({defaultAspectRatio:F.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});class m9A extends z2{entityType=yG.entityType;schema=mR;adapter=yG;constructor(A={}){super("image",YrA,A,iW1)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,B){if(!A.targetEntityType||!A.targetEntityId)return{kind:"continue",input:A};let $=await bK(B.entityService,A.targetEntityType,A.targetEntityId,this.logger,"Target entity");if(!$.ok)return{kind:"handled",result:{success:!1,error:$.error}};return{kind:"continue",input:{...A,targetEntityId:$.entity.id}}}createGenerationHandler(A){return new Iy(A,this.logger)}async onRegister(A){let Q=new Iy(A,this.logger);A.jobs.registerHandler("image-generate",Q)}}function lR(A){return new m9A(A)}w0();import{StdioServerTransport as rW1}from"@modelcontextprotocol/sdk/server/stdio.js";function XrA(){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 u9A(){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 Ky(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(B,...$)=>Q.info(B,...$),debug:(B,...$)=>Q.debug(B,...$),error:(B,...$)=>Q.error(B,...$),warn:(B,...$)=>Q.warn(B,...$)}}return u9A()}class KY{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return KY.instance??=new KY(A),KY.instance}static resetInstance(){if(KY.instance)KY.instance.stop(),KY.instance=null}static createFresh(A){return new KY(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?Ky(this.config.logger):XrA()}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 rW1,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 IrA}from"crypto";import{WebStandardStreamableHTTPServerTransport as nW1}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as oW1}from"@modelcontextprotocol/sdk/types.js";var sW1={"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 tK{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?Ky(this.config.logger):u9A(),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 tK.instance??=new tK(A),tK.instance}static resetInstance(){tK.instance=null}static createFresh(A){return new tK(A)}withCors(A){let Q=new Headers(A.headers);for(let[B,$]of Object.entries(sW1))Q.set(B,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}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 $;if(Q&&this.transports[Q])$=this.transports[Q];else if(!Q&&oW1(B))$=new nW1({sessionIdGenerator:()=>IrA(),onsessioninitialized:(D)=>{this.logger.info(`Session initialized: ${D}`),this.transports[D]=$},onsessionclosed:(D)=>{this.logger.info(`Session closed: ${D}`),delete this.transports[D]}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect($);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await $.handleRequest(A,{parsedBody:B}))}catch($){return this.logger.error("MCP transport error:",$),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 $=B??IrA();this.logger.debug(`POST /api/chat - conversation: ${$}`);try{let w=await this.agentService.chat(Q,$);return this.createJsonResponse(w)}catch(w){return this.logger.error("Agent chat error:",w),this.createJsonResponse({error:w instanceof Error?w.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}}ZA();var c9A=F.object({transport:F.enum(["stdio","http"]).default("http"),httpPort:F.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:F.string().describe("Bearer token for HTTP transport authentication").optional()});function KrA(A,Q){return[]}w0();function l9A(A,Q){A.messaging.subscribe("job-progress",async(B)=>{let $=nz.safeParse(B.payload);if(!$.success)return Q.warn("Received invalid job-progress message",{error:$.error.message}),{success:!1};let w=$.data,D=w.type,Y=w.status,X=w.id;if(Q.debug(`${D} ${X} - ${Y}:`,{id:w.id,message:w.message,progress:w.progress,metadata:w.metadata}),w.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:w.batchDetails.totalOperations,completedOperations:w.batchDetails.completedOperations,failedOperations:w.batchDetails.failedOperations,currentOperation:w.batchDetails.currentOperation,errors:w.batchDetails.errors});if(w.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:w.jobDetails.jobType,priority:w.jobDetails.priority,retryCount:w.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var HrA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.31",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 mG extends bX{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",HrA,Q,c9A)}async getTools(){return KrA(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});l9A(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;return this.httpServer=tK.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=KY.createFresh();let $=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer($),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let $=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer($,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(){KY.resetInstance(),tK.resetInstance()}}w0();ZA();var iD=o0(_Z0(),1);ZA();w0();var OYA=F.object({botToken:F.string().min(1).describe("Discord bot token"),allowedChannels:F.array(F.string()).default([]),requireMention:F.boolean().default(!0),allowDMs:F.boolean().default(!0),showTypingIndicator:F.boolean().default(!0),statusMessage:F.string().default("Mention me to chat"),useThreads:F.boolean().default(!0),threadAutoArchive:F.union([F.literal(60),F.literal(1440),F.literal(4320),F.literal(10080)]).default(1440),...gv.shape,captureUrlEmoji:F.string().default("\uD83D\uDD16")});var kZ0={name:"@brains/discord",private:!0,version:"0.2.0-alpha.31",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 jYA=2000,Gs1=8000,Js1=100;function Zc(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class LJ extends i4{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",kZ0,A,OYA);this.fetchText=Q.fetchText??dx}async onRegister(A){await super.onRegister(A),this.client=new iD.Client({intents:[iD.GatewayIntentBits.Guilds,iD.GatewayIntentBits.GuildMessages,iD.GatewayIntentBits.MessageContent,iD.GatewayIntentBits.DirectMessages],partials:[iD.Partials.Channel]}),this.client.on(iD.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.once(iD.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(!Zc(B))return;let $=lC(Q,jYA);for(let w of $)B.send(w).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(!Zc(B))return;let $=lC(Q,jYA),w;for(let D of $)w=(await B.send(D)).id;return w}async editMessage(A,Q,B){if(!A||!this.client)return!1;let $=this.client.channels.cache.get(A);if(!Zc($))return!1;try{return await(await $.messages.fetch(Q)).edit(B.slice(0,jYA)),!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 $=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!$)return;let w=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&&!w&&this.config.requireMention&&!$){if(this.config.captureUrls){let X=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(X.length>0){await A.react(this.config.captureUrlEmoji).catch((I)=>this.logger.debug("React failed",{error:I}));for(let I of X)await this.captureUrlViaAgent(I,A.channel.id,A.author.id,"discord").catch((K)=>this.logger.error("URL capture failed",{error:K,url:I}))}}return}let D=this.stripMention(A.content);if(A.attachments.size>0){let X=this.context.permissions.getUserLevel("discord",A.author.id);if(X==="anchor"||X==="trusted")for(let K of A.attachments.values()){let G=K.name,W=K.contentType??void 0,Z=K.size;if(!this.isUploadableTextFile(G,W))continue;if(!this.isFileSizeAllowed(Z))continue;try{let q=await this.fetchText(K.url);D+=`
1576
+ ${A.entityContent}`,lW1);I=$+_.imagePrompt}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:L0(_)})}}await this.reportProgress(B,{progress:GQ.PROCESS,message:"Generating image"});let K=this.context.identity.get(),G=this.context.identity.getProfile(),Z=DrA(K,G)+I,q;try{q=await this.context.ai.generateImage(Z,{...w&&{aspectRatio:w}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:L0(_)}),I6.failure(_)}await this.reportProgress(B,{progress:GQ.GENERATE,message:"Creating image entity"});let N=a1(X),M=yG.createImageEntity({dataUrl:q.dataUrl,title:X});if(await this.context.entityService.getEntity("image",N))this.logger.debug("Deleting existing image for regeneration",{imageId:N}),await this.context.entityService.deleteEntity("image",N);if(await this.context.entityService.createEntity({...M,id:N}),this.logger.debug("Created image entity",{imageId:N}),D&&Y){await this.reportProgress(B,{progress:GQ.SAVE,message:`Updating ${D} with cover image`});let _=await Tv(this.context.entityService,D,Y,this.logger);if(!_)return I6.failure(Error(`Target entity not found: ${D}/${Y}`));let T=jz(_,N);await this.context.entities.update(T),this.logger.debug("Updated target entity with cover image",{targetEntityType:D,targetEntityId:Y,imageId:N})}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:N,targetEntityType:D,targetEntityId:Y}),{success:!0,imageId:N}}catch(I){return this.logger.error("Image generation job failed",{jobId:Q,error:L0(I)}),I6.failure(I)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}var YrA={name:"@brains/image-plugin",private:!0,version:"0.2.0-alpha.32",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 iW1=F.object({defaultAspectRatio:F.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});class m9A extends z2{entityType=yG.entityType;schema=mR;adapter=yG;constructor(A={}){super("image",YrA,A,iW1)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,B){if(!A.targetEntityType||!A.targetEntityId)return{kind:"continue",input:A};let $=await bK(B.entityService,A.targetEntityType,A.targetEntityId,this.logger,"Target entity");if(!$.ok)return{kind:"handled",result:{success:!1,error:$.error}};return{kind:"continue",input:{...A,targetEntityId:$.entity.id}}}createGenerationHandler(A){return new Iy(A,this.logger)}async onRegister(A){let Q=new Iy(A,this.logger);A.jobs.registerHandler("image-generate",Q)}}function lR(A){return new m9A(A)}w0();import{StdioServerTransport as rW1}from"@modelcontextprotocol/sdk/server/stdio.js";function XrA(){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 u9A(){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 Ky(A){if(A&&typeof A==="object"&&"info"in A&&"debug"in A&&"error"in A&&"warn"in A){let Q=A;return{info:(B,...$)=>Q.info(B,...$),debug:(B,...$)=>Q.debug(B,...$),error:(B,...$)=>Q.error(B,...$),warn:(B,...$)=>Q.warn(B,...$)}}return u9A()}class KY{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return KY.instance??=new KY(A),KY.instance}static resetInstance(){if(KY.instance)KY.instance.stop(),KY.instance=null}static createFresh(A){return new KY(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?Ky(this.config.logger):XrA()}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 rW1,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 IrA}from"crypto";import{WebStandardStreamableHTTPServerTransport as nW1}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as oW1}from"@modelcontextprotocol/sdk/types.js";var sW1={"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 tK{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?Ky(this.config.logger):u9A(),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 tK.instance??=new tK(A),tK.instance}static resetInstance(){tK.instance=null}static createFresh(A){return new tK(A)}withCors(A){let Q=new Headers(A.headers);for(let[B,$]of Object.entries(sW1))Q.set(B,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}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 $;if(Q&&this.transports[Q])$=this.transports[Q];else if(!Q&&oW1(B))$=new nW1({sessionIdGenerator:()=>IrA(),onsessioninitialized:(D)=>{this.logger.info(`Session initialized: ${D}`),this.transports[D]=$},onsessionclosed:(D)=>{this.logger.info(`Session closed: ${D}`),delete this.transports[D]}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect($);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await $.handleRequest(A,{parsedBody:B}))}catch($){return this.logger.error("MCP transport error:",$),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 $=B??IrA();this.logger.debug(`POST /api/chat - conversation: ${$}`);try{let w=await this.agentService.chat(Q,$);return this.createJsonResponse(w)}catch(w){return this.logger.error("Agent chat error:",w),this.createJsonResponse({error:w instanceof Error?w.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}}ZA();var c9A=F.object({transport:F.enum(["stdio","http"]).default("http"),httpPort:F.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:F.string().describe("Bearer token for HTTP transport authentication").optional()});function KrA(A,Q){return[]}w0();function l9A(A,Q){A.messaging.subscribe("job-progress",async(B)=>{let $=nz.safeParse(B.payload);if(!$.success)return Q.warn("Received invalid job-progress message",{error:$.error.message}),{success:!1};let w=$.data,D=w.type,Y=w.status,X=w.id;if(Q.debug(`${D} ${X} - ${Y}:`,{id:w.id,message:w.message,progress:w.progress,metadata:w.metadata}),w.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:w.batchDetails.totalOperations,completedOperations:w.batchDetails.completedOperations,failedOperations:w.batchDetails.failedOperations,currentOperation:w.batchDetails.currentOperation,errors:w.batchDetails.errors});if(w.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:w.jobDetails.jobType,priority:w.jobDetails.priority,retryCount:w.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var HrA={name:"@brains/mcp",private:!0,version:"0.2.0-alpha.32",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 mG extends bX{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",HrA,Q,c9A)}async getTools(){return KrA(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});l9A(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;return this.httpServer=tK.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=KY.createFresh();let $=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer($),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let $=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer($,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(){KY.resetInstance(),tK.resetInstance()}}w0();ZA();var iD=o0(_Z0(),1);ZA();w0();var OYA=F.object({botToken:F.string().min(1).describe("Discord bot token"),allowedChannels:F.array(F.string()).default([]),requireMention:F.boolean().default(!0),allowDMs:F.boolean().default(!0),showTypingIndicator:F.boolean().default(!0),statusMessage:F.string().default("Mention me to chat"),useThreads:F.boolean().default(!0),threadAutoArchive:F.union([F.literal(60),F.literal(1440),F.literal(4320),F.literal(10080)]).default(1440),...gv.shape,captureUrlEmoji:F.string().default("\uD83D\uDD16")});var kZ0={name:"@brains/discord",private:!0,version:"0.2.0-alpha.32",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 jYA=2000,Gs1=8000,Js1=100;function Zc(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class LJ extends i4{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",kZ0,A,OYA);this.fetchText=Q.fetchText??dx}async onRegister(A){await super.onRegister(A),this.client=new iD.Client({intents:[iD.GatewayIntentBits.Guilds,iD.GatewayIntentBits.GuildMessages,iD.GatewayIntentBits.MessageContent,iD.GatewayIntentBits.DirectMessages],partials:[iD.Partials.Channel]}),this.client.on(iD.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.once(iD.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(!Zc(B))return;let $=lC(Q,jYA);for(let w of $)B.send(w).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(!Zc(B))return;let $=lC(Q,jYA),w;for(let D of $)w=(await B.send(D)).id;return w}async editMessage(A,Q,B){if(!A||!this.client)return!1;let $=this.client.channels.cache.get(A);if(!Zc($))return!1;try{return await(await $.messages.fetch(Q)).edit(B.slice(0,jYA)),!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 $=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!$)return;let w=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&&!w&&this.config.requireMention&&!$){if(this.config.captureUrls){let X=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(X.length>0){await A.react(this.config.captureUrlEmoji).catch((I)=>this.logger.debug("React failed",{error:I}));for(let I of X)await this.captureUrlViaAgent(I,A.channel.id,A.author.id,"discord").catch((K)=>this.logger.error("URL capture failed",{error:K,url:I}))}}return}let D=this.stripMention(A.content);if(A.attachments.size>0){let X=this.context.permissions.getUserLevel("discord",A.author.id);if(X==="anchor"||X==="trusted")for(let K of A.attachments.values()){let G=K.name,W=K.contentType??void 0,Z=K.size;if(!this.isUploadableTextFile(G,W))continue;if(!this.isFileSizeAllowed(Z))continue;try{let q=await this.fetchText(K.url);D+=`
1577
1577
 
1578
1578
  `+this.formatFileUploadMessage(G,q)}catch(q){this.logger.error("Failed to download attachment",{error:q,filename:G})}}}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 $=this.context.agentService,w=Q;if(this.config.useThreads&&B.guild&&!B.channel.isThread())try{w=(await B.startThread({name:$G(A,Js1),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(I){this.logger.error("Failed to create thread",{error:I})}let D=`discord-${w}`,Y=this.context.permissions.getUserLevel("discord",B.author.id),X=B.guild?.name??"DM";this.startProcessingInput(w);try{let I=this.client?.channels.cache.get(w);if(Zc(I))this.startTypingIndicator(I);if(this.pendingConfirmations.has(D)){await this.handleConfirmationResponse(A,D,w);return}let K=await $.chat(A,D,{userPermissionLevel:Y,interfaceType:"discord",channelId:w,channelName:X});if(K.pendingConfirmation)this.pendingConfirmations.set(D,!0);let G=await this.sendMessageWithId(w,K.text);if(G&&K.toolResults){for(let W of K.toolResults)if(W.jobId)this.trackAgentResponseForJob(W.jobId,G,w)}}catch(I){this.logger.error("Error handling message",{error:I,channelId:w}),this.sendMessageToChannel(w,`**Error:** ${I instanceof Error?I.message:"Unknown error"}`)}finally{this.endProcessingInput(),this.stopTypingIndicator(w)}}async handleConfirmationResponse(A,Q,B){let $=tz(A);if(!$){this.sendMessageToChannel(B,"_Please reply with **yes** to confirm or **no/cancel** to abort._");return}this.pendingConfirmations.delete(Q);let w=await this.context?.agentService.confirmPendingAction(Q,$.confirmed);if(w)await this.sendMessageWithId(B,w.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}))},Gs1);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()}}w0();import{resolve as bL,join as es1}from"path";var RYA=(A,Q,B)=>{return($,w)=>{let D=-1;return Y(0);async function Y(X){if(X<=D)throw Error("next() called multiple times");D=X;let I,K=!1,G;if(A[X])G=A[X][0][0],$.req.routeIndex=X;else G=X===A.length&&w||void 0;if(G)try{I=await G($,()=>Y(X+1))}catch(W){if(W instanceof Error&&Q)$.error=W,I=await Q(W,$),K=!0;else throw W}else if($.finalized===!1&&B)I=await B($);if(I&&($.finalized===!1||K))$.res=I;return $}}};var fZ0=Symbol();var bZ0=async(A,Q=Object.create(null))=>{let{all:B=!1,dot:$=!1}=Q,D=(A instanceof Fc?A.raw.headers:A.headers).get("Content-Type");if(D?.startsWith("multipart/form-data")||D?.startsWith("application/x-www-form-urlencoded"))return Ws1(A,{all:B,dot:$});return{}};async function Ws1(A,Q){let B=await A.formData();if(B)return Zs1(B,Q);return{}}function Zs1(A,Q){let B=Object.create(null);if(A.forEach(($,w)=>{if(!(Q.all||w.endsWith("[]")))B[w]=$;else Fs1(B,w,$)}),Q.dot)Object.entries(B).forEach(([$,w])=>{if($.includes("."))qs1(B,$,w),delete B[$]});return B}var Fs1=(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]},qs1=(A,Q,B)=>{let $=A,w=Q.split(".");w.forEach((D,Y)=>{if(Y===w.length-1)$[D]=B;else{if(!$[D]||typeof $[D]!=="object"||Array.isArray($[D])||$[D]instanceof File)$[D]=Object.create(null);$=$[D]}})};var _YA=(A)=>{let Q=A.split("/");if(Q[0]==="")Q.shift();return Q},TZ0=(A)=>{let{groups:Q,path:B}=zs1(A),$=_YA(B);return Vs1($,Q)},zs1=(A)=>{let Q=[];return A=A.replace(/\{[^}]+\}/g,(B,$)=>{let w=`@${$}`;return Q.push([w,B]),w}),{groups:Q,path:A}},Vs1=(A,Q)=>{for(let B=Q.length-1;B>=0;B--){let[$]=Q[B];for(let w=A.length-1;w>=0;w--)if(A[w].includes($)){A[w]=A[w].replace($,Q[B][1]);break}}return A},qc={},xZ0=(A,Q)=>{if(A==="*")return"*";let B=A.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(B){let $=`${A}#${Q}`;if(!qc[$])if(B[2])qc[$]=Q&&Q[0]!==":"&&Q[0]!=="*"?[$,B[1],new RegExp(`^${B[2]}(?=/${Q})`)]:[A,B[1],new RegExp(`^${B[2]}$`)];else qc[$]=[A,B[1],!0];return qc[$]}return null},zc=(A,Q)=>{try{return Q(A)}catch{return A.replace(/(?:%[0-9A-Fa-f]{2})+/g,(B)=>{try{return Q(B)}catch{return B}})}},kYA=(A)=>zc(A,decodeURI),fYA=(A)=>{let Q=A.url,B=Q.indexOf("/",Q.indexOf(":")+4),$=B;for(;$<Q.length;$++){let w=Q.charCodeAt($);if(w===37){let D=Q.indexOf("?",$),Y=Q.indexOf("#",$),X=D===-1?Y===-1?void 0:Y:Y===-1?D:Math.min(D,Y),I=Q.slice(B,X);return kYA(I.includes("%25")?I.replace(/%25/g,"%2525"):I)}else if(w===63||w===35)break}return Q.slice(B,$)};var vZ0=(A)=>{let Q=fYA(A);return Q.length>1&&Q.at(-1)==="/"?Q.slice(0,-1):Q},B3=(A,Q,...B)=>{if(B.length)Q=B3(Q,...B);return`${A?.[0]==="/"?"":"/"}${A}${Q==="/"?"":`${A?.at(-1)==="/"?"":"/"}${Q?.[0]==="/"?Q.slice(1):Q}`}`},Vc=(A)=>{if(A.charCodeAt(A.length-1)!==63||!A.includes(":"))return null;let Q=A.split("/"),B=[],$="";return Q.forEach((w)=>{if(w!==""&&!/\:/.test(w))$+="/"+w;else if(/\:/.test(w))if(/\?/.test(w)){if(B.length===0&&$==="")B.push("/");else B.push($);let D=w.replace("?","");$+="/"+D,B.push($)}else $+="/"+w}),B.filter((w,D,Y)=>Y.indexOf(w)===D)},PYA=(A)=>{if(!/[%+]/.test(A))return A;if(A.indexOf("+")!==-1)A=A.replace(/\+/g," ");return A.indexOf("%")!==-1?zc(A,bYA):A},SZ0=(A,Q,B)=>{let $;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 X=A.charCodeAt(Y+Q.length+1);if(X===61){let I=Y+Q.length+2,K=A.indexOf("&",I);return PYA(A.slice(I,K===-1?void 0:K))}else if(X==38||isNaN(X))return"";Y=A.indexOf(`&${Q}`,Y+1)}if($=/[%+]/.test(A),!$)return}let w={};$??=/[%+]/.test(A);let D=A.indexOf("?",8);while(D!==-1){let Y=A.indexOf("&",D+1),X=A.indexOf("=",D);if(X>Y&&Y!==-1)X=-1;let I=A.slice(D+1,X===-1?Y===-1?void 0:Y:X);if($)I=PYA(I);if(D=Y,I==="")continue;let K;if(X===-1)K="";else if(K=A.slice(X+1,Y===-1?void 0:Y),$)K=PYA(K);if(B){if(!(w[I]&&Array.isArray(w[I])))w[I]=[];w[I].push(K)}else w[I]??=K}return Q?w[Q]:w},hZ0=SZ0,gZ0=(A,Q)=>{return SZ0(A,Q,!0)},bYA=decodeURIComponent;var yZ0=(A)=>zc(A,bYA),Fc=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.#w(Q);return B&&/\%/.test(B)?yZ0(B):B}#D(){let A={},Q=Object.keys(this.#Q[0][this.routeIndex][1]);for(let B of Q){let $=this.#w(this.#Q[0][this.routeIndex][1][B]);if($!==void 0)A[B]=/\%/.test($)?yZ0($):$}return A}#w(A){return this.#Q[1]?this.#Q[1][A]:A}query(A){return hZ0(this.url,A)}queries(A){return gZ0(this.url,A)}header(A){if(A)return this.raw.headers.get(A)??void 0;let Q={};return this.raw.headers.forEach((B,$)=>{Q[$]=B}),Q}async parseBody(A){return this.bodyCache.parsedBody??=await bZ0(this,A)}#$=(A)=>{let{bodyCache:Q,raw:B}=this,$=Q[A];if($)return $;let w=Object.keys(Q)[0];if(w)return Q[w].then((D)=>{if(w==="json")D=JSON.stringify(D);return new Response(D)[A]()});return Q[A]=B[A]()};json(){return this.#$("text").then((A)=>JSON.parse(A))}text(){return this.#$("text")}arrayBuffer(){return this.#$("arrayBuffer")}blob(){return this.#$("blob")}formData(){return this.#$("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[fZ0](){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 mZ0={Stringify:1,BeforeStream:2,Stream:3},uZ0=(A,Q)=>{let B=new String(A);return B.isEscaped=!0,B.callbacks=Q,B};var TYA=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(w)w[0]+=A;else w=[A];let Y=Promise.all(D.map((X)=>X({phase:Q,buffer:w,context:$}))).then((X)=>Promise.all(X.filter(Boolean).map((I)=>TYA(I,Q,!1,$,w))).then(()=>w[0]));if(B)return uZ0(await Y,D);else return Y};var Ns1="text/plain; charset=UTF-8",xYA=(A,Q)=>{return{"Content-Type":A,...Q}},R_=(A,Q)=>new Response(A,Q),cZ0=class{#A;#Q;env={};#B;finalized=!1;error;#D;#w;#$;#H;#I;#K;#X;#U;#G;constructor(A,Q){if(this.#A=A,Q)this.#w=Q.executionCtx,this.env=Q.env,this.#K=Q.notFoundHandler,this.#G=Q.path,this.#U=Q.matchResult}get req(){return this.#Q??=new Fc(this.#A,this.#G,this.#U),this.#Q}get event(){if(this.#w&&"respondWith"in this.#w)return this.#w;else throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#w)return this.#w;else throw Error("This context has no ExecutionContext")}get res(){return this.#$||=R_(null,{headers:this.#X??=new Headers})}set res(A){if(this.#$&&A){A=R_(A.body,A);for(let[Q,B]of this.#$.headers.entries()){if(Q==="content-type")continue;if(Q==="set-cookie"){let $=this.#$.headers.getSetCookie();A.headers.delete("set-cookie");for(let w of $)A.headers.append("set-cookie",w)}else A.headers.set(Q,B)}}this.#$=A,this.finalized=!0}render=(...A)=>{return this.#I??=(Q)=>this.html(Q),this.#I(...A)};setLayout=(A)=>this.#H=A;getLayout=()=>this.#H;setRenderer=(A)=>{this.#I=A};header=(A,Q,B)=>{if(this.finalized)this.#$=R_(this.#$.body,this.#$);let $=this.#$?this.#$.headers:this.#X??=new Headers;if(Q===void 0)$.delete(A);else if(B?.append)$.append(A,Q);else $.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 $=this.#$?new Headers(this.#$.headers):this.#X??new Headers;if(typeof Q==="object"&&"headers"in Q){let D=Q.headers instanceof Headers?Q.headers:new Headers(Q.headers);for(let[Y,X]of D)if(Y.toLowerCase()==="set-cookie")$.append(Y,X);else $.set(Y,X)}if(B)for(let[D,Y]of Object.entries(B))if(typeof Y==="string")$.set(D,Y);else{$.delete(D);for(let X of Y)$.append(D,X)}let w=typeof Q==="number"?Q:Q?.status??this.#D;return R_(A,{status:w,headers:$})}newResponse=(...A)=>this.#Y(...A);body=(A,Q,B)=>this.#Y(A,Q,B);text=(A,Q,B)=>{return!this.#X&&!this.#D&&!Q&&!B&&!this.finalized?new Response(A):this.#Y(A,Q,xYA(Ns1,B))};json=(A,Q,B)=>{return this.#Y(JSON.stringify(A),Q,xYA("application/json",B))};html=(A,Q,B)=>{let $=(w)=>this.#Y(w,Q,xYA("text/html; charset=UTF-8",B));return typeof A==="object"?TYA(A,mZ0.Stringify,!1,{}).then($):$(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.#K??=()=>R_(),this.#K(this)}};var hB="ALL",lZ0="all",pZ0=["get","post","put","delete","options","patch"],Nc="Can not add a route since the matcher is already built.",Lc=class extends Error{};var vYA="__COMPOSED_HANDLER";var Ls1=(A)=>{return A.text("404 Not Found",404)},dZ0=(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)},iZ0=class A{get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#A="/";routes=[];constructor(Q={}){[...pZ0,lZ0].forEach((D)=>{this[D]=(Y,...X)=>{if(typeof Y==="string")this.#A=Y;else this.#D(D,this.#A,Y);return X.forEach((I)=>{this.#D(D,this.#A,I)}),this}}),this.on=(D,Y,...X)=>{for(let I of[Y].flat()){this.#A=I;for(let K of[D].flat())X.map((G)=>{this.#D(K.toUpperCase(),this.#A,G)})}return this},this.use=(D,...Y)=>{if(typeof D==="string")this.#A=D;else this.#A="*",Y.unshift(D);return Y.forEach((X)=>{this.#D(hB,this.#A,X)}),this};let{strict:$,...w}=Q;Object.assign(this,w),this.getPath=$??!0?Q.getPath??fYA:vZ0}#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=Ls1;errorHandler=dZ0;route(Q,B){let $=this.basePath(Q);return B.routes.map((w)=>{let D;if(B.errorHandler===dZ0)D=w.handler;else D=async(Y,X)=>(await RYA([],B.errorHandler)(Y,()=>w.handler(Y,X))).res,D[vYA]=w.handler;$.#D(w.method,w.path,D)}),this}basePath(Q){let B=this.#Q();return B._basePath=B3(this._basePath,Q),B}onError=(Q)=>{return this.errorHandler=Q,this};notFound=(Q)=>{return this.#B=Q,this};mount(Q,B,$){let w,D;if($)if(typeof $==="function")D=$;else if(D=$.optionHandler,$.replaceRequest===!1)w=(I)=>I;else w=$.replaceRequest;let Y=D?(I)=>{let K=D(I);return Array.isArray(K)?K:[K]}:(I)=>{let K=void 0;try{K=I.executionCtx}catch{}return[I.env,K]};w||=(()=>{let I=B3(this._basePath,Q),K=I==="/"?0:I.length;return(G)=>{let W=new URL(G.url);return W.pathname=W.pathname.slice(K)||"/",new Request(W,G)}})();let X=async(I,K)=>{let G=await B(w(I.req.raw),...Y(I));if(G)return G;await K()};return this.#D(hB,B3(Q,"*"),X),this}#D(Q,B,$){Q=Q.toUpperCase(),B=B3(this._basePath,B);let w={basePath:this._basePath,path:B,method:Q,handler:$};this.router.add(Q,B,[$,w]),this.routes.push(w)}#w(Q,B){if(Q instanceof Error)return this.errorHandler(Q,B);throw Q}#$(Q,B,$,w){if(w==="HEAD")return(async()=>new Response(null,await this.#$(Q,B,$,"GET")))();let D=this.getPath(Q,{env:$}),Y=this.router.match(w,D),X=new cZ0(Q,{path:D,matchResult:Y,env:$,executionCtx:B,notFoundHandler:this.#B});if(Y[0].length===1){let K;try{K=Y[0][0][0][0](X,async()=>{X.res=await this.#B(X)})}catch(G){return this.#w(G,X)}return K instanceof Promise?K.then((G)=>G||(X.finalized?X.res:this.#B(X))).catch((G)=>this.#w(G,X)):K??this.#B(X)}let I=RYA(Y[0],this.errorHandler,this.#B);return(async()=>{try{let K=await I(X);if(!K.finalized)throw Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return K.res}catch(K){return this.#w(K,X)}})()}fetch=(Q,...B)=>{return this.#$(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${B3("/",Q)}`,B),$,w)};fire=()=>{addEventListener("fetch",(Q)=>{Q.respondWith(this.#$(Q.request,Q,void 0,Q.request.method))})}};var P_=[];function Ec(A,Q){let B=this.buildAllMatchers(),$=(w,D)=>{let Y=B[w]||B[hB],X=Y[2][D];if(X)return X;let I=D.match(Y[0]);if(!I)return[[],P_];let K=I.indexOf("",1);return[Y[1][K],I]};return this.match=$,$(A,Q)}var Mc="[^/]+",__=".*",k_="(?:|/.*)",$3=Symbol(),Es1=new Set(".\\+*[^]$()");function Ms1(A,Q){if(A.length===1)return Q.length===1?A<Q?-1:1:-1;if(Q.length===1)return 1;if(A===__||A===k_)return 1;else if(Q===__||Q===k_)return-1;if(A===Mc)return 1;else if(Q===Mc)return-1;return A.length===Q.length?A<Q?-1:1:Q.length-A.length}var rZ0=class A{#A;#Q;#B=Object.create(null);insert(Q,B,$,w,D){if(Q.length===0){if(this.#A!==void 0)throw $3;if(D)return;this.#A=B;return}let[Y,...X]=Q,I=Y==="*"?X.length===0?["","",__]:["","",Mc]:Y==="/*"?["","",k_]:Y.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),K;if(I){let G=I[1],W=I[2]||Mc;if(G&&I[2]){if(W===".*")throw $3;if(W=W.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(W))throw $3}if(K=this.#B[W],!K){if(Object.keys(this.#B).some((Z)=>Z!==__&&Z!==k_))throw $3;if(D)return;if(K=this.#B[W]=new A,G!=="")K.#Q=w.varIndex++}if(!D&&G!=="")$.push([G,K.#Q])}else if(K=this.#B[Y],!K){if(Object.keys(this.#B).some((G)=>G.length>1&&G!==__&&G!==k_))throw $3;if(D)return;K=this.#B[Y]=new A}K.insert(X,B,$,w,D)}buildRegExpStr(){let B=Object.keys(this.#B).sort(Ms1).map(($)=>{let w=this.#B[$];return(typeof w.#Q==="number"?`(${$})@${w.#Q}`:Es1.has($)?`\\${$}`:$)+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 nZ0=class{#A={varIndex:0};#Q=new rZ0;insert(A,Q,B){let $=[],w=[];for(let Y=0;;){let X=!1;if(A=A.replace(/\{[^}]+\}/g,(I)=>{let K=`@\\${Y}`;return w[Y]=[K,I],Y++,X=!0,K}),!X)break}let D=A.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let Y=w.length-1;Y>=0;Y--){let[X]=w[Y];for(let I=D.length-1;I>=0;I--)if(D[I].indexOf(X)!==-1){D[I]=D[I].replace(X,w[Y][1]);break}}return this.#Q.insert(D,Q,$,this.#A,B),$}buildRegExp(){let A=this.#Q.buildRegExpStr();if(A==="")return[/^$/,[],[]];let Q=0,B=[],$=[];return A=A.replace(/#(\d+)|@(\d+)|\.\*\$/g,(w,D,Y)=>{if(D!==void 0)return B[++Q]=Number(D),"$()";if(Y!==void 0)return $[Number(Y)]=++Q,"";return""}),[new RegExp(`^${A}`),B,$]}};var Cs1=[/^$/,[],Object.create(null)],oZ0=Object.create(null);function sZ0(A){return oZ0[A]??=new RegExp(A==="*"?"":`^${A.replace(/\/\*$|([.\\+*[^\]$()])/g,(Q,B)=>B?`\\${B}`:"(?:|/.*)")}$`)}function Os1(){oZ0=Object.create(null)}function js1(A){let Q=new nZ0,B=[];if(A.length===0)return Cs1;let $=A.map((K)=>[!/\*|\/:/.test(K[0]),...K]).sort(([K,G],[W,Z])=>K?1:W?-1:G.length-Z.length),w=Object.create(null);for(let K=0,G=-1,W=$.length;K<W;K++){let[Z,q,N]=$[K];if(Z)w[q]=[N.map(([L])=>[L,Object.create(null)]),P_];else G++;let M;try{M=Q.insert(q,G,Z)}catch(L){throw L===$3?new Lc(q):L}if(Z)continue;B[G]=N.map(([L,_])=>{let T=Object.create(null);_-=1;for(;_>=0;_--){let[P,r]=M[_];T[P]=r}return[L,T]})}let[D,Y,X]=Q.buildRegExp();for(let K=0,G=B.length;K<G;K++)for(let W=0,Z=B[K].length;W<Z;W++){let q=B[K][W]?.[1];if(!q)continue;let N=Object.keys(q);for(let M=0,L=N.length;M<L;M++)q[N[M]]=X[q[N[M]]]}let I=[];for(let K in Y)I[K]=B[Y[K]];return[D,I,w]}function _L(A,Q){if(!A)return;for(let B of Object.keys(A).sort(($,w)=>w.length-$.length))if(sZ0(B).test(Q))return[...A[B]];return}var Cc=class{name="RegExpRouter";#A;#Q;constructor(){this.#A={[hB]:Object.create(null)},this.#Q={[hB]:Object.create(null)}}add(A,Q,B){let $=this.#A,w=this.#Q;if(!$||!w)throw Error(Nc);if(!$[A])[$,w].forEach((X)=>{X[A]=Object.create(null),Object.keys(X[hB]).forEach((I)=>{X[A][I]=[...X[hB][I]]})});if(Q==="/*")Q="*";let D=(Q.match(/\/:/g)||[]).length;if(/\*$/.test(Q)){let X=sZ0(Q);if(A===hB)Object.keys($).forEach((I)=>{$[I][Q]||=_L($[I],Q)||_L($[hB],Q)||[]});else $[A][Q]||=_L($[A],Q)||_L($[hB],Q)||[];Object.keys($).forEach((I)=>{if(A===hB||A===I)Object.keys($[I]).forEach((K)=>{X.test(K)&&$[I][K].push([B,D])})}),Object.keys(w).forEach((I)=>{if(A===hB||A===I)Object.keys(w[I]).forEach((K)=>X.test(K)&&w[I][K].push([B,D]))});return}let Y=Vc(Q)||[Q];for(let X=0,I=Y.length;X<I;X++){let K=Y[X];Object.keys(w).forEach((G)=>{if(A===hB||A===G)w[G][K]||=[..._L($[G],K)||_L($[hB],K)||[]],w[G][K].push([B,D-I+X+1])})}}match=Ec;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,Os1(),A}#B(A){let Q=[],B=A===hB;if([this.#A,this.#Q].forEach(($)=>{let w=$[A]?Object.keys($[A]).map((D)=>[D,$[A][D]]):[];if(w.length!==0)B||=!0,Q.push(...w);else if(A!==hB)Q.push(...Object.keys($[hB]).map((D)=>[D,$[hB][D]]))}),!B)return null;else return js1(Q)}};var Rs1=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(($)=>$&&$.push(Q)),Object.values(B[2]).forEach(($)=>$[0].push(Q))}#D(A,Q,B,$,w){let D=this.#A[A];if(!w)D[2][Q][0].push([B,{}]);else $.forEach((Y)=>{if(typeof Y==="number")D[1][Y].push([B,w]);else D[2][Y||Q][0].push([B,w])})}add(A,Q,B){if(!this.#A[A]){let w=this.#A[hB],D={};for(let Y in w[2])D[Y]=[w[2][Y][0].slice(),P_];this.#A[A]=[w[0],w[1].map((Y)=>Array.isArray(Y)?Y.slice():0),D]}if(Q==="/*"||Q==="*"){let w=[B,{}];if(A===hB)for(let D in this.#A)this.#B(D,w);else this.#B(A,w);return}let $=this.#Q[Q];if(!$)throw Error(`Path ${Q} is not registered`);for(let[w,D]of $)if(A===hB)for(let Y in this.#A)this.#D(Y,Q,B,w,D);else this.#D(A,Q,B,w,D)}buildAllMatchers(){return this.#A}match=Ec};var SYA=class{name="SmartRouter";#A=[];#Q=[];constructor(A){this.#A=A.routers}add(A,Q,B){if(!this.#Q)throw Error(Nc);this.#Q.push([A,Q,B])}match(A,Q){if(!this.#Q)throw Error("Fatal error");let B=this.#A,$=this.#Q,w=B.length,D=0,Y;for(;D<w;D++){let X=B[D];try{for(let I=0,K=$.length;I<K;I++)X.add(...$[I]);Y=X.match(A,Q)}catch(I){if(I instanceof Lc)continue;throw I}this.match=X.match.bind(X),this.#A=[X],this.#Q=void 0;break}if(D===w)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 f_=Object.create(null),Ps1=(A)=>{for(let Q in A)return!0;return!1},aZ0=class A{#A;#Q;#B;#D=0;#w=f_;constructor(Q,B,$){if(this.#Q=$||Object.create(null),this.#A=[],Q&&B){let w=Object.create(null);w[Q]={handler:B,possibleKeys:[],score:0},this.#A=[w]}this.#B=[]}insert(Q,B,$){this.#D=++this.#D;let w=this,D=TZ0(B),Y=[];for(let X=0,I=D.length;X<I;X++){let K=D[X],G=D[X+1],W=xZ0(K,G),Z=Array.isArray(W)?W[0]:K;if(Z in w.#Q){if(w=w.#Q[Z],W)Y.push(W[1]);continue}if(w.#Q[Z]=new A,W)w.#B.push(W),Y.push(W[1]);w=w.#Q[Z]}return w.#A.push({[Q]:{handler:$,possibleKeys:Y.filter((X,I,K)=>K.indexOf(X)===I),score:this.#D}}),w}#$(Q,B,$,w,D){for(let Y=0,X=B.#A.length;Y<X;Y++){let I=B.#A[Y],K=I[$]||I[hB],G={};if(K!==void 0){if(K.params=Object.create(null),Q.push(K),w!==f_||D&&D!==f_)for(let W=0,Z=K.possibleKeys.length;W<Z;W++){let q=K.possibleKeys[W],N=G[K.score];K.params[q]=D?.[q]&&!N?D[q]:w[q]??D?.[q],G[K.score]=!0}}}}search(Q,B){let $=[];this.#w=f_;let D=[this],Y=_YA(B),X=[],I=Y.length,K=null;for(let G=0;G<I;G++){let W=Y[G],Z=G===I-1,q=[];for(let M=0,L=D.length;M<L;M++){let _=D[M],T=_.#Q[W];if(T)if(T.#w=_.#w,Z){if(T.#Q["*"])this.#$($,T.#Q["*"],Q,_.#w);this.#$($,T,Q,_.#w)}else q.push(T);for(let P=0,r=_.#B.length;P<r;P++){let n=_.#B[P],g=_.#w===f_?{}:{..._.#w};if(n==="*"){let c=_.#Q["*"];if(c)this.#$($,c,Q,_.#w),c.#w=g,q.push(c);continue}let[x,S,h]=n;if(!W&&!(h instanceof RegExp))continue;let t=_.#Q[x];if(h instanceof RegExp){if(K===null){K=Array(I);let XA=B[0]==="/"?1:0;for(let k=0;k<I;k++)K[k]=XA,XA+=Y[k].length+1}let c=B.substring(K[G]),UA=h.exec(c);if(UA){if(g[S]=UA[0],this.#$($,t,Q,_.#w,g),Ps1(t.#Q)){t.#w=g;let XA=UA[0].match(/\//)?.length??0;(X[XA]||=[]).push(t)}continue}}if(h===!0||h.test(W))if(g[S]=W,Z){if(this.#$($,t,Q,g,_.#w),t.#Q["*"])this.#$($,t.#Q["*"],Q,g,_.#w)}else t.#w=g,q.push(t)}}let N=X.shift();D=N?q.concat(N):q}if($.length>1)$.sort((G,W)=>{return G.score-W.score});return[$.map(({handler:G,params:W})=>[G,W])]}};var hYA=class{name="TrieRouter";#A;constructor(){this.#A=new aZ0}add(A,Q,B){let $=Vc(Q);if($){for(let w=0,D=$.length;w<D;w++)this.#A.insert(A,$[w],B);return}this.#A.insert(A,Q,B)}match(A,Q){return this.#A.search(A,Q)}};var kL=class extends iZ0{constructor(A={}){super(A);this.router=A.router??new SYA({routers:[new Cc,new hYA]})}};import{stat as Ts1}from"fs/promises";import{join as xs1}from"path";var fL=/^\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 gYA=(A,Q=ks1)=>{let B=/\.([a-zA-Z0-9]+?)$/,$=A.match(B);if(!$)return;let w=Q[$[1]];if(w&&w.startsWith("text"))w+="; charset=utf-8";return w};var _s1={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"},ks1=_s1;var tZ0=(...A)=>{let Q=A.filter((w)=>w!=="").join("/");Q=Q.replace(/(?<=\/)\/+/g,"");let B=Q.split("/"),$=[];for(let w of B)if(w===".."&&$.length>0&&$.at(-1)!=="..")$.pop();else if(w!==".")$.push(w);return $.join("/")||"."};var eZ0={br:".br",zstd:".zst",gzip:".gz"},fs1=Object.keys(eZ0),bs1="index.html",AF0=(A)=>{let Q=A.root??"./",B=A.path,$=A.join??tZ0;return async(w,D)=>{if(w.finalized)return D();let Y;if(A.path)Y=A.path;else try{if(Y=kYA(w.req.path),/(?:^|[\/\\])\.\.(?:$|[\/\\])/.test(Y))throw Error()}catch{return await A.onNotFound?.(w.req.path,w),D()}let X=$(Q,!B&&A.rewriteRequestPath?A.rewriteRequestPath(Y):Y);if(A.isDir&&await A.isDir(X))X=$(X,bs1);let I=A.getContent,K=await I(X,w);if(K instanceof Response)return w.newResponse(K.body,K);if(K){let G=A.mimes&&gYA(X,A.mimes)||gYA(X);if(w.header("Content-Type",G||"application/octet-stream"),A.precompressed&&(!G||fL.test(G))){let W=new Set(w.req.header("Accept-Encoding")?.split(",").map((Z)=>Z.trim()));for(let Z of fs1){if(!W.has(Z))continue;let q=await I(X+eZ0[Z],w);if(q){K=q,w.header("Content-Encoding",Z),w.header("Vary","Accept-Encoding",{append:!0});break}}}return await A.onFound?.(X,w),w.body(K)}await A.onNotFound?.(X,w),await D();return}};var yYA=(A)=>{return async function(B,$){return AF0({...A,getContent:async(Y)=>{let X=Bun.file(Y);return await X.exists()?X:null},join:xs1,isDir:async(Y)=>{let X;try{X=(await Ts1(Y)).isDirectory()}catch{}return X}})(B,$)}};var mYA="x-hono-disable-ssg",Rk2=(()=>{try{return new Response("SSG is disabled",{status:404,headers:{[mYA]:"true"}})}catch{return null}})();var{write:If2}=Bun;var hs1=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 QF0=(A)=>{return(...Q)=>{if(typeof Q[0]==="function"){let[B,$]=Q;return async function(D,Y){let X=await B(D),I=await A(D,X,$);if(I)return I;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 Oc=(A)=>("server"in A.env)?A.env.server:A.env;var gs1=QF0((A,Q)=>{let B=Oc(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 ys1=["gzip","deflate"],ms1=/(?:^|,)\s*?no-transform\s*?(?:,|$)/i,BF0=(A)=>{let Q=A?.threshold??1024;return async function($,w){await w();let D=$.res.headers.get("Content-Length");if($.res.headers.has("Content-Encoding")||$.res.headers.has("Transfer-Encoding")||$.req.method==="HEAD"||D&&Number(D)<Q||!us1($.res)||!cs1($.res))return;let Y=$.req.header("Accept-Encoding"),X=A?.encoding??ys1.find((K)=>Y?.includes(K));if(!X||!$.res.body)return;let I=new CompressionStream(X);$.res=new Response($.res.body.pipeThrough(I),$.res),$.res.headers.delete("Content-Length"),$.res.headers.set("Content-Encoding",X)}},us1=(A)=>{let Q=A.headers.get("Content-Type");return Q&&fL.test(Q)},cs1=(A)=>{let Q=A.headers.get("Cache-Control");return!Q||!ms1.test(Q)};import{Readable as $F0}from"stream";import{createDeflate as ls1,createGzip as ps1}from"zlib";var ds1=["gzip","deflate"],is1=/(?:^|,)\s*?no-transform\s*?(?:,|$)/i,wF0=(A)=>{if(typeof CompressionStream<"u")return BF0(A);let Q=A?.threshold??1024;return async function($,w){await w();let D=$.res.headers.get("Content-Length");if($.res.headers.has("Content-Encoding")||$.res.headers.has("Transfer-Encoding")||$.req.method==="HEAD"||D&&Number(D)<Q||!rs1($.res)||!ns1($.res))return;let Y=$.req.header("Accept-Encoding"),X=A?.encoding??ds1.find((I)=>Y?.includes(I));if(!X||!$.res.body)return;try{let I=X==="gzip"?ps1():ls1(),K=$.res.body,W=$F0.fromWeb(K).pipe(I),Z=$F0.toWeb(W);$.res=new Response(Z,$.res),$.res.headers.delete("Content-Length"),$.res.headers.set("Content-Encoding",X)}catch(I){console.error("Compression error:",I)}}},rs1=(A)=>{let Q=A.headers.get("Content-Type");return Q&&fL.test(Q)},ns1=(A)=>{let Q=A.headers.get("Cache-Control");return!Q||!is1.test(Q)};var os1=(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},DF0=async(A,Q)=>{if(!A)return null;let B=void 0,$=A.getReader();for(;;){let{value:w,done:D}=await $.read();if(D)break;B=await Q(os1(B,w))}if(!B)return null;return Array.prototype.map.call(new Uint8Array(B),(w)=>w.toString(16).padStart(2,"0")).join("")};var ss1=["cache-control","content-location","date","etag","expires","vary"],YF0=(A)=>A.replace(/^W\//,"");function as1(A,Q){return Q!=null&&Q.split(/,\s*/).some((B)=>YF0(B)===YF0(A))}function ts1(A){if(!A){if(crypto&&crypto.subtle)A=(Q)=>crypto.subtle.digest({name:"SHA-1"},Q)}return A}var XF0=(A)=>{let Q=A?.retainedHeaders??ss1,B=A?.weak??!1,$=ts1(A?.generateDigest);return async function(D,Y){let X=D.req.header("If-None-Match")??null;await Y();let I=D.res,K=I.headers.get("ETag");if(!K){if(!$)return;let G=await DF0(I.clone().body,$);if(G===null)return;K=B?`W/"${G}"`:`"${G}"`}if(as1(K,X))D.res=new Response(null,{status:304,statusText:"Not Modified",headers:{ETag:K}}),D.res.headers.forEach((G,W)=>{if(Q.indexOf(W.toLowerCase())===-1)D.res.headers.delete(W)});else D.res.headers.set("ETag",K)}};w0();function jc(A,Q){return async(B)=>{let $=B.req.raw,w=$.headers.get("content-type")??"",D=$.headers.get("accept")?.includes("application/json"),Y={};if(w.includes("application/json"))Y=await $.json();else if(w.includes("form")){let q=await $.formData();for(let[N,M]of q.entries())Y[N]=M}let X=`${A.pluginId}_${A.definition.tool}`,I=await Q.send(`plugin:${A.pluginId}:tool:execute`,{toolName:X,args:Y,interfaceType:"webserver",userId:"anonymous"},"webserver"),K=typeof I==="object"&&"data"in I?I.data:I,G=aC.safeParse(K),W=G.success?G.data:K,Z=G.success&&G.data.success===!0;if(D)return B.json(W,Z?200:400);if(Z&&A.definition.successRedirect)return B.redirect(A.definition.successRedirect);if(!Z&&A.definition.errorRedirect)return B.redirect(A.definition.errorRedirect);return B.json(W,Z?200:400)}}var IF0="public, max-age=31536000, immutable";class Rc{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:bL(process.cwd(),A.productionDistDir),sharedImagesDir:bL(process.cwd(),A.sharedImagesDir),...A.previewDistDir&&{previewDistDir:bL(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 $=await this.serveImageFastPath(B);if($)return $;if(Q&&this.isPreviewHost(B.headers.get("host")))return Q.fetch(B);return A.fetch(B)}})}catch(B){let $=String(B);if($.includes("EADDRINUSE")||$.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 kL;if(A.healthEndpoint)Q.get("/health",async(B)=>{if(this.options.getHealthData){let $=await this.options.getHealthData();return B.json({status:"healthy",...$},200)}return B.json({status:"healthy"},200)});if(A.healthEndpoint&&this.options.webRoutes)for(let B of this.options.webRoutes){let $=(w)=>B.definition.handler(w.req.raw);switch(B.definition.method??"GET"){case"POST":Q.post(B.fullPath,$);break;case"PUT":Q.put(B.fullPath,$);break;case"DELETE":Q.delete(B.fullPath,$);break;case"OPTIONS":Q.options(B.fullPath,$);break;case"GET":default:Q.get(B.fullPath,$);break}}if(A.healthEndpoint&&this.options.apiRoutes&&this.options.messageBus)for(let B of this.options.apiRoutes){let $=jc(B,this.options.messageBus),w=B.definition.method.toLowerCase();Q[w](B.fullPath,$)}if(A.compress)Q.use("/*",wF0());return Q.use("/*",XF0()),Q.use("/*",async(B,$)=>{if(await $(),A.immutableExtensions.test(B.req.path))B.header("Cache-Control",IF0);else B.header("Cache-Control",A.defaultCache)}),Q.use("/*",this.createCleanUrlMiddleware(A.distDir)),Q.use("/*",yYA({root:A.distDir})),Q.notFound(async(B)=>{let $=Bun.file(es1(A.distDir,"404.html"));if(await $.exists())return B.html(await $.text(),404);return B.text("Not Found",404)}),Q}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),$=bL(this.options.sharedImagesDir,B);if(!$.startsWith(this.options.sharedImagesDir))return null;let w=Bun.file($);if(!await w.exists())return null;return new Response(w,{headers:{"Cache-Control":IF0}})}createCleanUrlMiddleware(A){return async(Q,B)=>{let $=Q.req.path;if($.includes(".")||$==="/"){await B();return}let w=bL(A,`.${$}`,"index.html");if(!w.startsWith(A)){await B();return}let D=Bun.file(w);if(await D.exists())return Q.html(await D.text());let Y=bL(A,`.${$}.html`);if(Y.startsWith(A)){let X=Bun.file(Y);if(await X.exists())return Q.html(await X.text())}await B()}}}import{existsSync as HF0}from"fs";import{join as UF0}from"path";ZA();var uYA=F.object({enablePreview:F.boolean().default(!0).describe("Enable the preview site server when preview assets are configured"),previewDistDir:F.string().default("./dist/site-preview").describe("Directory for preview site files"),productionDistDir:F.string().describe("Directory for production site files").default("./dist/site-production"),sharedImagesDir:F.string().default("./dist/images").describe("Shared directory for optimized images"),previewPort:F.number().default(4321).describe("Port for preview server"),productionPort:F.number().describe("Port for production server").default(8080),apiPort:F.number().describe("Port for API route server (plugin HTTP endpoints)").default(3335)});var cYA=`<!DOCTYPE html>
1579
1579
  <html lang="en">
@@ -1642,7 +1642,7 @@ ${A.entityContent}`,lW1);I=$+_.imagePrompt}catch(_){this.logger.warn("AI prompt
1642
1642
  <p>Once built, this page will be replaced with your actual website.</p>
1643
1643
  </div>
1644
1644
  </body>
1645
- </html>`;var KF0={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.31",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 EJ extends bX{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",KF0,A,uYA)}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 Rc({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(),webRoutes:A.webRoutes.getRoutes(),apiRoutes: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}`,$=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,w=[];if(Q){if(w.push(`Production: ${B}`),A?.previewUrl)w.push(`Preview: ${$}`)}return{status:Q?"healthy":"error",message:Q?w.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?$: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&&!HF0(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(UF0(this.config.previewDistDir,"index.html"),cYA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!HF0(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(UF0(this.config.productionDistDir,"index.html"),cYA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}w0();ZA();var GF0=F.object({port:F.number().default(3334),organization:F.string().optional(),trustedTokens:F.record(F.string()).optional(),outboundTokens:F.record(F.string()).optional()});w0();function Qa1(A,Q){return`${A.name} is ${Q.name}'s ${A.role}. Its purpose is: ${A.purpose}.`}function JF0(A){let{character:Q,profile:B,version:$,domain:w,organization:D,tools:Y}=A,I=`${A.baseUrl??(w?`https://${w}`:"http://localhost:8080")}/a2a`,K=A.skills&&A.skills.length>0?A.skills.map((Z)=>({id:Z.name.toLowerCase().replace(/\s+/g,"-"),name:Z.name,description:Z.description,tags:Z.tags,examples:Z.examples})):Y.map((Z)=>({id:Z.name,name:Z.name,description:Z.description,tags:[],examples:[]})),G={name:B.name};if(A.kind)G.kind=A.kind;if(B.description)G.description=B.description;if(D)G.organization=D;let W=[{uri:mv,description:"Anchor (operator) identity for this brain",params:G}];return{name:Q.name,description:Qa1(Q,B),url:I,version:$,protocolVersion:"0.2.2",capabilities:{streaming:!0,pushNotifications:!1,extensions:W},skills:K,defaultInputModes:["text/plain"],defaultOutputModes:["text/plain"],...D&&{provider:{organization:D,url:I}},...A.authEnabled&&{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer"}},security:[{bearerAuth:[]}]}}}w0();var lYA=new Set(["completed","failed","canceled","rejected"]);class pYA{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(lYA.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(),$=Q??crypto.randomUUID(),w=new Date().toISOString(),D={kind:"message",messageId:crypto.randomUUID(),role:"user",parts:[{kind:"text",text:A}],contextId:$,taskId:B},X={task:{id:B,contextId:$,kind:"task",status:{state:"submitted",timestamp:w},history:[D]},conversationId:`a2a:${B}`,createdAt:w,updatedAt:w};return this.tasks.set(B,X),X}getTask(A){return this.tasks.get(A)}updateState(A,Q,B){let $=this.tasks.get(A);if(!$)return;let w=new Date().toISOString();if($.task.status={state:Q,timestamp:w},$.updatedAt=w,Q==="working")$.workingStartedAt=w;if(B){let D={kind:"message",messageId:crypto.randomUUID(),role:"agent",parts:[{kind:"text",text:B}],contextId:$.task.contextId,taskId:A};$.task.status.message=D,$.task.history??=[],$.task.history.push(D)}return $}addArtifact(A,Q,B){let $=this.tasks.get(A);if(!$)return;return $.task.artifacts??=[],$.task.artifacts.push({artifactId:crypto.randomUUID(),name:Q,parts:B}),$.updatedAt=new Date().toISOString(),$}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}}ZA();var WF0=F.array(F.object({kind:F.string(),text:F.string().optional(),data:F.record(F.unknown()).optional()})),Ba1=F.object({message:F.object({kind:F.literal("message").optional(),messageId:F.string().optional(),role:F.enum(["user","agent"]).optional(),parts:WF0,contextId:F.string().optional(),taskId:F.string().optional()}),configuration:F.object({historyLength:F.number().optional()}).optional()}),ZF0=F.object({id:F.string(),historyLength:F.number().optional()});function dYA(A,Q){return{jsonrpc:"2.0",id:A,result:Q}}function II(A,Q,B){return{jsonrpc:"2.0",id:A,error:{code:Q,message:B}}}var FF0=F.object({jsonrpc:F.string(),id:F.union([F.string(),F.number()]),method:F.string(),params:F.record(F.unknown()).optional()});async function qF0(A,Q){let{id:B,method:$,params:w}=A;switch($){case"message/send":return $a1(B,w??{},Q);case"tasks/get":return Da1(B,w??{},Q);case"tasks/cancel":return Ya1(B,w??{},Q);default:return II(B,-32601,`Method not found: ${$}`)}}async function $a1(A,Q,B){let $=Ba1.safeParse(Q);if(!$.success)return II(A,-32602,`Invalid params: ${$.error.message}`);let w=$.data.message.parts.filter((G)=>G.kind==="text"&&typeof G.text==="string");if(w.length===0)return II(A,-32602,"Message must contain at least one text part");let D=w.map((G)=>G.text).join(`
1645
+ </html>`;var KF0={name:"@brains/webserver",private:!0,version:"0.2.0-alpha.32",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 EJ extends bX{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",KF0,A,uYA)}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 Rc({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(),webRoutes:A.webRoutes.getRoutes(),apiRoutes: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}`,$=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,w=[];if(Q){if(w.push(`Production: ${B}`),A?.previewUrl)w.push(`Preview: ${$}`)}return{status:Q?"healthy":"error",message:Q?w.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?$: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&&!HF0(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(UF0(this.config.previewDistDir,"index.html"),cYA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!HF0(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(UF0(this.config.productionDistDir,"index.html"),cYA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}w0();ZA();var GF0=F.object({port:F.number().default(3334),organization:F.string().optional(),trustedTokens:F.record(F.string()).optional(),outboundTokens:F.record(F.string()).optional()});w0();function Qa1(A,Q){return`${A.name} is ${Q.name}'s ${A.role}. Its purpose is: ${A.purpose}.`}function JF0(A){let{character:Q,profile:B,version:$,domain:w,organization:D,tools:Y}=A,I=`${A.baseUrl??(w?`https://${w}`:"http://localhost:8080")}/a2a`,K=A.skills&&A.skills.length>0?A.skills.map((Z)=>({id:Z.name.toLowerCase().replace(/\s+/g,"-"),name:Z.name,description:Z.description,tags:Z.tags,examples:Z.examples})):Y.map((Z)=>({id:Z.name,name:Z.name,description:Z.description,tags:[],examples:[]})),G={name:B.name};if(A.kind)G.kind=A.kind;if(B.description)G.description=B.description;if(D)G.organization=D;let W=[{uri:mv,description:"Anchor (operator) identity for this brain",params:G}];return{name:Q.name,description:Qa1(Q,B),url:I,version:$,protocolVersion:"0.2.2",capabilities:{streaming:!0,pushNotifications:!1,extensions:W},skills:K,defaultInputModes:["text/plain"],defaultOutputModes:["text/plain"],...D&&{provider:{organization:D,url:I}},...A.authEnabled&&{securitySchemes:{bearerAuth:{type:"http",scheme:"bearer"}},security:[{bearerAuth:[]}]}}}w0();var lYA=new Set(["completed","failed","canceled","rejected"]);class pYA{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(lYA.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(),$=Q??crypto.randomUUID(),w=new Date().toISOString(),D={kind:"message",messageId:crypto.randomUUID(),role:"user",parts:[{kind:"text",text:A}],contextId:$,taskId:B},X={task:{id:B,contextId:$,kind:"task",status:{state:"submitted",timestamp:w},history:[D]},conversationId:`a2a:${B}`,createdAt:w,updatedAt:w};return this.tasks.set(B,X),X}getTask(A){return this.tasks.get(A)}updateState(A,Q,B){let $=this.tasks.get(A);if(!$)return;let w=new Date().toISOString();if($.task.status={state:Q,timestamp:w},$.updatedAt=w,Q==="working")$.workingStartedAt=w;if(B){let D={kind:"message",messageId:crypto.randomUUID(),role:"agent",parts:[{kind:"text",text:B}],contextId:$.task.contextId,taskId:A};$.task.status.message=D,$.task.history??=[],$.task.history.push(D)}return $}addArtifact(A,Q,B){let $=this.tasks.get(A);if(!$)return;return $.task.artifacts??=[],$.task.artifacts.push({artifactId:crypto.randomUUID(),name:Q,parts:B}),$.updatedAt=new Date().toISOString(),$}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}}ZA();var WF0=F.array(F.object({kind:F.string(),text:F.string().optional(),data:F.record(F.unknown()).optional()})),Ba1=F.object({message:F.object({kind:F.literal("message").optional(),messageId:F.string().optional(),role:F.enum(["user","agent"]).optional(),parts:WF0,contextId:F.string().optional(),taskId:F.string().optional()}),configuration:F.object({historyLength:F.number().optional()}).optional()}),ZF0=F.object({id:F.string(),historyLength:F.number().optional()});function dYA(A,Q){return{jsonrpc:"2.0",id:A,result:Q}}function II(A,Q,B){return{jsonrpc:"2.0",id:A,error:{code:Q,message:B}}}var FF0=F.object({jsonrpc:F.string(),id:F.union([F.string(),F.number()]),method:F.string(),params:F.record(F.unknown()).optional()});async function qF0(A,Q){let{id:B,method:$,params:w}=A;switch($){case"message/send":return $a1(B,w??{},Q);case"tasks/get":return Da1(B,w??{},Q);case"tasks/cancel":return Ya1(B,w??{},Q);default:return II(B,-32601,`Method not found: ${$}`)}}async function $a1(A,Q,B){let $=Ba1.safeParse(Q);if(!$.success)return II(A,-32602,`Invalid params: ${$.error.message}`);let w=$.data.message.parts.filter((G)=>G.kind==="text"&&typeof G.text==="string");if(w.length===0)return II(A,-32602,"Message must contain at least one text part");let D=w.map((G)=>G.text).join(`
1646
1646
  `),Y=$.data.message.contextId,X=B.taskManager.createTask(D,Y),I=X.task.id;B.taskManager.updateState(I,"working"),wa1(I,D,X.conversationId,B);let K=B.taskManager.getTask(I);if(!K)return II(A,-32603,"Internal error: task disappeared");return dYA(A,K.task)}function wa1(A,Q,B,$){$.agentService.chat(Q,B,{userPermissionLevel:$.callerPermissionLevel,interfaceType:"a2a"}).then((w)=>{$.taskManager.updateState(A,"completed",w.text)}).catch((w)=>{let D=w instanceof Error?w.message:"Unknown error";$.taskManager.updateState(A,"failed",`Error: ${D}`)})}var zF0=F.object({message:F.object({kind:F.string(),parts:WF0,contextId:F.string().optional()})});function VF0(A,Q,B){let w=Q.parts.filter((K)=>K.kind==="text"&&typeof K.text==="string").map((K)=>K.text).join(`
1647
1647
  `)||"No message text",D=B.taskManager.createTask(w,Q.contextId),Y=D.task.id;B.taskManager.updateState(Y,"working");let X=new TextEncoder,I=new ReadableStream({start(K){let G=!1;function W(M){if(G)return;try{K.enqueue(X.encode(`data: ${JSON.stringify(M)}
1648
1648
 
@@ -1650,7 +1650,7 @@ ${A.entityContent}`,lW1);I=$+_.imagePrompt}catch(_){this.logger.warn("AI prompt
1650
1650
 
1651
1651
  `);$=D.pop()??"";for(let Y of D){let X=Y.split(`
1652
1652
  `).find((M)=>M.startsWith("data: "));if(!X)continue;let K=JSON.parse(X.slice(6)).result;if(!K)continue;if(K.final!==!0)continue;Q.cancel().catch(()=>{});let W=K.status,Z=W?.state??"unknown",N=(W?.message?.parts??[]).filter((M)=>M.kind==="text"&&typeof M.text==="string").map((M)=>M.text).join(`
1653
- `)||"No response text";return{success:!0,data:{state:Z,response:N}}}w=await Q.read()}return{success:!1,error:"Stream ended without a terminal event"}}function EF0(A={}){let Q=A.fetch??globalThis.fetch;return{name:"a2a_call",description:"Call a remote A2A agent. Discovers the agent via its Agent Card, sends a message, and returns the response.",inputSchema:NF0,visibility:"anchor",handler:async(B)=>{let $=F.object(NF0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:w,message:D}=$.data,Y=w,X=w.startsWith("http://")||w.startsWith("https://");if(!X&&A.entityService){let Z=await A.entityService.getEntity("agent",w);if(Z){if(Z.metadata.status==="archived")return{success:!1,error:`Agent ${w} is archived. Use agent_add to re-activate.`};let q=Z.metadata.url;if(typeof q==="string")Y=q}}if(!Y.startsWith("http"))Y=`https://${Y}`;let I=await Xa1(Y,Q);if(!I)return{success:!1,error:`Could not fetch Agent Card from ${Y}`};let K=I.url,G;if(A.outboundTokens)try{let Z=new URL(K).hostname;G=A.outboundTokens[Z]}catch{}let W=await Ia1(K,D,Q,G);if("success"in W&&W.success&&X&&A.sendMessage){let Z=new URL(K).hostname;A.sendMessage("a2a:call:completed",{domain:Z}).catch(()=>{})}return W}}}var iYA={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.31",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 Ua1={"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 bX{agentCard;unsubscribeReady;unsubscribeSyncCompleted;taskManager=new pYA;agentService;permissionContext;app;constructor(A={}){super("a2a",iYA,A,GF0)}async onRegister(A){if(await super.onRegister(A),!A.plugins.has("webserver"))throw Error("A2A requires the webserver interface. Standalone HTTP listeners have been removed.");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.logger.info("A2A interface registered",{domain:A.domain})}async rebuildAgentCard(A){let Q=A.identity.get(),B=A.identity.getProfile(),$=A.tools.listForPermissionLevel("public"),w=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((X)=>wV.safeParse(X.metadata)).filter((X)=>X.success).map((X)=>X.data)}catch{}this.agentCard=JF0({character:Q,profile:B,version:iYA.version,domain:A.domain,organization:this.config.organization,tools:$,skills:D,authEnabled:w}),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,$]of Object.entries(Ua1))Q.set(B,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new kL;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 $=FF0.safeParse(B);if(!$.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));let w=this.resolveCallerPermission(Q.req.header("Authorization"));if($.data.method==="message/stream"){let Y=zF0.safeParse($.data.params??{});if(!Y.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Y.error.message}`},id:$.data.id}));let{stream:X}=VF0($.data.id,Y.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:w});return this.withCors(new Response(X,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let D=await qF0($.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:w});return this.withCors(Q.json(D))}),this.app=A,A}getWebRoutes(){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[EF0({outboundTokens:this.config.outboundTokens,entityService:this.getContext().entityService,sendMessage:(A,Q)=>this.getContext().messaging.send(A,Q)})]}createDaemon(){return{start:async()=>{this.logger.info("A2A mounted on shared webserver host")},stop:async()=>{this.unsubscribeReady?.(),this.unsubscribeSyncCompleted?.(),this.logger.info("A2A server stopped")}}}}w0();w0();class rYA{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=[],$=this.createImportOperations(A);B.push(...$);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:w,totalFiles:D}),{operations:B,exportOperationsCount:0,importOperationsCount:w,totalFiles:D}}async queueSyncBatch(A,Q,B,$,w){let D=this.prepareBatchOperations(B,w);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:$?.rootJobId??j6(),metadata:{progressToken:$?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:$?.pluginId??"directory-sync",interfaceType:$?.interfaceType,channelId:$?.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 $=0;$<A.length;$+=Q){let w=A.slice($,$+Q);B.push({type:"directory-import",data:{batchIndex:Math.floor($/Q),paths:w,batchSize:w.length}})}return B}}ZA();import{resolve as C1Q,isAbsolute as O1Q}from"path";import{mkdir as j1Q}from"fs/promises";var cq0=o0(hq0(),1);d4();import{join as KI,dirname as K1Q,extname as nc}from"path";import{mkdir as iXA,readFile as rc,writeFile as gq0,readdir as H1Q,stat as yq0,utimes as U1Q,access as G1Q}from"fs/promises";var d_=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function mq0(A){let Q=nc(A).toLowerCase();return d_.includes(Q)}function J1Q(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 uq0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}async function mL(A){try{return await G1Q(A),!0}catch{return!1}}class rXA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){let $=(A.startsWith(this.syncPath)?A:KI(this.syncPath,A)).replace(this.syncPath+"/","").split("/"),w,D;if($.length===1)w="base",D=$;else if($.length>1&&$[0])w=$[0],D=$.slice(1);else w="base",D=$;let Y;if(D.length>1){let X=D[D.length-1];if(X){let I=nc(X).toLowerCase(),K=I===".md"||d_.includes(I)?X.slice(0,-I.length):X;D[D.length-1]=K}Y=D.join(":")}else{let X=D[0]??"",I=nc(X).toLowerCase();Y=I===".md"||d_.includes(I)?X.slice(0,-I.length):X}return{entityType:w,id:Y}}async readEntity(A){let Q=A.startsWith(this.syncPath)?A:KI(this.syncPath,A),B=await yq0(Q),{entityType:$,id:w}=this.parseEntityFromPath(A),D=B.birthtime.getTime()>0?B.birthtime:B.mtime,Y=B.mtime,X;if(mq0(A)){let K=(await rc(Q)).toString("base64"),G=nc(A);X=`data:${J1Q(G)};base64,${K}`}else X=await rc(Q,"utf-8");return{entityType:$,id:w,content:X,created:D,updated:Y}}async writeEntity(A){let Q=this.getEntityFilePath(A),B=A.entityType==="image",$;if(B){let D=A.content.match(/^data:image\/[a-z+]+;base64,(.+)$/i);$=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64")}else $=this.entityService.serializeEntity(A);if(await mL(Q)){let D=B?await rc(Q):await rc(Q,"utf-8"),Y=nB(B?D.toString("base64"):D),X=nB(B?$.toString("base64"):$);if(Y===X)return}if(A.entityType!=="base")await iXA(K1Q(Q),{recursive:!0});if(B)await gq0(Q,$);else await gq0(Q,$,"utf-8");let w=new Date(A.updated);await U1Q(Q,w,w)}getFilePath(A,Q,B=".md"){let $=A.split(":").filter((I)=>I.length>0),w=Q==="base";if($.length===1)return w?KI(this.syncPath,`${$[0]}${B}`):KI(this.syncPath,Q,`${$[0]}${B}`);let D=$;if($[0]===Q)D=$.slice(1);let Y=D[D.length-1],X=D.slice(0,-1);if(w)return KI(this.syncPath,...X,`${Y}${B}`);else return KI(this.syncPath,Q,...X,`${Y}${B}`)}getEntityFilePath(A){let Q=".md";if(A.entityType==="image"){let B=A.metadata.format;if(B)Q=uq0(B);else{let $=A.content.match(/^data:image\/([a-z+]+);base64,/i);if($?.[1])Q=uq0($[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 mL(this.syncPath))return Q;let B=async($,w="",D=!1)=>{let Y=await H1Q($,{withFileTypes:!0});for(let X of Y){let I=w?KI(w,X.name):X.name;if(X.isFile()&&!X.name.endsWith(".invalid")){if(X.name.endsWith(".md"))Q.push(I);else if(A.includeImages&&D&&mq0(X.name))Q.push(I)}else if(X.isDirectory()&&!X.name.startsWith(".")){if(w===""&&!this.entityService.hasEntityType(X.name))continue;let K=KI($,X.name),G=X.name==="image"&&w==="";await B(K,I,D||G)}}};return await B(this.syncPath),Q}async ensureDirectoryStructure(A){if(!await mL(this.syncPath))await iXA(this.syncPath,{recursive:!0});for(let Q of A)if(Q!=="base")await iXA(KI(this.syncPath,Q),{recursive:!0})}shouldUpdateEntity(A,Q){let B=nB(Q.content);return A.contentHash!==B}async gatherFileStatus(){let A=[],Q={totalFiles:0,byEntityType:{}};if(!await mL(this.syncPath))return{files:A,stats:Q};let B=await this.getAllMarkdownFiles();for(let $ of B)try{let w=KI(this.syncPath,$),D=await yq0(w),{entityType:Y}=this.parseEntityFromPath($);A.push({path:$,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 mL(this.syncPath)}async fileExists(A){return mL(A)}}function W1Q(A,Q){if(!A.replace(Q+"/","").startsWith("image/"))return!1;return d_.some(($)=>A.toLowerCase().endsWith($))}function Z1Q(A,Q){if(A.replace(Q+"/","").split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return W1Q(A,Q)}class nXA{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=cq0.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(!Z1Q(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 $=`${this.syncPath}/${Q}`;try{if(this.onFileChange)await this.onFileChange(B,$)}catch(w){this.logger.error("Error processing file change",{path:Q,event:B,error:w})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}class oXA{logger;entityService;fileOperations;constructor(A,Q,B){this.logger=A,this.entityService=Q,this.fileOperations=B}async importEntitiesWithProgress(A,Q,B,$){this.logger.debug("Importing entities with progress reporting");let w={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 X=0;X<Y;X+=B){let I=D.slice(X,X+B),K=await $(I);w.imported+=K.imported,w.skipped+=K.skipped,w.failed+=K.failed,w.errors.push(...K.errors),w.jobIds.push(...K.jobIds);let G=Math.min(X+B,Y),W=Math.round(G/Y*40);await Q.report({progress:W,message:`Imported ${G}/${Y} files`})}return w}async exportEntitiesWithProgress(A,Q,B){this.logger.debug("Exporting entities with progress reporting");let $=A??this.entityService.getEntityTypes(),w={exported:0,failed:0,errors:[]},D=$.length;await Q.report({progress:50,message:`Starting export of ${D} entity types`});for(let Y=0;Y<D;Y++){let X=$[Y];if(!X)continue;let I=await this.entityService.listEntities(X,{limit:1000});for(let K=0;K<I.length;K+=B){let G=I.slice(K,K+B);for(let q of G)try{await this.fileOperations.writeEntity(q),w.exported++,this.logger.debug("Exported entity",{entityType:X,id:q.id})}catch(N){let M=N instanceof Error?N:Error(`Failed to export entity ${q.id||"unknown"}`);w.failed++,w.errors.push({entityId:q.id||"unknown",entityType:X,error:M.message}),this.logger.error("Failed to export entity",{entityType:X,id:q.id||"unknown",error:M})}let W=(Y+1)/D,Z=50+Math.round(W*50);await Q.report({progress:Z,message:`Exported ${w.exported} entities`})}}return this.logger.debug("Export completed",w),w}}class sXA{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,B,$,w=!0){if(this.logger=A,this.fileOperations=$,this.deleteOnFileRemoval=w,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:X}=this.fileOperations.parseEntityFromPath(D),I=await B({type:"directory-delete",data:{entityId:X,entityType:Y,filePath:D}});this.logger.info("Queued delete job for removed file",{jobId:I,path:D,entityId:X,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})}}}ZA();async function oc(A,Q,B,$){let{sourceUrl:w}=A,D=await Q.listEntities("image",{filter:{metadata:{sourceUrl:w}},limit:1});if(D[0])return $.debug("Reusing existing image entity",{sourceUrl:w,imageId:D[0].id}),D[0].id;let Y=await B(w),{base64:X}=hG(Y),I=JF(X),K=gG(X);if(!I||!K)throw Error("Could not detect image format or dimensions");let G=await Q.createEntity({id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:I,width:K.width,height:K.height,sourceUrl:w}});return $.debug("Created image entity from URL",{sourceUrl:w,imageId:G.entityId}),G.entityId}var lq0=F.object({title:F.string(),slug:F.string().optional(),coverImageUrl:F.string().url(),coverImageId:F.string().optional(),coverImageAlt:F.string().optional()});class aXA{entityService;fetcher;logger;constructor(A,Q,B=E7){this.entityService=A;this.fetcher=B;this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=v4(A)}catch{return null}let{frontmatter:B}=Q,$=lq0.safeParse(B);if(!$.success)return null;if($.data.coverImageId)return null;let{title:w,slug:D,coverImageUrl:Y,coverImageAlt:X}=$.data;if(!OK(Y))return null;return{sourceUrl:Y,postTitle:w,postSlug:D??a1(w),customAlt:X}}async convert(A){let Q;try{Q=v4(A)}catch(K){return this.logger.debug("Parse failed",{error:K}),{content:A,converted:!1}}let{frontmatter:B}=Q,$=lq0.safeParse(B);if(!$.success)return{content:A,converted:!1};if($.data.coverImageId)return{content:A,converted:!1};let{title:w,slug:D,coverImageUrl:Y,coverImageAlt:X}=$.data;if(!OK(Y))return{content:A,converted:!1};let I={postTitle:w,postSlug:D??a1(w),sourceUrl:Y,customAlt:X};try{let K=await this.createImageEntity(I),G={...B};return delete G.coverImageUrl,delete G.coverImageAlt,G.coverImageId=K,{content:JZ(G,Q.content),converted:!0,imageId:K}}catch(K){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:L0(K)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:B,sourceUrl:$,customAlt:w}=A,D=`Cover image for ${Q}`;return oc({id:`${B}-cover`,title:D,alt:w??D,sourceUrl:$},this.entityService,this.fetcher,this.logger)}}ZA();class i_{entityService;fetcher;logger;constructor(A,Q,B=E7){this.entityService=A;this.fetcher=B;this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let B=[],$=Rx(A);for(let w of $){if(!OK(w.url))continue;if(w.url.startsWith("entity://"))continue;let D=this.reconstructMarkdown(w);B.push({sourceUrl:w.url,alt:w.alt,originalMarkdown:D,postSlug:Q})}return B}reconstructMarkdown(A){if(A.title)return`![${A.alt}](${A.url} "${A.title}")`;return`![${A.alt}](${A.url})`}async convert(A,Q){let B=this.detectInlineImages(A,Q);if(B.length===0)return{content:A,converted:!1,convertedCount:0};let $=A,w=0,D=0;for(let Y of B)try{let X=await this.createImageEntity(Y,D++),I=`![${Y.alt}](entity://image/${X})`;$=$.replace(Y.originalMarkdown,I),w++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:X})}catch(X){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:L0(X)})}return{content:$,converted:w>0,convertedCount:w}}async createImageEntity(A,Q){let{sourceUrl:B,alt:$,postSlug:w}=A;return oc({id:`${w}-inline-${Q}`,title:$||`Inline image ${Q+1} for ${w}`,alt:$||"",sourceUrl:B},this.entityService,this.fetcher,this.logger)}}ZA();import{rename as F1Q,appendFile as q1Q,readFile as z1Q,writeFile as V1Q,access as N1Q}from"fs/promises";import{join as pq0}from"path";class tXA{logger;syncPath;constructor(A,Q){this.logger=A;this.syncPath=Q}isValidationError(A){if(A instanceof F.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,$){let w=$(A),D=`${w}.invalid`;try{await F1Q(w,D),B.quarantined++,B.quarantinedFiles.push(A);let Y=pq0(this.syncPath,".import-errors.log"),X=new Date().toISOString(),I=L0(Q),K=`${X} - ${A}: ${I}
1653
+ `)||"No response text";return{success:!0,data:{state:Z,response:N}}}w=await Q.read()}return{success:!1,error:"Stream ended without a terminal event"}}function EF0(A={}){let Q=A.fetch??globalThis.fetch;return{name:"a2a_call",description:"Call a remote A2A agent. Discovers the agent via its Agent Card, sends a message, and returns the response.",inputSchema:NF0,visibility:"anchor",handler:async(B)=>{let $=F.object(NF0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{agent:w,message:D}=$.data,Y=w,X=w.startsWith("http://")||w.startsWith("https://");if(!X&&A.entityService){let Z=await A.entityService.getEntity("agent",w);if(Z){if(Z.metadata.status==="archived")return{success:!1,error:`Agent ${w} is archived. Use agent_add to re-activate.`};let q=Z.metadata.url;if(typeof q==="string")Y=q}}if(!Y.startsWith("http"))Y=`https://${Y}`;let I=await Xa1(Y,Q);if(!I)return{success:!1,error:`Could not fetch Agent Card from ${Y}`};let K=I.url,G;if(A.outboundTokens)try{let Z=new URL(K).hostname;G=A.outboundTokens[Z]}catch{}let W=await Ia1(K,D,Q,G);if("success"in W&&W.success&&X&&A.sendMessage){let Z=new URL(K).hostname;A.sendMessage("a2a:call:completed",{domain:Z}).catch(()=>{})}return W}}}var iYA={name:"@brains/a2a",private:!0,version:"0.2.0-alpha.32",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 Ua1={"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 bX{agentCard;unsubscribeReady;unsubscribeSyncCompleted;taskManager=new pYA;agentService;permissionContext;app;constructor(A={}){super("a2a",iYA,A,GF0)}async onRegister(A){if(await super.onRegister(A),!A.plugins.has("webserver"))throw Error("A2A requires the webserver interface. Standalone HTTP listeners have been removed.");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.logger.info("A2A interface registered",{domain:A.domain})}async rebuildAgentCard(A){let Q=A.identity.get(),B=A.identity.getProfile(),$=A.tools.listForPermissionLevel("public"),w=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((X)=>wV.safeParse(X.metadata)).filter((X)=>X.success).map((X)=>X.data)}catch{}this.agentCard=JF0({character:Q,profile:B,version:iYA.version,domain:A.domain,organization:this.config.organization,tools:$,skills:D,authEnabled:w}),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,$]of Object.entries(Ua1))Q.set(B,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new kL;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 $=FF0.safeParse(B);if(!$.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));let w=this.resolveCallerPermission(Q.req.header("Authorization"));if($.data.method==="message/stream"){let Y=zF0.safeParse($.data.params??{});if(!Y.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Y.error.message}`},id:$.data.id}));let{stream:X}=VF0($.data.id,Y.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:w});return this.withCors(new Response(X,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let D=await qF0($.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:w});return this.withCors(Q.json(D))}),this.app=A,A}getWebRoutes(){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[EF0({outboundTokens:this.config.outboundTokens,entityService:this.getContext().entityService,sendMessage:(A,Q)=>this.getContext().messaging.send(A,Q)})]}createDaemon(){return{start:async()=>{this.logger.info("A2A mounted on shared webserver host")},stop:async()=>{this.unsubscribeReady?.(),this.unsubscribeSyncCompleted?.(),this.logger.info("A2A server stopped")}}}}w0();w0();class rYA{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=[],$=this.createImportOperations(A);B.push(...$);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:w,totalFiles:D}),{operations:B,exportOperationsCount:0,importOperationsCount:w,totalFiles:D}}async queueSyncBatch(A,Q,B,$,w){let D=this.prepareBatchOperations(B,w);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:$?.rootJobId??j6(),metadata:{progressToken:$?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:$?.pluginId??"directory-sync",interfaceType:$?.interfaceType,channelId:$?.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 $=0;$<A.length;$+=Q){let w=A.slice($,$+Q);B.push({type:"directory-import",data:{batchIndex:Math.floor($/Q),paths:w,batchSize:w.length}})}return B}}ZA();import{resolve as C1Q,isAbsolute as O1Q}from"path";import{mkdir as j1Q}from"fs/promises";var cq0=o0(hq0(),1);d4();import{join as KI,dirname as K1Q,extname as nc}from"path";import{mkdir as iXA,readFile as rc,writeFile as gq0,readdir as H1Q,stat as yq0,utimes as U1Q,access as G1Q}from"fs/promises";var d_=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function mq0(A){let Q=nc(A).toLowerCase();return d_.includes(Q)}function J1Q(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 uq0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}async function mL(A){try{return await G1Q(A),!0}catch{return!1}}class rXA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){let $=(A.startsWith(this.syncPath)?A:KI(this.syncPath,A)).replace(this.syncPath+"/","").split("/"),w,D;if($.length===1)w="base",D=$;else if($.length>1&&$[0])w=$[0],D=$.slice(1);else w="base",D=$;let Y;if(D.length>1){let X=D[D.length-1];if(X){let I=nc(X).toLowerCase(),K=I===".md"||d_.includes(I)?X.slice(0,-I.length):X;D[D.length-1]=K}Y=D.join(":")}else{let X=D[0]??"",I=nc(X).toLowerCase();Y=I===".md"||d_.includes(I)?X.slice(0,-I.length):X}return{entityType:w,id:Y}}async readEntity(A){let Q=A.startsWith(this.syncPath)?A:KI(this.syncPath,A),B=await yq0(Q),{entityType:$,id:w}=this.parseEntityFromPath(A),D=B.birthtime.getTime()>0?B.birthtime:B.mtime,Y=B.mtime,X;if(mq0(A)){let K=(await rc(Q)).toString("base64"),G=nc(A);X=`data:${J1Q(G)};base64,${K}`}else X=await rc(Q,"utf-8");return{entityType:$,id:w,content:X,created:D,updated:Y}}async writeEntity(A){let Q=this.getEntityFilePath(A),B=A.entityType==="image",$;if(B){let D=A.content.match(/^data:image\/[a-z+]+;base64,(.+)$/i);$=D?.[1]?Buffer.from(D[1],"base64"):Buffer.from(A.content,"base64")}else $=this.entityService.serializeEntity(A);if(await mL(Q)){let D=B?await rc(Q):await rc(Q,"utf-8"),Y=nB(B?D.toString("base64"):D),X=nB(B?$.toString("base64"):$);if(Y===X)return}if(A.entityType!=="base")await iXA(K1Q(Q),{recursive:!0});if(B)await gq0(Q,$);else await gq0(Q,$,"utf-8");let w=new Date(A.updated);await U1Q(Q,w,w)}getFilePath(A,Q,B=".md"){let $=A.split(":").filter((I)=>I.length>0),w=Q==="base";if($.length===1)return w?KI(this.syncPath,`${$[0]}${B}`):KI(this.syncPath,Q,`${$[0]}${B}`);let D=$;if($[0]===Q)D=$.slice(1);let Y=D[D.length-1],X=D.slice(0,-1);if(w)return KI(this.syncPath,...X,`${Y}${B}`);else return KI(this.syncPath,Q,...X,`${Y}${B}`)}getEntityFilePath(A){let Q=".md";if(A.entityType==="image"){let B=A.metadata.format;if(B)Q=uq0(B);else{let $=A.content.match(/^data:image\/([a-z+]+);base64,/i);if($?.[1])Q=uq0($[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 mL(this.syncPath))return Q;let B=async($,w="",D=!1)=>{let Y=await H1Q($,{withFileTypes:!0});for(let X of Y){let I=w?KI(w,X.name):X.name;if(X.isFile()&&!X.name.endsWith(".invalid")){if(X.name.endsWith(".md"))Q.push(I);else if(A.includeImages&&D&&mq0(X.name))Q.push(I)}else if(X.isDirectory()&&!X.name.startsWith(".")){if(w===""&&!this.entityService.hasEntityType(X.name))continue;let K=KI($,X.name),G=X.name==="image"&&w==="";await B(K,I,D||G)}}};return await B(this.syncPath),Q}async ensureDirectoryStructure(A){if(!await mL(this.syncPath))await iXA(this.syncPath,{recursive:!0});for(let Q of A)if(Q!=="base")await iXA(KI(this.syncPath,Q),{recursive:!0})}shouldUpdateEntity(A,Q){let B=nB(Q.content);return A.contentHash!==B}async gatherFileStatus(){let A=[],Q={totalFiles:0,byEntityType:{}};if(!await mL(this.syncPath))return{files:A,stats:Q};let B=await this.getAllMarkdownFiles();for(let $ of B)try{let w=KI(this.syncPath,$),D=await yq0(w),{entityType:Y}=this.parseEntityFromPath($);A.push({path:$,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 mL(this.syncPath)}async fileExists(A){return mL(A)}}function W1Q(A,Q){if(!A.replace(Q+"/","").startsWith("image/"))return!1;return d_.some(($)=>A.toLowerCase().endsWith($))}function Z1Q(A,Q){if(A.replace(Q+"/","").split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return W1Q(A,Q)}class nXA{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=cq0.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(!Z1Q(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 $=`${this.syncPath}/${Q}`;try{if(this.onFileChange)await this.onFileChange(B,$)}catch(w){this.logger.error("Error processing file change",{path:Q,event:B,error:w})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}class oXA{logger;entityService;fileOperations;constructor(A,Q,B){this.logger=A,this.entityService=Q,this.fileOperations=B}async importEntitiesWithProgress(A,Q,B,$){this.logger.debug("Importing entities with progress reporting");let w={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 X=0;X<Y;X+=B){let I=D.slice(X,X+B),K=await $(I);w.imported+=K.imported,w.skipped+=K.skipped,w.failed+=K.failed,w.errors.push(...K.errors),w.jobIds.push(...K.jobIds);let G=Math.min(X+B,Y),W=Math.round(G/Y*40);await Q.report({progress:W,message:`Imported ${G}/${Y} files`})}return w}async exportEntitiesWithProgress(A,Q,B){this.logger.debug("Exporting entities with progress reporting");let $=A??this.entityService.getEntityTypes(),w={exported:0,failed:0,errors:[]},D=$.length;await Q.report({progress:50,message:`Starting export of ${D} entity types`});for(let Y=0;Y<D;Y++){let X=$[Y];if(!X)continue;let I=await this.entityService.listEntities(X,{limit:1000});for(let K=0;K<I.length;K+=B){let G=I.slice(K,K+B);for(let q of G)try{await this.fileOperations.writeEntity(q),w.exported++,this.logger.debug("Exported entity",{entityType:X,id:q.id})}catch(N){let M=N instanceof Error?N:Error(`Failed to export entity ${q.id||"unknown"}`);w.failed++,w.errors.push({entityId:q.id||"unknown",entityType:X,error:M.message}),this.logger.error("Failed to export entity",{entityType:X,id:q.id||"unknown",error:M})}let W=(Y+1)/D,Z=50+Math.round(W*50);await Q.report({progress:Z,message:`Exported ${w.exported} entities`})}}return this.logger.debug("Export completed",w),w}}class sXA{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,B,$,w=!0){if(this.logger=A,this.fileOperations=$,this.deleteOnFileRemoval=w,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:X}=this.fileOperations.parseEntityFromPath(D),I=await B({type:"directory-delete",data:{entityId:X,entityType:Y,filePath:D}});this.logger.info("Queued delete job for removed file",{jobId:I,path:D,entityId:X,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})}}}ZA();async function oc(A,Q,B,$){let{sourceUrl:w}=A,D=await Q.listEntities("image",{filter:{metadata:{sourceUrl:w}},limit:1});if(D[0])return $.debug("Reusing existing image entity",{sourceUrl:w,imageId:D[0].id}),D[0].id;let Y=await B(w),{base64:X}=hG(Y),I=JF(X),K=gG(X);if(!I||!K)throw Error("Could not detect image format or dimensions");let G=await Q.createEntity({id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:I,width:K.width,height:K.height,sourceUrl:w}});return $.debug("Created image entity from URL",{sourceUrl:w,imageId:G.entityId}),G.entityId}var lq0=F.object({title:F.string(),slug:F.string().optional(),coverImageUrl:F.string().url(),coverImageId:F.string().optional(),coverImageAlt:F.string().optional()});class aXA{entityService;fetcher;logger;constructor(A,Q,B=E7){this.entityService=A;this.fetcher=B;this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=v4(A)}catch{return null}let{frontmatter:B}=Q,$=lq0.safeParse(B);if(!$.success)return null;if($.data.coverImageId)return null;let{title:w,slug:D,coverImageUrl:Y,coverImageAlt:X}=$.data;if(!OK(Y))return null;return{sourceUrl:Y,postTitle:w,postSlug:D??a1(w),customAlt:X}}async convert(A){let Q;try{Q=v4(A)}catch(K){return this.logger.debug("Parse failed",{error:K}),{content:A,converted:!1}}let{frontmatter:B}=Q,$=lq0.safeParse(B);if(!$.success)return{content:A,converted:!1};if($.data.coverImageId)return{content:A,converted:!1};let{title:w,slug:D,coverImageUrl:Y,coverImageAlt:X}=$.data;if(!OK(Y))return{content:A,converted:!1};let I={postTitle:w,postSlug:D??a1(w),sourceUrl:Y,customAlt:X};try{let K=await this.createImageEntity(I),G={...B};return delete G.coverImageUrl,delete G.coverImageAlt,G.coverImageId=K,{content:JZ(G,Q.content),converted:!0,imageId:K}}catch(K){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:L0(K)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:B,sourceUrl:$,customAlt:w}=A,D=`Cover image for ${Q}`;return oc({id:`${B}-cover`,title:D,alt:w??D,sourceUrl:$},this.entityService,this.fetcher,this.logger)}}ZA();class i_{entityService;fetcher;logger;constructor(A,Q,B=E7){this.entityService=A;this.fetcher=B;this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let B=[],$=Rx(A);for(let w of $){if(!OK(w.url))continue;if(w.url.startsWith("entity://"))continue;let D=this.reconstructMarkdown(w);B.push({sourceUrl:w.url,alt:w.alt,originalMarkdown:D,postSlug:Q})}return B}reconstructMarkdown(A){if(A.title)return`![${A.alt}](${A.url} "${A.title}")`;return`![${A.alt}](${A.url})`}async convert(A,Q){let B=this.detectInlineImages(A,Q);if(B.length===0)return{content:A,converted:!1,convertedCount:0};let $=A,w=0,D=0;for(let Y of B)try{let X=await this.createImageEntity(Y,D++),I=`![${Y.alt}](entity://image/${X})`;$=$.replace(Y.originalMarkdown,I),w++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:X})}catch(X){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:L0(X)})}return{content:$,converted:w>0,convertedCount:w}}async createImageEntity(A,Q){let{sourceUrl:B,alt:$,postSlug:w}=A;return oc({id:`${w}-inline-${Q}`,title:$||`Inline image ${Q+1} for ${w}`,alt:$||"",sourceUrl:B},this.entityService,this.fetcher,this.logger)}}ZA();import{rename as F1Q,appendFile as q1Q,readFile as z1Q,writeFile as V1Q,access as N1Q}from"fs/promises";import{join as pq0}from"path";class tXA{logger;syncPath;constructor(A,Q){this.logger=A;this.syncPath=Q}isValidationError(A){if(A instanceof F.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,$){let w=$(A),D=`${w}.invalid`;try{await F1Q(w,D),B.quarantined++,B.quarantinedFiles.push(A);let Y=pq0(this.syncPath,".import-errors.log"),X=new Date().toISOString(),I=L0(Q),K=`${X} - ${A}: ${I}
1654
1654
  \u2192 ${A}.invalid
1655
1655
 
1656
1656
  `;await q1Q(Y,K),this.logger.warn("Quarantined invalid entity file",{originalPath:A,quarantinePath:`${A}.invalid`,error:I})}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=pq0(this.syncPath,".import-errors.log");try{await N1Q(Q)}catch{return}try{let B=await z1Q(Q,"utf-8");if(B.includes(A)){let w=`${new Date().toISOString()} - [RECOVERED] ${A}
@@ -1676,7 +1676,7 @@ ${A.entityContent}`,lW1);I=$+_.imagePrompt}catch(_){this.logger.warn("AI prompt
1676
1676
  *...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
1677
1677
  ## Getting Started
1678
1678
  `),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(`
1679
- `)}}w0();class Vl extends NB{context;directorySync;constructor(A,Q,B){super(A,{schema:SN0,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 $=Date.now(),w={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,X]of D.entries())await this.exportEntityType(X,A.batchSize??100,Q,w),await B.report({message:`Exported ${Y+1}/${D.length} entity types (${w.exported} entities)`,progress:Y+1,total:D.length});return this.logger.debug("Directory export job completed",{jobId:Q,exported:w.exported,failed:w.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,$){let w=0,D=!0;while(D){let Y=await this.context.entityService.listEntities(A,{limit:Q,offset:w});if(Y.length===0){D=!1;break}let X=Y.map(async(I)=>{let K=await this.directorySync.processEntityExport(I);if(K.success)$.exported++;else $.failed++,$.errors.push({entityId:I.id,entityType:A,error:K.error??"Unknown error"});return K});await Promise.all(X),this.logger.debug("Export progress",{jobId:B,entityType:A,processed:w+Y.length,exported:$.exported,failed:$.failed}),w+=Q,D=Y.length===Q}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}w0();ZA();d4();class Nl extends NB{context;directorySync;constructor(A,Q,B){super(A,{schema:vN0,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 $=Date.now(),w={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 X=0;X<D.length;X+=Y){let I=D.slice(X,X+Y);await this.importBatch(I,Q,w,X,D.length);let K=Math.min(X+Y,D.length);await B.report({message:`Imported ${K}/${D.length} files (${w.imported} successful, ${w.failed} failed)`,progress:K,total:D.length})}return this.logger.debug("Directory import job completed",{jobId:Q,imported:w.imported,skipped:w.skipped,failed:w.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 X=await this.directorySync.fileOps.readEntity(Y);if(!this.context.entityService.getEntityTypes().includes(X.entityType))return B.skipped++,{success:!1,skipped:!0};try{let K=this.context.entityService.deserializeEntity(X.content,X.entityType),G=await this.context.entityService.getEntity(X.entityType,X.id);if(G){let W=new Date(G.updated).getTime(),Z=X.updated.getTime(),q=nB(X.content),N=G.contentHash!==q;if(W<Z||N){let M={...G,content:X.content,...K,id:X.id,entityType:X.entityType,updated:X.updated.toISOString()};await this.context.entityService.updateEntity(M),B.imported++}else B.skipped++}else{let W={id:X.id,entityType:X.entityType,content:X.content,...K,metadata:K.metadata??{},created:X.created.toISOString(),updated:X.updated.toISOString()};await this.context.entityService.createEntity(W),B.imported++}return{success:!0}}catch{return B.skipped++,{success:!1,skipped:!0}}}catch(X){return B.failed++,B.errors.push({path:Y,error:L0(X)}),{success:!1,error:X}}});await Promise.all(D),this.logger.debug("Import progress",{jobId:Q,processed:$+A.length,total:w,imported:B.imported,skipped:B.skipped,failed:B.failed})}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}w0();class Ll extends NB{directorySync;context;constructor(A,Q,B){super(A,{schema:xN0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=B}async process(A,Q,B){let $=Date.now(),w=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:w});let D={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if(w!=="export")if(await B.report({progress:10,message:"Scanning directory for changes"}),D=await this.importWithProgress(A.paths,B),w==="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(w!=="import"){let I=w==="export"?10:60;await B.report({progress:I,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,B),await B.report({progress:100,message:w==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${D.imported} imported, ${Y.exported} exported`})}let X=Date.now()-$;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:D.imported,exported:Y.exported}),{import:D,export:Y,duration:X}}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,$=300000,w=500,D=Date.now(),Y=async()=>{let I=(await Promise.all(A.map((G)=>B.getAsyncJobStatus(G)))).filter((G)=>G&&(G.status==="completed"||G.status==="failed")).length;if(I===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-D>$){this.logger.warn(`Timeout waiting for import jobs (${I}/${A.length} completed)`);return}let K=Math.round(I/A.length*100);return await Q.report({progress:50+Math.round(K*0.05),message:`Processing ${I}/${A.length} entities`}),await new Promise((G)=>setTimeout(G,w)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}w0();class El extends NB{context;constructor(A,Q,B){super(A,{schema:rIA,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,B){let $=rIA.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}),await B.report({progress:0,total:1,message:`Deleting ${$.entityType}:${$.entityId}`});try{let w=await this.context.entityService.deleteEntity($.entityType,$.entityId);if(w)this.logger.info("Successfully deleted entity for removed file",{entityId:$.entityId,entityType:$.entityType});else this.logger.warn("Entity not found in database",{entityId:$.entityId,entityType:$.entityType});return await B.report({progress:1,total:1,message:`Deleted ${$.entityType}:${$.entityId}`}),{deleted:w,entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}}catch(w){throw this.logger.error("Failed to delete entity",{entityId:$.entityId,entityType:$.entityType,error:w}),w}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}w0();ZA();var B8Q=F.object({});class Ml extends NB{directorySync;constructor(A,Q){super(A,{schema:B8Q,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,B){await B.report({progress:0,message:"Removing orphaned entities"});let $=await this.directorySync.removeOrphanedEntities();return await B.report({progress:100,message:`Cleanup complete: ${$.deleted} orphans removed`}),$}}w0();ZA();import{readFile as $8Q,writeFile as w8Q}from"fs/promises";var D8Q=F.object({filePath:F.string(),sourceUrl:F.string().url(),postTitle:F.string(),postSlug:F.string(),customAlt:F.string().optional()});class Cl extends NB{context;fetcher;constructor(A,Q,B=E7){super(Q,{schema:D8Q,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=B}async process(A,Q,B){let{filePath:$,sourceUrl:w,postTitle:D,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:$,sourceUrl:w,postSlug:Y});try{await this.reportProgress(B,{progress:GQ.INIT,message:`Reading file: ${$}`});let I;try{I=await $8Q($,"utf-8")}catch(M){return this.logger.error("Failed to read file",{filePath:$,error:L0(M)}),I6.failure(M)}let K;try{K=v4(I)}catch(M){return this.logger.warn("Failed to parse markdown",{filePath:$,error:L0(M)}),I6.failure(M)}let G=K.frontmatter;if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(B,{progress:GQ.FETCH,message:"Checking for existing image"});let W=await this.context.entityService.listEntities("image",{filter:{metadata:{sourceUrl:w}},limit:1}),Z;if(W[0])Z=W[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:w,imageId:Z}),await this.reportProgress(B,{progress:GQ.EXTRACT,message:`Reusing existing image: ${Z}`});else{await this.reportProgress(B,{progress:GQ.PROCESS,message:`Fetching image from ${w}`});let M;try{M=await this.fetcher(w)}catch(n){return this.logger.error("Failed to fetch image",{sourceUrl:w,error:L0(n)}),I6.failure(n)}await this.reportProgress(B,{progress:GQ.GENERATE,message:"Creating image entity"});let{base64:L}=hG(M),_=JF(L),T=gG(L);if(!_||!T)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:w}),I6.failure(Error("Could not detect image format or dimensions"));Z=`${Y}-cover`;let P=`Cover image for ${D}`,r=X??P;await this.context.entityService.createEntity({id:Z,entityType:"image",content:M,metadata:{title:P,alt:r,format:_,width:T.width,height:T.height,sourceUrl:w}}),this.logger.debug("Created image entity",{imageId:Z,sourceUrl:w}),await this.reportProgress(B,{progress:GQ.EXTRACT,message:`Created image: ${Z}`})}await this.reportProgress(B,{progress:GQ.SAVE,message:"Updating file"});let q={...G};delete q.coverImageUrl,delete q.coverImageAlt,q.coverImageId=Z;let N=JZ(q,K.content);try{await w8Q($,N,"utf-8")}catch(M){return this.logger.error("Failed to write file",{filePath:$,error:L0(M)}),I6.failure(M)}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:Z,sourceUrl:w}),{success:!0,imageId:Z}}catch(I){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:L0(I)}),I6.failure(I)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}w0();ZA();import{readFile as Y8Q,writeFile as X8Q}from"fs/promises";class Ol extends NB{converter;constructor(A,Q,B=E7){super(Q,{schema:hN0,jobTypeName:"inline-image-convert"});this.converter=new i_(A.entityService,Q,B)}async process(A,Q,B){let{filePath:$,postSlug:w}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:$,postSlug:w});try{await this.reportProgress(B,{progress:GQ.INIT,message:`Reading file: ${$}`});let D;try{D=await Y8Q($,"utf-8")}catch(I){let K=L0(I);return this.logger.error("Failed to read file",{filePath:$,error:K}),{success:!1,error:K}}await this.reportProgress(B,{progress:GQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(D,w);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:$,count:Y.length}),await this.reportProgress(B,{progress:GQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(D,w);if(!X.converted)return this.logger.debug("No images were converted",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(B,{progress:GQ.SAVE,message:"Writing updated file"});try{await X8Q($,X.content,"utf-8")}catch(I){let K=L0(I);return this.logger.error("Failed to write file",{filePath:$,error:K}),{success:!1,error:K}}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(D){let Y=L0(D);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:$,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function mN0(A,Q,B){let $=(w)=>B.child(w);A.jobs.registerHandler("directory-sync",new Ll($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new Vl($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new Nl($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new El($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new Ml($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Cl(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Ol(A,$("InlineImageConversionJobHandler"))),B.debug("Registered async job handlers")}w0();import{unlink as I8Q,access as K8Q}from"fs/promises";function uN0(A,Q,B,$){let{subscribe:w}=A.messaging,{entityService:D}=A;w("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),B.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(I){B.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:I instanceof Error?I.message:String(I),stack:I instanceof Error?I.stack:void 0})}return{success:!0}}),w("entity:updated",async(Y)=>{let{entityType:X,entityId:I}=Y.payload;try{let K=await D.getEntity(X,I);if(!K)return B.debug("Entity not found in DB, skipping export",{entityType:X,entityId:I}),{success:!1};await Q.fileOps.writeEntity(K),B.debug("Auto-exported updated entity",{id:K.id,entityType:K.entityType})}catch(K){B.error("Auto-export FAILED for updated entity",{entityType:X,entityId:I,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0})}return{success:!0}}),w("entity:deleted",async(Y)=>{let{entityId:X,entityType:I}=Y.payload,K=Q.fileOps.getFilePath(X,I);if(await K8Q(K).then(()=>!0,()=>!1))await I8Q(K),B.debug("Auto-deleted entity file",{id:X,entityType:I,path:K});return{success:!0}}),B.debug("Setup auto-sync for entity events",{entityTypes:$})}function cN0(A,Q,B){Q.setJobQueueCallback(async($)=>{let w=[{type:$.type,data:$.data}];return A.jobs.enqueueBatch(w,{priority:5,source:"directory-sync-watcher",rootJobId:j6(),metadata:{operationType:"file_operations",operationTarget:B,pluginId:"directory-sync"}})})}ZA();import{access as H8Q,readdir as lN0,mkdir as U8Q,copyFile as G8Q}from"fs/promises";import{exec as J8Q}from"child_process";import{promisify as W8Q}from"util";import{join as oIA,resolve as nIA}from"path";var Z8Q=W8Q(J8Q);async function jl(A){try{return await H8Q(A),!0}catch{return!1}}async function F8Q(A,Q){if(!await jl(A))return!0;if((await lN0(A)).filter((w)=>!w.startsWith(".")&&!w.startsWith("_")).length>0)return!1;if(await q8Q(A))return Q.debug("Git repository with remote detected - skipping seed content",{path:A}),!1;return!0}async function q8Q(A){let Q=oIA(A,".git");if(!await jl(Q))return!1;try{let{stdout:B}=await Z8Q("git remote",{cwd:A});return B.trim().length>0}catch{return!1}}async function pN0(A,Q){let B=await lN0(A,{withFileTypes:!0});for(let $ of B){let w=oIA(A,$.name),D=oIA(Q,$.name);if($.isDirectory()){if(!await jl(D))await U8Q(D,{recursive:!0});await pN0(w,D)}else await G8Q(w,D)}}async function dN0(A,Q,B){let $=nIA(process.cwd(),A);B=B?nIA(B):nIA(process.cwd(),"seed-content");let w=await F8Q($,Q);if(w&&await jl(B))Q.debug("Copying seed content to brain-data directory"),await pN0(B,$),Q.debug("Seed content copied successfully");else if(w)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 z8Q(A,Q,B,$=300000){let D=Date.now();while(Date.now()-D<$){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((X)=>setTimeout(X,500))}B.warn(`Timeout waiting for batch ${Q} after ${$}ms`)}function iN0(A,Q,B,$,w,D){let Y=!1,X=async()=>{if(Y)return;Y=!0;let I=Q();if(B.seedContent){let K=B.syncPath??A.dataDir;await dN0(K,w,B.seedContentPath)}try{if(D){w.debug("Git enabled \u2014 pulling before import");let G=await D.pull();if(G.files.length>0)w.info("Pulled changes from remote",{filesChanged:G.files.length})}w.debug("Starting initial sync");let K=await I.queueSyncBatch(A,"initial-sync",void 0,{includeCleanup:!0});if(!K){w.debug("Initial sync: no files to import"),await A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0});return}w.debug("Initial sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles}),z8Q(A,K.batchId,w).then(()=>A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0}),(G)=>{w.error("Initial sync batch failed",G),A.messaging.send("sync:initial:completed",{success:!1,error:L0(G)},{broadcast:!0})})}catch(K){w.error("Initial sync failed",K),await A.messaging.send("sync:initial:completed",{success:!1,error:L0(K)},{broadcast:!0})}};A.messaging.subscribe("system:plugins:ready",async()=>{return w.debug("system:plugins:ready received, starting initial sync"),await X(),{success:!0}})}ZA();function rN0(A,Q,B,$){let w=new zZ(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){$.error("Git auto-commit failed",{error:X})}})},B),D=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of D){let I=A.subscribe(X,async()=>{return w.trigger(),{success:!0}});Y.push(I)}return()=>{w.dispose();for(let X of Y)X()}}function nN0(A,Q,B,$,w){if($<=0)return()=>{};let D=$*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:K}=await A.withLock(()=>A.pull());if(K.length>0)w.info("Periodic sync: pulled changes",{filesChanged:K.length});let G=await Q.queueSyncBatch(B,"periodic-sync");if(G)w.debug("Periodic sync: queued imports",{importOperations:G.importOperationsCount,totalFiles:G.totalFiles})}catch(K){w.error("Periodic git sync failed",{error:K})}finally{Y=!1}},I=setInterval(()=>{X()},D);return w.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(I)}}function oN0(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(X){return{success:!1,error:X instanceof Error?X.message:"Export failed"}}}),D("entity:import:request",async(Y)=>{try{let X=Q(),I=Y.payload.paths,K=await X.importEntities(I);if(I&&I.length>0)await X.removeOrphanedEntities();return{success:!0,data:K}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Import failed"}}}),D("sync:status:request",async()=>{try{let X=await Q().getStatus();return{success:!0,data:{syncPath:X.syncPath,isInitialized:X.exists,watchEnabled:X.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),D("sync:configure:request",async(Y)=>{try{return await B({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Configuration failed"}}}),D("git-sync:get-repo-info",async()=>{if(!w?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:w.repo,branch:w.branch??"main"}}}),$.debug("Registered message handlers")}w0();ZA();w0();ZA();function sN0(A,Q){return g2(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",F.object({entityType:F.string().describe("Entity type (e.g. post, note, link)"),id:F.string().describe("Entity ID"),sha:F.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:F.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(B)=>{let $=`${B.entityType}/${B.id}.md`;try{if(B.sha){let D=await Q.show(B.sha,$);return E9({sha:B.sha,entityType:B.entityType,id:B.id,content:D},`Content at ${B.sha.slice(0,7)}`)}let w=await Q.log($,B.limit);if(w.length===0)return E9({commits:[]},`No history found for ${B.entityType}/${B.id}`);return E9({commits:w,entityType:B.entityType,id:B.id},`${w.length} version${w.length===1?"":"s"} found`)}catch(w){return z5(w instanceof Error?w.message:"History lookup failed")}})}function aN0(A,Q,B,$){let w=[g2(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.",F.object({}),async(D,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${B}`,I={interfaceType:Y.interfaceType,channelId:Y.channelId},K=!1;if($)await $.withLock(()=>$.pull()),K=!0;let G=await A.queueSyncBatch(Q,X,I);if(!G)return E9({gitPulled:K},"No files to sync");return E9({batchId:G.batchId,importOperations:G.importOperationsCount,totalFiles:G.totalFiles,gitPulled:K},`Sync started: ${G.importOperationsCount} import jobs queued for ${G.totalFiles} files${K?" (pulled from git)":""}`)}catch(X){return z5(X instanceof Error?X.message:"Sync failed")}},{cli:{name:"sync"}}),g2(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.",F.object({}),async()=>{try{let D=await A.getStatus(),Y={syncPath:D.syncPath,lastSync:D.lastSync?.toISOString(),watching:D.watching};if($){let X=await $.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return E9(Y)}catch(D){return z5(D instanceof Error?D.message:"Status check failed")}},{visibility:"public"})];if($)w.push(sN0(B,$));return w}var tN0={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.31",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 sIA extends f8{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",tN0,A,TN0)}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:$k,basePrompt:"",formatter:new zl,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new r_({syncPath:$,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:$})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let w=this.requireDirectorySync();if(uN0(A,w,this.logger,this.config.entityTypes),this.config.autoSync)cN0(A,w,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 iIA({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(rN0(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(nN0(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)iN0(A,()=>this.requireDirectorySync(),this.config,this.id,this.logger,this.gitSync);oN0(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return aN0(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 r_({...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){mN0(A,this.requireDirectorySync(),this.logger)}}function H3(A={}){return new sIA(A)}w0();w0();ZA();ZA();var eN0=F.object({environment:F.enum(["preview","production"]),outputDir:F.string(),workingDir:F.string().optional(),sharedImagesDir:F.string().default("./dist/images"),enableContentGeneration:F.boolean().default(!1),cleanBeforeBuild:F.boolean().default(!0),siteConfig:F.object({title:F.string(),description:F.string(),url:F.string().optional(),copyright:F.string().optional(),themeMode:F.enum(["light","dark"]).optional(),analyticsScript:F.string().optional()}),layouts:F.record(F.any()),themeCSS:F.string().optional()}),mS2=F.object({success:F.boolean(),outputDir:F.string(),filesGenerated:F.number(),routesBuilt:F.number(),errors:F.array(F.string()).optional(),warnings:F.array(F.string()).optional()});import{render as Mk0}from"preact-render-to-string";import{h as S3}from"preact";class aIA{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(`
1679
+ `)}}w0();class Vl extends NB{context;directorySync;constructor(A,Q,B){super(A,{schema:SN0,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 $=Date.now(),w={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,X]of D.entries())await this.exportEntityType(X,A.batchSize??100,Q,w),await B.report({message:`Exported ${Y+1}/${D.length} entity types (${w.exported} entities)`,progress:Y+1,total:D.length});return this.logger.debug("Directory export job completed",{jobId:Q,exported:w.exported,failed:w.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,$){let w=0,D=!0;while(D){let Y=await this.context.entityService.listEntities(A,{limit:Q,offset:w});if(Y.length===0){D=!1;break}let X=Y.map(async(I)=>{let K=await this.directorySync.processEntityExport(I);if(K.success)$.exported++;else $.failed++,$.errors.push({entityId:I.id,entityType:A,error:K.error??"Unknown error"});return K});await Promise.all(X),this.logger.debug("Export progress",{jobId:B,entityType:A,processed:w+Y.length,exported:$.exported,failed:$.failed}),w+=Q,D=Y.length===Q}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}w0();ZA();d4();class Nl extends NB{context;directorySync;constructor(A,Q,B){super(A,{schema:vN0,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 $=Date.now(),w={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 X=0;X<D.length;X+=Y){let I=D.slice(X,X+Y);await this.importBatch(I,Q,w,X,D.length);let K=Math.min(X+Y,D.length);await B.report({message:`Imported ${K}/${D.length} files (${w.imported} successful, ${w.failed} failed)`,progress:K,total:D.length})}return this.logger.debug("Directory import job completed",{jobId:Q,imported:w.imported,skipped:w.skipped,failed:w.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 X=await this.directorySync.fileOps.readEntity(Y);if(!this.context.entityService.getEntityTypes().includes(X.entityType))return B.skipped++,{success:!1,skipped:!0};try{let K=this.context.entityService.deserializeEntity(X.content,X.entityType),G=await this.context.entityService.getEntity(X.entityType,X.id);if(G){let W=new Date(G.updated).getTime(),Z=X.updated.getTime(),q=nB(X.content),N=G.contentHash!==q;if(W<Z||N){let M={...G,content:X.content,...K,id:X.id,entityType:X.entityType,updated:X.updated.toISOString()};await this.context.entityService.updateEntity(M),B.imported++}else B.skipped++}else{let W={id:X.id,entityType:X.entityType,content:X.content,...K,metadata:K.metadata??{},created:X.created.toISOString(),updated:X.updated.toISOString()};await this.context.entityService.createEntity(W),B.imported++}return{success:!0}}catch{return B.skipped++,{success:!1,skipped:!0}}}catch(X){return B.failed++,B.errors.push({path:Y,error:L0(X)}),{success:!1,error:X}}});await Promise.all(D),this.logger.debug("Import progress",{jobId:Q,processed:$+A.length,total:w,imported:B.imported,skipped:B.skipped,failed:B.failed})}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}w0();class Ll extends NB{directorySync;context;constructor(A,Q,B){super(A,{schema:xN0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=B}async process(A,Q,B){let $=Date.now(),w=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:w});let D={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if(w!=="export")if(await B.report({progress:10,message:"Scanning directory for changes"}),D=await this.importWithProgress(A.paths,B),w==="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(w!=="import"){let I=w==="export"?10:60;await B.report({progress:I,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,B),await B.report({progress:100,message:w==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${D.imported} imported, ${Y.exported} exported`})}let X=Date.now()-$;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:D.imported,exported:Y.exported}),{import:D,export:Y,duration:X}}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,$=300000,w=500,D=Date.now(),Y=async()=>{let I=(await Promise.all(A.map((G)=>B.getAsyncJobStatus(G)))).filter((G)=>G&&(G.status==="completed"||G.status==="failed")).length;if(I===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-D>$){this.logger.warn(`Timeout waiting for import jobs (${I}/${A.length} completed)`);return}let K=Math.round(I/A.length*100);return await Q.report({progress:50+Math.round(K*0.05),message:`Processing ${I}/${A.length} entities`}),await new Promise((G)=>setTimeout(G,w)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}w0();class El extends NB{context;constructor(A,Q,B){super(A,{schema:rIA,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,B){let $=rIA.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}),await B.report({progress:0,total:1,message:`Deleting ${$.entityType}:${$.entityId}`});try{let w=await this.context.entityService.deleteEntity($.entityType,$.entityId);if(w)this.logger.info("Successfully deleted entity for removed file",{entityId:$.entityId,entityType:$.entityType});else this.logger.warn("Entity not found in database",{entityId:$.entityId,entityType:$.entityType});return await B.report({progress:1,total:1,message:`Deleted ${$.entityType}:${$.entityId}`}),{deleted:w,entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}}catch(w){throw this.logger.error("Failed to delete entity",{entityId:$.entityId,entityType:$.entityType,error:w}),w}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}w0();ZA();var B8Q=F.object({});class Ml extends NB{directorySync;constructor(A,Q){super(A,{schema:B8Q,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,B){await B.report({progress:0,message:"Removing orphaned entities"});let $=await this.directorySync.removeOrphanedEntities();return await B.report({progress:100,message:`Cleanup complete: ${$.deleted} orphans removed`}),$}}w0();ZA();import{readFile as $8Q,writeFile as w8Q}from"fs/promises";var D8Q=F.object({filePath:F.string(),sourceUrl:F.string().url(),postTitle:F.string(),postSlug:F.string(),customAlt:F.string().optional()});class Cl extends NB{context;fetcher;constructor(A,Q,B=E7){super(Q,{schema:D8Q,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=B}async process(A,Q,B){let{filePath:$,sourceUrl:w,postTitle:D,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:$,sourceUrl:w,postSlug:Y});try{await this.reportProgress(B,{progress:GQ.INIT,message:`Reading file: ${$}`});let I;try{I=await $8Q($,"utf-8")}catch(M){return this.logger.error("Failed to read file",{filePath:$,error:L0(M)}),I6.failure(M)}let K;try{K=v4(I)}catch(M){return this.logger.warn("Failed to parse markdown",{filePath:$,error:L0(M)}),I6.failure(M)}let G=K.frontmatter;if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(B,{progress:GQ.FETCH,message:"Checking for existing image"});let W=await this.context.entityService.listEntities("image",{filter:{metadata:{sourceUrl:w}},limit:1}),Z;if(W[0])Z=W[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:w,imageId:Z}),await this.reportProgress(B,{progress:GQ.EXTRACT,message:`Reusing existing image: ${Z}`});else{await this.reportProgress(B,{progress:GQ.PROCESS,message:`Fetching image from ${w}`});let M;try{M=await this.fetcher(w)}catch(n){return this.logger.error("Failed to fetch image",{sourceUrl:w,error:L0(n)}),I6.failure(n)}await this.reportProgress(B,{progress:GQ.GENERATE,message:"Creating image entity"});let{base64:L}=hG(M),_=JF(L),T=gG(L);if(!_||!T)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:w}),I6.failure(Error("Could not detect image format or dimensions"));Z=`${Y}-cover`;let P=`Cover image for ${D}`,r=X??P;await this.context.entityService.createEntity({id:Z,entityType:"image",content:M,metadata:{title:P,alt:r,format:_,width:T.width,height:T.height,sourceUrl:w}}),this.logger.debug("Created image entity",{imageId:Z,sourceUrl:w}),await this.reportProgress(B,{progress:GQ.EXTRACT,message:`Created image: ${Z}`})}await this.reportProgress(B,{progress:GQ.SAVE,message:"Updating file"});let q={...G};delete q.coverImageUrl,delete q.coverImageAlt,q.coverImageId=Z;let N=JZ(q,K.content);try{await w8Q($,N,"utf-8")}catch(M){return this.logger.error("Failed to write file",{filePath:$,error:L0(M)}),I6.failure(M)}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:Z,sourceUrl:w}),{success:!0,imageId:Z}}catch(I){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:L0(I)}),I6.failure(I)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}w0();ZA();import{readFile as Y8Q,writeFile as X8Q}from"fs/promises";class Ol extends NB{converter;constructor(A,Q,B=E7){super(Q,{schema:hN0,jobTypeName:"inline-image-convert"});this.converter=new i_(A.entityService,Q,B)}async process(A,Q,B){let{filePath:$,postSlug:w}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:$,postSlug:w});try{await this.reportProgress(B,{progress:GQ.INIT,message:`Reading file: ${$}`});let D;try{D=await Y8Q($,"utf-8")}catch(I){let K=L0(I);return this.logger.error("Failed to read file",{filePath:$,error:K}),{success:!1,error:K}}await this.reportProgress(B,{progress:GQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(D,w);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:$,count:Y.length}),await this.reportProgress(B,{progress:GQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(D,w);if(!X.converted)return this.logger.debug("No images were converted",{filePath:$}),await this.reportProgress(B,{progress:GQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(B,{progress:GQ.SAVE,message:"Writing updated file"});try{await X8Q($,X.content,"utf-8")}catch(I){let K=L0(I);return this.logger.error("Failed to write file",{filePath:$,error:K}),{success:!1,error:K}}return await this.reportProgress(B,{progress:GQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(D){let Y=L0(D);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:$,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function mN0(A,Q,B){let $=(w)=>B.child(w);A.jobs.registerHandler("directory-sync",new Ll($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new Vl($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new Nl($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new El($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new Ml($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Cl(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Ol(A,$("InlineImageConversionJobHandler"))),B.debug("Registered async job handlers")}w0();import{unlink as I8Q,access as K8Q}from"fs/promises";function uN0(A,Q,B,$){let{subscribe:w}=A.messaging,{entityService:D}=A;w("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),B.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(I){B.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:I instanceof Error?I.message:String(I),stack:I instanceof Error?I.stack:void 0})}return{success:!0}}),w("entity:updated",async(Y)=>{let{entityType:X,entityId:I}=Y.payload;try{let K=await D.getEntity(X,I);if(!K)return B.debug("Entity not found in DB, skipping export",{entityType:X,entityId:I}),{success:!1};await Q.fileOps.writeEntity(K),B.debug("Auto-exported updated entity",{id:K.id,entityType:K.entityType})}catch(K){B.error("Auto-export FAILED for updated entity",{entityType:X,entityId:I,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0})}return{success:!0}}),w("entity:deleted",async(Y)=>{let{entityId:X,entityType:I}=Y.payload,K=Q.fileOps.getFilePath(X,I);if(await K8Q(K).then(()=>!0,()=>!1))await I8Q(K),B.debug("Auto-deleted entity file",{id:X,entityType:I,path:K});return{success:!0}}),B.debug("Setup auto-sync for entity events",{entityTypes:$})}function cN0(A,Q,B){Q.setJobQueueCallback(async($)=>{let w=[{type:$.type,data:$.data}];return A.jobs.enqueueBatch(w,{priority:5,source:"directory-sync-watcher",rootJobId:j6(),metadata:{operationType:"file_operations",operationTarget:B,pluginId:"directory-sync"}})})}ZA();import{access as H8Q,readdir as lN0,mkdir as U8Q,copyFile as G8Q}from"fs/promises";import{exec as J8Q}from"child_process";import{promisify as W8Q}from"util";import{join as oIA,resolve as nIA}from"path";var Z8Q=W8Q(J8Q);async function jl(A){try{return await H8Q(A),!0}catch{return!1}}async function F8Q(A,Q){if(!await jl(A))return!0;if((await lN0(A)).filter((w)=>!w.startsWith(".")&&!w.startsWith("_")).length>0)return!1;if(await q8Q(A))return Q.debug("Git repository with remote detected - skipping seed content",{path:A}),!1;return!0}async function q8Q(A){let Q=oIA(A,".git");if(!await jl(Q))return!1;try{let{stdout:B}=await Z8Q("git remote",{cwd:A});return B.trim().length>0}catch{return!1}}async function pN0(A,Q){let B=await lN0(A,{withFileTypes:!0});for(let $ of B){let w=oIA(A,$.name),D=oIA(Q,$.name);if($.isDirectory()){if(!await jl(D))await U8Q(D,{recursive:!0});await pN0(w,D)}else await G8Q(w,D)}}async function dN0(A,Q,B){let $=nIA(process.cwd(),A);B=B?nIA(B):nIA(process.cwd(),"seed-content");let w=await F8Q($,Q);if(w&&await jl(B))Q.debug("Copying seed content to brain-data directory"),await pN0(B,$),Q.debug("Seed content copied successfully");else if(w)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 z8Q(A,Q,B,$=300000){let D=Date.now();while(Date.now()-D<$){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((X)=>setTimeout(X,500))}B.warn(`Timeout waiting for batch ${Q} after ${$}ms`)}function iN0(A,Q,B,$,w,D){let Y=!1,X=async()=>{if(Y)return;Y=!0;let I=Q();if(B.seedContent){let K=B.syncPath??A.dataDir;await dN0(K,w,B.seedContentPath)}try{if(D){w.debug("Git enabled \u2014 pulling before import");let G=await D.pull();if(G.files.length>0)w.info("Pulled changes from remote",{filesChanged:G.files.length})}w.debug("Starting initial sync");let K=await I.queueSyncBatch(A,"initial-sync",void 0,{includeCleanup:!0});if(!K){w.debug("Initial sync: no files to import"),await A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0});return}w.debug("Initial sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles}),z8Q(A,K.batchId,w).then(()=>A.messaging.send("sync:initial:completed",{success:!0},{broadcast:!0}),(G)=>{w.error("Initial sync batch failed",G),A.messaging.send("sync:initial:completed",{success:!1,error:L0(G)},{broadcast:!0})})}catch(K){w.error("Initial sync failed",K),await A.messaging.send("sync:initial:completed",{success:!1,error:L0(K)},{broadcast:!0})}};A.messaging.subscribe("system:plugins:ready",async()=>{return w.debug("system:plugins:ready received, starting initial sync"),await X(),{success:!0}})}ZA();function rN0(A,Q,B,$){let w=new zZ(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){$.error("Git auto-commit failed",{error:X})}})},B),D=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of D){let I=A.subscribe(X,async()=>{return w.trigger(),{success:!0}});Y.push(I)}return()=>{w.dispose();for(let X of Y)X()}}function nN0(A,Q,B,$,w){if($<=0)return()=>{};let D=$*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:K}=await A.withLock(()=>A.pull());if(K.length>0)w.info("Periodic sync: pulled changes",{filesChanged:K.length});let G=await Q.queueSyncBatch(B,"periodic-sync");if(G)w.debug("Periodic sync: queued imports",{importOperations:G.importOperationsCount,totalFiles:G.totalFiles})}catch(K){w.error("Periodic git sync failed",{error:K})}finally{Y=!1}},I=setInterval(()=>{X()},D);return w.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(I)}}function oN0(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(X){return{success:!1,error:X instanceof Error?X.message:"Export failed"}}}),D("entity:import:request",async(Y)=>{try{let X=Q(),I=Y.payload.paths,K=await X.importEntities(I);if(I&&I.length>0)await X.removeOrphanedEntities();return{success:!0,data:K}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Import failed"}}}),D("sync:status:request",async()=>{try{let X=await Q().getStatus();return{success:!0,data:{syncPath:X.syncPath,isInitialized:X.exists,watchEnabled:X.watching}}}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:"Status check failed"}}}),D("sync:configure:request",async(Y)=>{try{return await B({syncPath:Y.payload.syncPath}),{success:!0,data:{syncPath:Y.payload.syncPath,configured:!0}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Configuration failed"}}}),D("git-sync:get-repo-info",async()=>{if(!w?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:w.repo,branch:w.branch??"main"}}}),$.debug("Registered message handlers")}w0();ZA();w0();ZA();function sN0(A,Q){return g2(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",F.object({entityType:F.string().describe("Entity type (e.g. post, note, link)"),id:F.string().describe("Entity ID"),sha:F.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:F.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(B)=>{let $=`${B.entityType}/${B.id}.md`;try{if(B.sha){let D=await Q.show(B.sha,$);return E9({sha:B.sha,entityType:B.entityType,id:B.id,content:D},`Content at ${B.sha.slice(0,7)}`)}let w=await Q.log($,B.limit);if(w.length===0)return E9({commits:[]},`No history found for ${B.entityType}/${B.id}`);return E9({commits:w,entityType:B.entityType,id:B.id},`${w.length} version${w.length===1?"":"s"} found`)}catch(w){return z5(w instanceof Error?w.message:"History lookup failed")}})}function aN0(A,Q,B,$){let w=[g2(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.",F.object({}),async(D,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${B}`,I={interfaceType:Y.interfaceType,channelId:Y.channelId},K=!1;if($)await $.withLock(()=>$.pull()),K=!0;let G=await A.queueSyncBatch(Q,X,I);if(!G)return E9({gitPulled:K},"No files to sync");return E9({batchId:G.batchId,importOperations:G.importOperationsCount,totalFiles:G.totalFiles,gitPulled:K},`Sync started: ${G.importOperationsCount} import jobs queued for ${G.totalFiles} files${K?" (pulled from git)":""}`)}catch(X){return z5(X instanceof Error?X.message:"Sync failed")}},{cli:{name:"sync"}}),g2(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.",F.object({}),async()=>{try{let D=await A.getStatus(),Y={syncPath:D.syncPath,lastSync:D.lastSync?.toISOString(),watching:D.watching};if($){let X=await $.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return E9(Y)}catch(D){return z5(D instanceof Error?D.message:"Status check failed")}},{visibility:"public"})];if($)w.push(sN0(B,$));return w}var tN0={name:"@brains/directory-sync",private:!0,version:"0.2.0-alpha.32",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 sIA extends f8{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",tN0,A,TN0)}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:$k,basePrompt:"",formatter:new zl,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new r_({syncPath:$,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:$})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let w=this.requireDirectorySync();if(uN0(A,w,this.logger,this.config.entityTypes),this.config.autoSync)cN0(A,w,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 iIA({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(rN0(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(nN0(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)iN0(A,()=>this.requireDirectorySync(),this.config,this.id,this.logger,this.gitSync);oN0(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git)}async getTools(){let A=this.requireDirectorySync();return aN0(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 r_({...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){mN0(A,this.requireDirectorySync(),this.logger)}}function H3(A={}){return new sIA(A)}w0();w0();ZA();ZA();var eN0=F.object({environment:F.enum(["preview","production"]),outputDir:F.string(),workingDir:F.string().optional(),sharedImagesDir:F.string().default("./dist/images"),enableContentGeneration:F.boolean().default(!1),cleanBeforeBuild:F.boolean().default(!0),siteConfig:F.object({title:F.string(),description:F.string(),url:F.string().optional(),copyright:F.string().optional(),themeMode:F.enum(["light","dark"]).optional(),analyticsScript:F.string().optional()}),layouts:F.record(F.any()),themeCSS:F.string().optional()}),mS2=F.object({success:F.boolean(),outputDir:F.string(),filesGenerated:F.number(),routesBuilt:F.number(),errors:F.array(F.string()).optional(),warnings:F.array(F.string()).optional()});import{render as Mk0}from"preact-render-to-string";import{h as S3}from"preact";class aIA{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(`
1680
1680
  `);let{title:Q,description:B,ogImage:$,ogType:w,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="${w??"website"}">`),$)A.push(`<meta property="og:image" content="${this.escapeHtml($)}">`);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($)A.push(`<meta name="twitter:image" content="${this.escapeHtml($)}">`);if(Y)A.push(`<link rel="canonical" href="${this.escapeHtml(Y)}">`);return A.join(`
1681
1681
  `)}escapeHtml(A){let Q={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return A.replace(/[&<>"']/g,(B)=>Q[B]??B)}}function AL0(A){var Q,B,$="";if(typeof A=="string"||typeof A=="number")$+=A;else if(typeof A=="object")if(Array.isArray(A)){var w=A.length;for(Q=0;Q<w;Q++)A[Q]&&(B=AL0(A[Q]))&&($&&($+=" "),$+=B)}else for(B in A)A[B]&&($&&($+=" "),$+=B);return $}function Rl(){for(var A,Q,B=0,$="",w=arguments.length;B<w;B++)(A=arguments[B])&&(Q=AL0(A))&&($&&($+=" "),$+=Q);return $}var N8Q=(A)=>{let Q=E8Q(A),{conflictingClassGroups:B,conflictingClassGroupModifiers:$}=A;return{getClassGroupId:(Y)=>{let X=Y.split("-");if(X[0]===""&&X.length!==1)X.shift();return DL0(X,Q)||L8Q(Y)},getConflictingClassGroupIds:(Y,X)=>{let I=B[Y]||[];if(X&&$[Y])return[...I,...$[Y]];return I}}},DL0=(A,Q)=>{if(A.length===0)return Q.classGroupId;let B=A[0],$=Q.nextPart.get(B),w=$?DL0(A.slice(1),$):void 0;if(w)return w;if(Q.validators.length===0)return;let D=A.join("-");return Q.validators.find(({validator:Y})=>Y(D))?.classGroupId},QL0=/^\[(.+)\]$/,L8Q=(A)=>{if(QL0.test(A)){let Q=QL0.exec(A)[1],B=Q?.substring(0,Q.indexOf(":"));if(B)return"arbitrary.."+B}},E8Q=(A)=>{let{theme:Q,prefix:B}=A,$={nextPart:new Map,validators:[]};return C8Q(Object.entries(A.classGroups),B).forEach(([D,Y])=>{eIA(Y,$,D,Q)}),$},eIA=(A,Q,B,$)=>{A.forEach((w)=>{if(typeof w==="string"){let D=w===""?Q:BL0(Q,w);D.classGroupId=B;return}if(typeof w==="function"){if(M8Q(w)){eIA(w($),Q,B,$);return}Q.validators.push({validator:w,classGroupId:B});return}Object.entries(w).forEach(([D,Y])=>{eIA(Y,BL0(Q,D),B,$)})})},BL0=(A,Q)=>{let B=A;return Q.split("-").forEach(($)=>{if(!B.nextPart.has($))B.nextPart.set($,{nextPart:new Map,validators:[]});B=B.nextPart.get($)}),B},M8Q=(A)=>A.isThemeGetter,C8Q=(A,Q)=>{if(!Q)return A;return A.map(([B,$])=>{let w=$.map((D)=>{if(typeof D==="string")return Q+D;if(typeof D==="object")return Object.fromEntries(Object.entries(D).map(([Y,X])=>[Q+Y,X]));return D});return[B,w]})},O8Q=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,B=new Map,$=new Map,w=(D,Y)=>{if(B.set(D,Y),Q++,Q>A)Q=0,$=B,B=new Map};return{get(D){let Y=B.get(D);if(Y!==void 0)return Y;if((Y=$.get(D))!==void 0)return w(D,Y),Y},set(D,Y){if(B.has(D))B.set(D,Y);else w(D,Y)}}};var j8Q=(A)=>{let{separator:Q,experimentalParseClassName:B}=A,$=Q.length===1,w=Q[0],D=Q.length,Y=(X)=>{let I=[],K=0,G=0,W;for(let L=0;L<X.length;L++){let _=X[L];if(K===0){if(_===w&&($||X.slice(L,L+D)===Q)){I.push(X.slice(G,L)),G=L+D;continue}if(_==="/"){W=L;continue}}if(_==="[")K++;else if(_==="]")K--}let Z=I.length===0?X:X.substring(G),q=Z.startsWith("!"),N=q?Z.substring(1):Z,M=W&&W>G?W-G:void 0;return{modifiers:I,hasImportantModifier:q,baseClassName:N,maybePostfixModifierPosition:M}};if(B)return(X)=>B({className:X,parseClassName:Y});return Y},R8Q=(A)=>{if(A.length<=1)return A;let Q=[],B=[];return A.forEach(($)=>{if($[0]==="[")Q.push(...B.sort(),$),B=[];else B.push($)}),Q.push(...B.sort()),Q},P8Q=(A)=>({cache:O8Q(A.cacheSize),parseClassName:j8Q(A),...N8Q(A)}),_8Q=/\s+/,k8Q=(A,Q)=>{let{parseClassName:B,getClassGroupId:$,getConflictingClassGroupIds:w}=Q,D=[],Y=A.trim().split(_8Q),X="";for(let I=Y.length-1;I>=0;I-=1){let K=Y[I],{modifiers:G,hasImportantModifier:W,baseClassName:Z,maybePostfixModifierPosition:q}=B(K),N=Boolean(q),M=$(N?Z.substring(0,q):Z);if(!M){if(!N){X=K+(X.length>0?" "+X:X);continue}if(M=$(Z),!M){X=K+(X.length>0?" "+X:X);continue}N=!1}let L=R8Q(G).join(":"),_=W?L+"!":L,T=_+M;if(D.includes(T))continue;D.push(T);let P=w(M,N);for(let r=0;r<P.length;++r){let n=P[r];D.push(_+n)}X=K+(X.length>0?" "+X:X)}return X};function f8Q(){let A=0,Q,B,$="";while(A<arguments.length)if(Q=arguments[A++]){if(B=YL0(Q))$&&($+=" "),$+=B}return $}var YL0=(A)=>{if(typeof A==="string")return A;let Q,B="";for(let $=0;$<A.length;$++)if(A[$]){if(Q=YL0(A[$]))B&&(B+=" "),B+=Q}return B};function $L0(A,...Q){let B,$,w,D=Y;function Y(I){let K=Q.reduce((G,W)=>W(G),A());return B=P8Q(K),$=B.cache.get,w=B.cache.set,D=X,X(I)}function X(I){let K=$(I);if(K)return K;let G=k8Q(I,B);return w(I,G),G}return function(){return D(f8Q.apply(null,arguments))}}var V8=(A)=>{let Q=(B)=>B[A]||[];return Q.isThemeGetter=!0,Q},XL0=/^\[(?:([a-z-]+):)?(.+)\]$/i,b8Q=/^\d+\/\d+$/,T8Q=new Set(["px","full","screen"]),x8Q=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,v8Q=/\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$/,S8Q=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,h8Q=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,g8Q=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,zH=(A)=>iL(A)||T8Q.has(A)||b8Q.test(A),OJ=(A)=>rL(A,"length",i8Q),iL=(A)=>Boolean(A)&&!Number.isNaN(Number(A)),tIA=(A)=>rL(A,"number",iL),wk=(A)=>Boolean(A)&&Number.isInteger(Number(A)),y8Q=(A)=>A.endsWith("%")&&iL(A.slice(0,-1)),w2=(A)=>XL0.test(A),jJ=(A)=>x8Q.test(A),m8Q=new Set(["length","size","percentage"]),u8Q=(A)=>rL(A,m8Q,IL0),c8Q=(A)=>rL(A,"position",IL0),l8Q=new Set(["image","url"]),p8Q=(A)=>rL(A,l8Q,n8Q),d8Q=(A)=>rL(A,"",r8Q),Dk=()=>!0,rL=(A,Q,B)=>{let $=XL0.exec(A);if($){if($[1])return typeof Q==="string"?$[1]===Q:Q.has($[1]);return B($[2])}return!1},i8Q=(A)=>v8Q.test(A)&&!S8Q.test(A),IL0=()=>!1,r8Q=(A)=>h8Q.test(A),n8Q=(A)=>g8Q.test(A);var wL0=()=>{let A=V8("colors"),Q=V8("spacing"),B=V8("blur"),$=V8("brightness"),w=V8("borderColor"),D=V8("borderRadius"),Y=V8("borderSpacing"),X=V8("borderWidth"),I=V8("contrast"),K=V8("grayscale"),G=V8("hueRotate"),W=V8("invert"),Z=V8("gap"),q=V8("gradientColorStops"),N=V8("gradientColorStopPositions"),M=V8("inset"),L=V8("margin"),_=V8("opacity"),T=V8("padding"),P=V8("saturate"),r=V8("scale"),n=V8("sepia"),g=V8("skew"),x=V8("space"),S=V8("translate"),h=()=>["auto","contain","none"],t=()=>["auto","hidden","clip","visible","scroll"],c=()=>["auto",w2,Q],UA=()=>[w2,Q],XA=()=>["",zH,OJ],k=()=>["auto",iL,w2],R=()=>["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"],f=()=>["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",w2],i=()=>["auto","avoid","all","avoid-page","page","left","right","column"],HA=()=>[iL,w2];return{cacheSize:500,separator:":",theme:{colors:[Dk],spacing:[zH,OJ],blur:["none","",jJ,w2],brightness:HA(),borderColor:[A],borderRadius:["none","","full",jJ,w2],borderSpacing:UA(),borderWidth:XA(),contrast:HA(),grayscale:e(),hueRotate:HA(),invert:e(),gap:UA(),gradientColorStops:[A],gradientColorStopPositions:[y8Q,OJ],inset:c(),margin:c(),opacity:HA(),padding:UA(),saturate:HA(),scale:HA(),sepia:e(),skew:HA(),space:UA(),translate:UA()},classGroups:{aspect:[{aspect:["auto","square","video",w2]}],container:["container"],columns:[{columns:[jJ]}],"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(),w2]}],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:[M]}],"inset-x":[{"inset-x":[M]}],"inset-y":[{"inset-y":[M]}],start:[{start:[M]}],end:[{end:[M]}],top:[{top:[M]}],right:[{right:[M]}],bottom:[{bottom:[M]}],left:[{left:[M]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",wk,w2]}],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",w2]}],grow:[{grow:e()}],shrink:[{shrink:e()}],order:[{order:["first","last","none",wk,w2]}],"grid-cols":[{"grid-cols":[Dk]}],"col-start-end":[{col:["auto",{span:["full",wk,w2]},w2]}],"col-start":[{"col-start":k()}],"col-end":[{"col-end":k()}],"grid-rows":[{"grid-rows":[Dk]}],"row-start-end":[{row:["auto",{span:[wk,w2]},w2]}],"row-start":[{"row-start":k()}],"row-end":[{"row-end":k()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",w2]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",w2]}],gap:[{gap:[Z]}],"gap-x":[{"gap-x":[Z]}],"gap-y":[{"gap-y":[Z]}],"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:[T]}],px:[{px:[T]}],py:[{py:[T]}],ps:[{ps:[T]}],pe:[{pe:[T]}],pt:[{pt:[T]}],pr:[{pr:[T]}],pb:[{pb:[T]}],pl:[{pl:[T]}],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":[x]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[x]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",w2,Q]}],"min-w":[{"min-w":[w2,Q,"min","max","fit"]}],"max-w":[{"max-w":[w2,Q,"none","full","min","max","fit","prose",{screen:[jJ]},jJ]}],h:[{h:[w2,Q,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[w2,Q,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[w2,Q,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[w2,Q,"auto","min","max","fit"]}],"font-size":[{text:["base",jJ,OJ]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",tIA]}],"font-family":[{font:[Dk]}],"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",w2]}],"line-clamp":[{"line-clamp":["none",iL,tIA]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",zH,w2]}],"list-image":[{"list-image":["none",w2]}],"list-style-type":[{list:["none","disc","decimal",w2]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[A]}],"placeholder-opacity":[{"placeholder-opacity":[_]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[A]}],"text-opacity":[{"text-opacity":[_]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...f(),"wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",zH,OJ]}],"underline-offset":[{"underline-offset":["auto",zH,w2]}],"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",w2]}],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",w2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[_]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[...R(),c8Q]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",u8Q]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},p8Q]}],"bg-color":[{bg:[A]}],"gradient-from-pos":[{from:[N]}],"gradient-via-pos":[{via:[N]}],"gradient-to-pos":[{to:[N]}],"gradient-from":[{from:[q]}],"gradient-via":[{via:[q]}],"gradient-to":[{to:[q]}],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:[X]}],"border-w-x":[{"border-x":[X]}],"border-w-y":[{"border-y":[X]}],"border-w-s":[{"border-s":[X]}],"border-w-e":[{"border-e":[X]}],"border-w-t":[{"border-t":[X]}],"border-w-r":[{"border-r":[X]}],"border-w-b":[{"border-b":[X]}],"border-w-l":[{"border-l":[X]}],"border-opacity":[{"border-opacity":[_]}],"border-style":[{border:[...f(),"hidden"]}],"divide-x":[{"divide-x":[X]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[X]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[_]}],"divide-style":[{divide:f()}],"border-color":[{border:[w]}],"border-color-x":[{"border-x":[w]}],"border-color-y":[{"border-y":[w]}],"border-color-s":[{"border-s":[w]}],"border-color-e":[{"border-e":[w]}],"border-color-t":[{"border-t":[w]}],"border-color-r":[{"border-r":[w]}],"border-color-b":[{"border-b":[w]}],"border-color-l":[{"border-l":[w]}],"divide-color":[{divide:[w]}],"outline-style":[{outline:["",...f()]}],"outline-offset":[{"outline-offset":[zH,w2]}],"outline-w":[{outline:[zH,OJ]}],"outline-color":[{outline:[A]}],"ring-w":[{ring:XA()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[A]}],"ring-opacity":[{"ring-opacity":[_]}],"ring-offset-w":[{"ring-offset":[zH,OJ]}],"ring-offset-color":[{"ring-offset":[A]}],shadow:[{shadow:["","inner","none",jJ,d8Q]}],"shadow-color":[{shadow:[Dk]}],opacity:[{opacity:[_]}],"mix-blend":[{"mix-blend":[...s(),"plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":s()}],filter:[{filter:["","none"]}],blur:[{blur:[B]}],brightness:[{brightness:[$]}],contrast:[{contrast:[I]}],"drop-shadow":[{"drop-shadow":["","none",jJ,w2]}],grayscale:[{grayscale:[K]}],"hue-rotate":[{"hue-rotate":[G]}],invert:[{invert:[W]}],saturate:[{saturate:[P]}],sepia:[{sepia:[n]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[B]}],"backdrop-brightness":[{"backdrop-brightness":[$]}],"backdrop-contrast":[{"backdrop-contrast":[I]}],"backdrop-grayscale":[{"backdrop-grayscale":[K]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[G]}],"backdrop-invert":[{"backdrop-invert":[W]}],"backdrop-opacity":[{"backdrop-opacity":[_]}],"backdrop-saturate":[{"backdrop-saturate":[P]}],"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",w2]}],duration:[{duration:HA()}],ease:[{ease:["linear","in","out","in-out",w2]}],delay:[{delay:HA()}],animate:[{animate:["none","spin","ping","pulse","bounce",w2]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[r]}],"scale-x":[{"scale-x":[r]}],"scale-y":[{"scale-y":[r]}],rotate:[{rotate:[wk,w2]}],"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",w2]}],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",w2]}],"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",w2]}],fill:[{fill:[A,"none"]}],"stroke-w":[{stroke:[zH,OJ,tIA]}],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"]}}},o8Q=(A,{cacheSize:Q,prefix:B,separator:$,experimentalParseClassName:w,extend:D={},override:Y={}})=>{Yk(A,"cacheSize",Q),Yk(A,"prefix",B),Yk(A,"separator",$),Yk(A,"experimentalParseClassName",w);for(let X in Y)s8Q(A[X],Y[X]);for(let X in D)a8Q(A[X],D[X]);return A},Yk=(A,Q,B)=>{if(B!==void 0)A[Q]=B},s8Q=(A,Q)=>{if(Q)for(let B in Q)Yk(A,B,Q[B])},a8Q=(A,Q)=>{if(Q)for(let B in Q){let $=Q[B];if($!==void 0)A[B]=(A[B]||[]).concat($)}},KL0=(A,...Q)=>typeof A==="function"?$L0(wL0,A,...Q):$L0(()=>o8Q(wL0(),A),...Q);var t8Q=KL0({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 l1(...A){return t8Q(Rl(A))}var HL0=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,UL0=Rl,gB=(A,Q)=>(B)=>{var $;if((Q===null||Q===void 0?void 0:Q.variants)==null)return UL0(A,B===null||B===void 0?void 0:B.class,B===null||B===void 0?void 0:B.className);let{variants:w,defaultVariants:D}=Q,Y=Object.keys(w).map((K)=>{let G=B===null||B===void 0?void 0:B[K],W=D===null||D===void 0?void 0:D[K];if(G===null)return null;let Z=HL0(G)||HL0(W);return w[K][Z]}),X=B&&Object.entries(B).reduce((K,G)=>{let[W,Z]=G;if(Z===void 0)return K;return K[W]=Z,K},{}),I=Q===null||Q===void 0?void 0:($=Q.compoundVariants)===null||$===void 0?void 0:$.reduce((K,G)=>{let{class:W,className:Z,...q}=G;return Object.entries(q).every((N)=>{let[M,L]=N;return Array.isArray(L)?L.includes({...D,...X}[M]):{...D,...X}[M]===L})?[...K,W,Z]:K},[]);return UL0(A,Y,I,B===null||B===void 0?void 0:B.class,B===null||B===void 0?void 0:B.className)};import{jsxDEV as AKA}from"preact/jsx-dev-runtime";var GL0=gB("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 QKA({variant:A,title:Q,children:B,className:$}){return AKA("div",{className:l1(GL0({variant:A}),$),role:"alert",children:[Q&&AKA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),AKA("div",{className:l1(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 e8Q}from"preact/jsx-dev-runtime";var JL0=gB("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 U3({variant:A,size:Q,className:B,children:$,ssrOnClick:w,type:D="button",...Y}){return e8Q("button",{type:D,className:l1(JL0({variant:A,size:Q}),B),...Y,...w&&{onclick:w},children:$},void 0,!1,void 0,this)}import{jsxDEV as A6Q}from"preact/jsx-dev-runtime";var WL0=gB("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 G9({href:A,children:Q,variant:B,size:$,external:w=!1,className:D,"aria-label":Y}){let X=w?{target:"_blank",rel:"noopener noreferrer"}:{};return A6Q("a",{href:A,className:l1(WL0({variant:B,size:$}),D),"aria-label":Y,...X,children:Q},void 0,!1,void 0,this)}import{jsxDEV as Pl}from"preact/jsx-dev-runtime";var ZL0=gB("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"}}),Q6Q={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function nL({variant:A,size:Q,className:B}){let $=Q6Q[Q??"md"];return Pl("button",{onclick:"toggleTheme()",type:"button",className:l1(ZL0({variant:A,size:Q}),B),"aria-label":"Toggle dark mode",children:Pl("svg",{className:l1($,"transition-colors"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[Pl("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),Pl("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 BKA}from"preact/jsx-dev-runtime";var FL0=gB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function _l({items:A,className:Q,linkClassName:B="hover:text-accent transition-colors",orientation:$,children:w}){if(A.length===0&&!w)return null;let D=[...A].sort((Y,X)=>Y.priority-X.priority);return BKA("ul",{className:l1(FL0({orientation:$}),Q),children:[D.map((Y)=>BKA("li",{children:BKA("a",{href:Y.href,className:B,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),w]},void 0,!0,void 0,this)}import{jsxDEV as qh2}from"preact/jsx-dev-runtime";import{jsxDEV as Nh2}from"preact/jsx-dev-runtime";ZA();ZA();import{createContext as B6Q,h as $6Q}from"preact";import{useContext as w6Q}from"preact/hooks";var qL0=B6Q(null);function kl({imageRenderer:A,children:Q}){return $6Q(qL0.Provider,{value:A??null},Q)}function zL0(){return w6Q(qL0)}function G3(){let A=zL0();return(Q)=>Ox(Q,A?{imageRenderer:A}:void 0)}import{jsxDEV as VH}from"preact/jsx-dev-runtime";var $KA=({markdown:A})=>{let Q=G3(),$=A.split(/^---$/gm).map((Y)=>Y.trim()).map((Y)=>{let{attributes:X,markdown:I}=rx(Y),K=nx(I),G;if(K)G=`<div class="slide-columns">${K.map((Z)=>`<div class="slide-column">${iC(Q(Z.trim()))}</div>`).join("")}</div>`;else G=iC(Q(I));return{attributes:X,htmlContent:G}}),w=$.some((Y)=>Y.htmlContent.includes('class="mermaid"')),D=$.map(({attributes:Y,htmlContent:X},I)=>VH("section",{...Y,dangerouslySetInnerHTML:{__html:X}},I,!1,void 0,this));return VH("section",{className:"presentation-section",children:[VH("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),VH("div",{className:"reveal",children:VH("div",{className:"slides",children:D},void 0,!1,void 0,this)},void 0,!1,void 0,this),VH("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),w&&VH("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),VH("script",{dangerouslySetInnerHTML:{__html:`
1682
1682
  window.addEventListener('DOMContentLoaded', () => {
@@ -2394,7 +2394,7 @@ ${Q.join(`
2394
2394
  `+w:B,Y=ZI(this.outputDir,"styles","main.css");await this.cssProcessor.process(D,Y,this.workingDir,this.outputDir,this.logger);let X=await T5.readFile(Y,"utf-8"),I=$.length>0?$:Q;if(I.length>0){let K=I.join(`
2395
2395
  `)+`
2396
2396
 
2397
- `+X;await T5.writeFile(Y,K,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=ZI(process.cwd(),"public");try{await T5.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await T5.readdir(A,{withFileTypes:!0});for(let B of Q){let $=ZI(A,B.name),w=ZI(this.outputDir,B.name);if(B.isDirectory())await this.copyDirectory($,w);else await T5.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,$])=>{let w=B.startsWith("/")?B.slice(1):B,D=ZI(this.outputDir,w);await T5.mkdir(EUQ(D),{recursive:!0}),await T5.writeFile(D,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${w}`)}))}async copyDirectory(A,Q){await T5.mkdir(Q,{recursive:!0});let B=await T5.readdir(A,{withFileTypes:!0});for(let $ of B){let w=ZI(A,$.name),D=ZI(Q,$.name);if($.isDirectory())await this.copyDirectory(w,D);else await T5.copyFile(w,D)}}}function hUA(A){return new Ck0(A)}function MUQ(A,Q){let B=new Map;for(let $ of A.sections){let w=Q.getViewTemplate($.template);if(!w?.runtimeScripts)continue;for(let D of w.runtimeScripts)if(!B.has(D.src))B.set(D.src,D)}return[...B.values()].map(($)=>{let w=[`src="${$.src}"`];if($.defer)w.push("defer");if($.module)w.push('type="module"');return`<script ${w.join(" ")}></script>`})}import{join as sZQ}from"path";ZA();class gUA{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 w of Q)if(w.sourceEntityType)this.routeRegistry.unregister(w.path),B++;if(B>0)A.debug(`Cleared ${B} dynamic routes before regeneration`);let $=this.context.entityService.getEntityTypes();A.debug(`Found ${$.length} entity types`,{entityTypes:$});for(let w of $)await this.generateRoutesForEntityType(w)}async generateRoutesForEntityType(A){let Q=this.context.logger.child("DynamicRouteGenerator"),{listTemplateName:B,detailTemplateName:$}=this.findTemplatesForEntityType(A);if(!B&&!$){Q.debug(`No matching templates found for entity type: ${A}`);return}if(Q.debug(`Generating routes for entity type: ${A}`,{listTemplate:B,detailTemplate:$}),B){let{pluralName:w,label:D,layout:Y,paginate:X,pageSize:I,navigation:K}=this.getEntityDisplayConfig(A);if(X)await this.generatePaginatedRoutes(A,B,w,D,Y,I,K,Q);else{let G={id:`${A}-index`,path:`/${w}`,title:D,description:`Browse all ${w}`,...Y&&{layout:Y},navigation:{show:K.show,label:D,slot:K.slot,priority:K.priority},sections:[{id:"list",template:B,dataQuery:{entityType:A,query:{limit:100}}}],sourceEntityType:A};try{this.routeRegistry.register(G),Q.debug(`Registered index route for ${A}`,{path:G.path})}catch(W){Q.warn(`Failed to register index route for ${A}`,{error:W})}}}if($)try{let w=await this.context.entityService.listEntities(A,{limit:1000});Q.debug(`Found ${w.length} ${A} entities to generate routes for`);let{pluralName:D,layout:Y}=this.getEntityDisplayConfig(A);for(let I of w){let K="slug"in I.metadata?I.metadata.slug:I.id,G={id:`${A}-${I.id}`,path:`/${D}/${K}`,title:`${this.capitalize(A)}: ${K}`,description:`View ${A} details`,...Y&&{layout:Y},sections:[{id:"detail",template:$,dataQuery:{entityType:A,query:{id:K}}}],sourceEntityType:A};try{this.routeRegistry.register(G)}catch(W){Q.warn(`Failed to register detail route for ${A}/${I.id}`,{error:W})}}let X=B?w.length+1:w.length;Q.debug(`Successfully registered ${X} routes for ${A}`)}catch(w){Q.error(`Failed to list entities for type: ${A}`,{error:w})}}async generatePaginatedRoutes(A,Q,B,$,w,D,Y,X){let K=(await this.context.entityService.listEntities(A,{limit:1000})).length,G=Math.max(1,Math.ceil(K/D));X.debug(`Generating ${G} paginated routes for ${A}`,{totalItems:K,pageSize:D});for(let W=1;W<=G;W++){let Z=W===1,q=Z?`/${B}`:`/${B}/page/${W}`,N={id:`${A}-index${Z?"":`-page-${W}`}`,path:q,title:Z?$:`${$} - Page ${W}`,description:`Browse all ${B}${Z?"":` - Page ${W}`}`,...w&&{layout:w},navigation:Z?{show:Y.show,label:$,slot:Y.slot,priority:Y.priority}:void 0,sections:[{id:"list",template:Q,dataQuery:{entityType:A,query:{page:W,pageSize:D,baseUrl:`/${B}`}}}],sourceEntityType:A};try{this.routeRegistry.register(N),X.debug(`Registered paginated route for ${A}`,{path:N.path,page:W})}catch(M){X.warn(`Failed to register paginated route for ${A} page ${W}`,{error:M})}}}findTemplatesForEntityType(A){let Q=this.context.views.list(),B,$,w=`${A}-list`,D=`${A}-detail`;for(let X of Q){let I=X.name;if(I.endsWith(w)){let K=I.slice(0,-w.length);if(K===""||K.endsWith(":"))B=I}if(I.endsWith(D)){let K=I.slice(0,-D.length);if(K===""||K.endsWith(":"))$=I}}let Y={};if(B)Y.listTemplateName=B;if($)Y.detailTemplateName=$;return Y}getEntityDisplayConfig(A){let Q=this.entityDisplay?.[A],B=10,$=!0,w=!0,D="primary",Y=40;if(Q){let I=Q.pluralName??Vw(Q.label.toLowerCase()),K=this.capitalize(Vw(Q.label.toLowerCase()));return{pluralName:I,label:K,...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 X=Vw(A);return{pluralName:X,label:this.capitalize(X),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(" ")}}w0();ZA();w0();var Ok0=F.object({}),Uf=FQ.extend({id:F.literal("site-info"),entityType:F.literal("site-info"),metadata:Ok0}),Gf=F.object({heading:F.string().describe("Main CTA heading text"),buttonText:F.string().describe("Call-to-action button text"),buttonLink:F.string().describe("URL or anchor for the CTA button")}),FI=F.object({title:F.string().describe("The site's title"),description:F.string().describe("The site's description"),copyright:F.string().optional().describe("Copyright notice text"),logo:F.boolean().optional().describe("Whether to display logo instead of title text in header"),themeMode:F.enum(["light","dark"]).optional().describe("Default theme mode"),cta:Gf.optional().describe("Call-to-action configuration")});w0();class SY extends _Q{constructor(){super({entityType:"site-info",schema:Uf,frontmatterSchema:FI,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=FI.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 qI{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,B){return qI.instance??=new qI(A,Q,B),qI.instance}static resetInstance(){qI.instance=null}static createFresh(A,Q,B){return new qI(A,Q,B)}constructor(A,Q,B){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new SY;let $=qI.getDefaultSiteInfo();this.defaultSiteInfo={...$,...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 CUQ=new SY;class zd{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:$}=B,w;try{let X=await $.getEntity("site-info","site-info");w=X?CUQ.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{w={title:"Brain",description:"A knowledge management system"}}let D;try{let X=await $.getEntity("anchor-profile","anchor-profile");if(X)D=X.metadata.socialLinks}catch{}let Y={...w,socialLinks:D,copyright:w.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var jk0={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.31",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 jUQ=new SY;class yUA extends z2{entityType="site-info";schema=Uf;adapter=jUQ;defaultSiteInfo;constructor(A){super("site-info",jk0);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new zd(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=qI.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function h3(A){return new yUA(A)}var RUQ=new SY;async function vH(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 RUQ.parseSiteInfoBody(B.content)}ZA();var PUQ=FI.extend({navigation:F.object({primary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()})),secondary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()}))}),copyright:F.string(),socialLinks:F.array(F.object({platform:F.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:F.string().describe("Profile or contact URL"),label:F.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});async function Rk0(A,Q,B){let $;try{$=await vH(A)}catch{$={title:"Brain",description:"A knowledge management system"}}let w=Q.getProfile(),D=B.getNavigationItems("primary"),Y=B.getNavigationItems("secondary");return{...$,socialLinks:w.socialLinks,navigation:{primary:D,secondary:Y},copyright:$.copyright??"Powered by Rizom"}}ZA();ZA();import{promises as ab0}from"fs";import{join as oZQ}from"path";import{createHash as pZQ}from"crypto";import{promises as GGA}from"fs";import{join as rb0}from"path";var nb0=null;async function dZQ(){return nb0??=Promise.resolve().then(() => o0(ib0(),1)).then((A)=>A.default),nb0}var iZQ=[480,960,1920],rZQ=80,nZQ="(max-width: 640px) 480px, (max-width: 1280px) 960px, 1920px";class JGA{imagesDir;logger;constructor(A,Q){this.imagesDir=A;this.logger=Q.child("ImageOptimizer")}async optimize(A,Q){try{let B=await dZQ(),$=pZQ("sha256").update(A).digest("hex").slice(0,16),w=await B(A).metadata();if(!w.width||!w.height)return this.logger.warn("Could not determine image dimensions",{originalUrl:Q}),null;let{width:D,height:Y}=w,X=[];for(let W of iZQ){if(W>D)continue;let Z=`${$}-${W}w.webp`,q=rb0(this.imagesDir,Z),N=`/images/${Z}`;if(await GGA.access(q).then(()=>!0).catch(()=>!1)){this.logger.debug("Cache hit, skipping optimization",{fileName:Z}),X.push({width:W,url:N});continue}await B(A).resize(W,null,{withoutEnlargement:!0}).webp({quality:rZQ}).toFile(q),X.push({width:W,url:N}),this.logger.debug("Created WebP variant",{fileName:Z,width:W})}if(X.length===0)return null;let I=X[X.length-1];if(!I)return null;let K=X.find((W)=>W.width===960)??I,G=Math.round(Y*(K.width/D));return{src:K.url,srcset:X.map((W)=>`${W.url} ${W.width}w`).join(", "),sizes:nZQ,width:K.width,height:G}}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 GGA.readdir(this.imagesDir,{withFileTypes:!0})}catch{return this.logger.debug("Images directory does not exist, nothing to optimize"),A}let B=Q.filter(($)=>$.isFile()&&/\.(png|jpe?g)$/i.test($.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 $ of B){let w=rb0(this.imagesDir,$.name),D=`/images/${$.name}`;try{let Y=await GGA.readFile(w),X=await this.optimize(Y,D);if(X)A[D]=X}catch(Y){this.logger.warn("Failed to optimize image",{file:$.name,error:Y instanceof Error?Y.message:String(Y)})}}return this.logger.debug(`Optimized ${Object.keys(A).length}/${B.length} images`),A}}function ob0(A,Q){if(A.format)return A.format;return Q.match(/^data:image\/([^;]+);/)?.[1]??"png"}function sb0(A){return A.match(/^data:image\/[^;]+;base64,(.+)$/)?.[1]??null}function RE(A){return A.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}class WGA{entityService;logger;imageMap={};imagesDir;optimizer;constructor(A,Q,B){this.entityService=A;this.logger=Q.child("ImageBuildService"),this.imagesDir=B,this.optimizer=new JGA(this.imagesDir,this.logger)}async resolveAll(A){let Q=[...new Set(A)];if(Q.length===0)return;await ab0.mkdir(this.imagesDir,{recursive:!0});let B=WZ(4);await Promise.all(Q.map(($)=>B(async()=>{try{await this.resolveImage($)}catch(w){this.logger.warn("Failed to resolve image",{imageId:$,error:w instanceof Error?w.message:String(w)})}}))),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=sb0(Q.content);if(!B){this.logger.warn("Could not extract base64 from image",{imageId:A});return}let $=Buffer.from(B,"base64"),w=ob0(Q.metadata,Q.content),D=`${A}.${w}`,Y=oZQ(this.imagesDir,D);await ab0.writeFile(Y,$);let X=`/images/${D}`,I=await this.optimizer.optimize($,X);if(I)this.imageMap[A]={src:I.src,srcset:I.srcset,sizes:I.sizes,width:I.width,height:I.height};else this.imageMap[A]={src:X,width:Q.metadata.width??0,height:Q.metadata.height??0};this.logger.debug("Resolved image",{imageId:A,optimized:Boolean(I)})}get(A){return this.imageMap[A]}getMap(){return this.imageMap}createImageRenderer(){let A=this.imageMap;return(Q,B,$)=>{let w=/^entity:\/\/image\/(.+)$/.exec(Q);if(!w?.[1])return;let D=A[w[1]];if(!D)return;let Y=[`src="${RE(D.src)}"`,`alt="${RE($)}"`];if(D.srcset)Y.push(`srcset="${RE(D.srcset)}"`);if(D.sizes)Y.push(`sizes="${RE(D.sizes)}"`);if(D.width)Y.push(`width="${D.width}"`);if(D.height)Y.push(`height="${D.height}"`);if(B)Y.push(`title="${RE(B)}"`);return Y.push('loading="lazy"'),Y.push('decoding="async"'),`<img ${Y.join(" ")}>`}}}var aZQ=FQ.extend({metadata:F.object({slug:F.string()}).passthrough()});class ow{static instance=null;static defaultStaticSiteBuilderFactory=hUA;logger;context;staticSiteBuilderFactory;routeRegistry;profileService;entityDisplay;imageBuildService=null;static setDefaultStaticSiteBuilderFactory(A){ow.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,B,$,w){return ow.instance??=new ow(A,ow.defaultStaticSiteBuilderFactory,Q,B,$,w),ow.instance}static resetInstance(){ow.instance=null}static createFresh(A,Q,B,$,w,D){return new ow(A,w??ow.defaultStaticSiteBuilderFactory,Q,B,$,D)}constructor(A,Q,B,$,w,D){this.logger=A,this.context=B,this.staticSiteBuilderFactory=Q,this.routeRegistry=$,this.profileService=w,this.entityDisplay=D,L7.getInstance().configure(D)}async getSiteInfo(){return Rk0(this.context.entityService,this.profileService,this.routeRegistry)}async build(A,Q){let B=eN0.parse(A),$=n5.from(Q),w=[],D=[];try{await $?.report({message:"Starting site build",progress:0,total:100}),await $?.report({message:"Generating dynamic routes",progress:10,total:100}),await new gUA(this.context,this.routeRegistry,this.entityDisplay).generateEntityRoutes();let X=B.workingDir??sZQ(B.outputDir,".preact-work"),I=this.staticSiteBuilderFactory({logger:this.logger.child("StaticSiteBuilder"),workingDir:X,outputDir:B.outputDir});if(B.cleanBeforeBuild)await I.clean();let K=this.routeRegistry.list();if(K.length===0)D.push("No routes registered for site build");await $?.report({message:`Building ${K.length} routes`,progress:20,total:100}),await $?.report({message:"Resolving images",progress:25,total:100}),this.imageBuildService=new WGA(this.context.entityService,this.logger,B.sharedImagesDir);let G=await this.collectAllImageIds();if(G.length>0)await this.imageBuildService.resolveAll(G);let W=B.siteConfig,Z={routes:K,pluginContext:this.context,siteConfig:{title:W.title,description:W.description,...W.url&&{url:W.url},...W.copyright&&{copyright:W.copyright},...W.themeMode&&{themeMode:W.themeMode},...W.analyticsScript&&{analyticsScript:W.analyticsScript}},headScripts:A.headScripts,...A.staticAssets&&{staticAssets:A.staticAssets},getContent:async(_,T)=>{let P=B.environment==="production";return this.getContentForSection(T,_,P)},getViewTemplate:(_)=>{return this.context.views.get(_)},layouts:B.layouts,getSiteInfo:async()=>{return this.getSiteInfo()},...B.themeCSS!==void 0&&{themeCSS:B.themeCSS},...A.slots&&{slots:A.slots},imageBuildService:this.imageBuildService},q=0,N=K.length+4;await I.build(Z,(_)=>{q++;let T=85+Math.round(q/N*10);$?.report({message:_,progress:T,total:100}).catch(()=>{})}),await $?.report({message:"Site build complete",progress:100,total:100});let M=K.length+1,L={success:w.length===0,outputDir:B.outputDir,filesGenerated:M,routesBuilt:K.length};if(w.length>0)L.errors=w;if(D.length>0)L.warnings=D;return L}catch(Y){let X=Error("Site build process failed");return this.logger.error("Site build failed",{error:X,originalError:Y}),w.push(X.message),{success:!1,outputDir:B.outputDir,filesGenerated:0,routesBuilt:0,errors:w}}}async getContentForSection(A,Q,B){if(!A.template)return A.content??null;let $=A.template,w=L7.getInstance();if(A.dataQuery){let Y={dataParams:A.dataQuery,fallback:A.content,publishedOnly:B},X=await this.context.templates.resolve($,Y);if(X)return this.enrichWithUrls(X,w);return null}let D=await this.context.templates.resolve($,{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content});if(D)return this.enrichWithUrls(D,w);return null}async enrichWithUrls(A,Q){if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((P)=>this.enrichWithUrls(P,Q)));if(typeof A!=="object")return A;let B=A,$={},w=Object.entries(B),D=await Promise.all(w.map(([,P])=>this.enrichWithUrls(P,Q)));for(let P=0;P<w.length;P++){let r=w[P];if(r)$[r[0]]=D[P]}let Y=aZQ.safeParse(B);if(!Y.success)return $;let X=Y.data,I=X.entityType,K=X.metadata.slug,G=this.entityDisplay?.[I],W=G?G.label:I.charAt(0).toUpperCase()+I.slice(1),Z=G?G.pluralName??G.label.toLowerCase()+"s":Vw(I),q=`/${Z}`,N=Z.charAt(0).toUpperCase()+Z.slice(1),M=uR(X),L=M?this.imageBuildService?.get(M):void 0,_={};if(L)_={coverImageUrl:L.src,coverImageWidth:L.width,coverImageHeight:L.height,...L.srcset&&{coverImageSrcset:L.srcset,coverImageSizes:L.sizes}};else{let P=await cR(X,this.context.entityService);if(P)_={coverImageUrl:P.url,coverImageWidth:P.width,coverImageHeight:P.height}}return{...$,...X,url:Q.generateUrl(I,K),typeLabel:W,listUrl:q,listLabel:N,..._}}async collectAllImageIds(){let A=new Set;try{let Q=this.context.entityService.getEntityTypes();for(let B of Q){if(B==="image")continue;let $=await this.context.entityService.listEntities(B);for(let w of $){let D=uR(w);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]}}w0();class ZGA{logger;routes=new Map;constructor(A){this.logger=A}register(A){let Q=Array.isArray(A)?A:[A];for(let B of Q){let $=AV.parse(B);if(this.routes.has($.path)){let w=this.routes.get($.path);this.logger.debug(`Overriding route "${$.path}" (was registered by plugin "${w?.pluginId}")`)}this.routes.set($.path,$)}}unregister(A){(Array.isArray(A)?A:[A]).forEach((B)=>this.routes.delete(B))}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,$]of this.routes.entries())if($.navigation?.show&&$.navigation.slot===A)Q.push({label:$.navigation.label??$.title,href:B,priority:$.navigation.priority});return Q.sort((B,$)=>B.priority-$.priority)}}class Sd{slots=new Map;register(A,Q){let B={...Q,priority:Q.priority??50},$=this.slots.get(A)??[];$.push(B),this.slots.set(A,$)}getSlot(A){return[...this.slots.get(A)??[]].sort((B,$)=>$.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 $=B.filter((w)=>w.pluginId!==Q);if($.length>0)this.slots.set(A,$);else this.slots.delete(A)}unregisterAll(A){for(let[Q,B]of this.slots){let $=B.filter((w)=>w.pluginId!==A);if($.length>0)this.slots.set(Q,$);else this.slots.delete(Q)}}getSlotNames(){return Array.from(this.slots.keys())}clear(){this.slots.clear()}}ZA();class FGA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,B,$){this.config=A;this.context=Q;this.pluginId=B;this.logger=$}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),B=this.debounces.get(Q);if(!B)B=new zZ(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,B);B.trigger()}setupAutoRebuild(){let A=new Set(["base"]),Q=async($)=>{let{entityType:w}=$.payload;if(!A.has(w))this.logger.debug(`Entity type ${w} will trigger rebuild`),this.requestBuild();return{success:!0}},B=["entity:created","entity:updated","entity:deleted"];for(let $ of B)this.unsubscribeFunctions.push(this.context.messaging.subscribe($,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})}}}w0();function tZQ(A,Q){return A.map((B)=>({...B,template:B.template.includes(":")?B.template:`${Q}:${B.template}`}))}function hd(A,Q,B){for(let $ of A)B.register({...$,pluginId:Q,sections:$.sections?tZQ($.sections,Q):[]})}function tb0(A,Q,B){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let w=Qe.parse($.payload),{routes:D,pluginId:Y}=w;return hd(D,Y,Q),{success:!0}}catch(w){return B.error("Failed to register routes",{error:w}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async($)=>{try{let w=Be.parse($.payload),{paths:D,pluginId:Y}=w;if(D)for(let X of D)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch(w){return B.error("Failed to unregister routes",{error:w}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async($)=>{try{let w=$e.parse($.payload);return{success:!0,data:{routes:Q.list(w.pluginId?w:void 0)}}}catch(w){return B.error("Failed to list routes",{error:w}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async($)=>{try{let w=we.parse($.payload);return{success:!0,data:{route:Q.get(w.path)}}}catch(w){return B.error("Failed to get route",{error:w}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}ZA();import{promises as Nf}from"fs";import{join as Lf}from"path";function eb0(A,Q){if(Q==="preview")return`User-agent: *
2397
+ `+X;await T5.writeFile(Y,K,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=ZI(process.cwd(),"public");try{await T5.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await T5.readdir(A,{withFileTypes:!0});for(let B of Q){let $=ZI(A,B.name),w=ZI(this.outputDir,B.name);if(B.isDirectory())await this.copyDirectory($,w);else await T5.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,$])=>{let w=B.startsWith("/")?B.slice(1):B,D=ZI(this.outputDir,w);await T5.mkdir(EUQ(D),{recursive:!0}),await T5.writeFile(D,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${w}`)}))}async copyDirectory(A,Q){await T5.mkdir(Q,{recursive:!0});let B=await T5.readdir(A,{withFileTypes:!0});for(let $ of B){let w=ZI(A,$.name),D=ZI(Q,$.name);if($.isDirectory())await this.copyDirectory(w,D);else await T5.copyFile(w,D)}}}function hUA(A){return new Ck0(A)}function MUQ(A,Q){let B=new Map;for(let $ of A.sections){let w=Q.getViewTemplate($.template);if(!w?.runtimeScripts)continue;for(let D of w.runtimeScripts)if(!B.has(D.src))B.set(D.src,D)}return[...B.values()].map(($)=>{let w=[`src="${$.src}"`];if($.defer)w.push("defer");if($.module)w.push('type="module"');return`<script ${w.join(" ")}></script>`})}import{join as sZQ}from"path";ZA();class gUA{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 w of Q)if(w.sourceEntityType)this.routeRegistry.unregister(w.path),B++;if(B>0)A.debug(`Cleared ${B} dynamic routes before regeneration`);let $=this.context.entityService.getEntityTypes();A.debug(`Found ${$.length} entity types`,{entityTypes:$});for(let w of $)await this.generateRoutesForEntityType(w)}async generateRoutesForEntityType(A){let Q=this.context.logger.child("DynamicRouteGenerator"),{listTemplateName:B,detailTemplateName:$}=this.findTemplatesForEntityType(A);if(!B&&!$){Q.debug(`No matching templates found for entity type: ${A}`);return}if(Q.debug(`Generating routes for entity type: ${A}`,{listTemplate:B,detailTemplate:$}),B){let{pluralName:w,label:D,layout:Y,paginate:X,pageSize:I,navigation:K}=this.getEntityDisplayConfig(A);if(X)await this.generatePaginatedRoutes(A,B,w,D,Y,I,K,Q);else{let G={id:`${A}-index`,path:`/${w}`,title:D,description:`Browse all ${w}`,...Y&&{layout:Y},navigation:{show:K.show,label:D,slot:K.slot,priority:K.priority},sections:[{id:"list",template:B,dataQuery:{entityType:A,query:{limit:100}}}],sourceEntityType:A};try{this.routeRegistry.register(G),Q.debug(`Registered index route for ${A}`,{path:G.path})}catch(W){Q.warn(`Failed to register index route for ${A}`,{error:W})}}}if($)try{let w=await this.context.entityService.listEntities(A,{limit:1000});Q.debug(`Found ${w.length} ${A} entities to generate routes for`);let{pluralName:D,layout:Y}=this.getEntityDisplayConfig(A);for(let I of w){let K="slug"in I.metadata?I.metadata.slug:I.id,G={id:`${A}-${I.id}`,path:`/${D}/${K}`,title:`${this.capitalize(A)}: ${K}`,description:`View ${A} details`,...Y&&{layout:Y},sections:[{id:"detail",template:$,dataQuery:{entityType:A,query:{id:K}}}],sourceEntityType:A};try{this.routeRegistry.register(G)}catch(W){Q.warn(`Failed to register detail route for ${A}/${I.id}`,{error:W})}}let X=B?w.length+1:w.length;Q.debug(`Successfully registered ${X} routes for ${A}`)}catch(w){Q.error(`Failed to list entities for type: ${A}`,{error:w})}}async generatePaginatedRoutes(A,Q,B,$,w,D,Y,X){let K=(await this.context.entityService.listEntities(A,{limit:1000})).length,G=Math.max(1,Math.ceil(K/D));X.debug(`Generating ${G} paginated routes for ${A}`,{totalItems:K,pageSize:D});for(let W=1;W<=G;W++){let Z=W===1,q=Z?`/${B}`:`/${B}/page/${W}`,N={id:`${A}-index${Z?"":`-page-${W}`}`,path:q,title:Z?$:`${$} - Page ${W}`,description:`Browse all ${B}${Z?"":` - Page ${W}`}`,...w&&{layout:w},navigation:Z?{show:Y.show,label:$,slot:Y.slot,priority:Y.priority}:void 0,sections:[{id:"list",template:Q,dataQuery:{entityType:A,query:{page:W,pageSize:D,baseUrl:`/${B}`}}}],sourceEntityType:A};try{this.routeRegistry.register(N),X.debug(`Registered paginated route for ${A}`,{path:N.path,page:W})}catch(M){X.warn(`Failed to register paginated route for ${A} page ${W}`,{error:M})}}}findTemplatesForEntityType(A){let Q=this.context.views.list(),B,$,w=`${A}-list`,D=`${A}-detail`;for(let X of Q){let I=X.name;if(I.endsWith(w)){let K=I.slice(0,-w.length);if(K===""||K.endsWith(":"))B=I}if(I.endsWith(D)){let K=I.slice(0,-D.length);if(K===""||K.endsWith(":"))$=I}}let Y={};if(B)Y.listTemplateName=B;if($)Y.detailTemplateName=$;return Y}getEntityDisplayConfig(A){let Q=this.entityDisplay?.[A],B=10,$=!0,w=!0,D="primary",Y=40;if(Q){let I=Q.pluralName??Vw(Q.label.toLowerCase()),K=this.capitalize(Vw(Q.label.toLowerCase()));return{pluralName:I,label:K,...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 X=Vw(A);return{pluralName:X,label:this.capitalize(X),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(" ")}}w0();ZA();w0();var Ok0=F.object({}),Uf=FQ.extend({id:F.literal("site-info"),entityType:F.literal("site-info"),metadata:Ok0}),Gf=F.object({heading:F.string().describe("Main CTA heading text"),buttonText:F.string().describe("Call-to-action button text"),buttonLink:F.string().describe("URL or anchor for the CTA button")}),FI=F.object({title:F.string().describe("The site's title"),description:F.string().describe("The site's description"),copyright:F.string().optional().describe("Copyright notice text"),logo:F.boolean().optional().describe("Whether to display logo instead of title text in header"),themeMode:F.enum(["light","dark"]).optional().describe("Default theme mode"),cta:Gf.optional().describe("Call-to-action configuration")});w0();class SY extends _Q{constructor(){super({entityType:"site-info",schema:Uf,frontmatterSchema:FI,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=FI.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 qI{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,B){return qI.instance??=new qI(A,Q,B),qI.instance}static resetInstance(){qI.instance=null}static createFresh(A,Q,B){return new qI(A,Q,B)}constructor(A,Q,B){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new SY;let $=qI.getDefaultSiteInfo();this.defaultSiteInfo={...$,...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 CUQ=new SY;class zd{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:$}=B,w;try{let X=await $.getEntity("site-info","site-info");w=X?CUQ.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{w={title:"Brain",description:"A knowledge management system"}}let D;try{let X=await $.getEntity("anchor-profile","anchor-profile");if(X)D=X.metadata.socialLinks}catch{}let Y={...w,socialLinks:D,copyright:w.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var jk0={name:"@brains/site-info",private:!0,version:"0.2.0-alpha.32",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 jUQ=new SY;class yUA extends z2{entityType="site-info";schema=Uf;adapter=jUQ;defaultSiteInfo;constructor(A){super("site-info",jk0);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new zd(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=qI.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function h3(A){return new yUA(A)}var RUQ=new SY;async function vH(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 RUQ.parseSiteInfoBody(B.content)}ZA();var PUQ=FI.extend({navigation:F.object({primary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()})),secondary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()}))}),copyright:F.string(),socialLinks:F.array(F.object({platform:F.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:F.string().describe("Profile or contact URL"),label:F.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});async function Rk0(A,Q,B){let $;try{$=await vH(A)}catch{$={title:"Brain",description:"A knowledge management system"}}let w=Q.getProfile(),D=B.getNavigationItems("primary"),Y=B.getNavigationItems("secondary");return{...$,socialLinks:w.socialLinks,navigation:{primary:D,secondary:Y},copyright:$.copyright??"Powered by Rizom"}}ZA();ZA();import{promises as ab0}from"fs";import{join as oZQ}from"path";import{createHash as pZQ}from"crypto";import{promises as GGA}from"fs";import{join as rb0}from"path";var nb0=null;async function dZQ(){return nb0??=Promise.resolve().then(() => o0(ib0(),1)).then((A)=>A.default),nb0}var iZQ=[480,960,1920],rZQ=80,nZQ="(max-width: 640px) 480px, (max-width: 1280px) 960px, 1920px";class JGA{imagesDir;logger;constructor(A,Q){this.imagesDir=A;this.logger=Q.child("ImageOptimizer")}async optimize(A,Q){try{let B=await dZQ(),$=pZQ("sha256").update(A).digest("hex").slice(0,16),w=await B(A).metadata();if(!w.width||!w.height)return this.logger.warn("Could not determine image dimensions",{originalUrl:Q}),null;let{width:D,height:Y}=w,X=[];for(let W of iZQ){if(W>D)continue;let Z=`${$}-${W}w.webp`,q=rb0(this.imagesDir,Z),N=`/images/${Z}`;if(await GGA.access(q).then(()=>!0).catch(()=>!1)){this.logger.debug("Cache hit, skipping optimization",{fileName:Z}),X.push({width:W,url:N});continue}await B(A).resize(W,null,{withoutEnlargement:!0}).webp({quality:rZQ}).toFile(q),X.push({width:W,url:N}),this.logger.debug("Created WebP variant",{fileName:Z,width:W})}if(X.length===0)return null;let I=X[X.length-1];if(!I)return null;let K=X.find((W)=>W.width===960)??I,G=Math.round(Y*(K.width/D));return{src:K.url,srcset:X.map((W)=>`${W.url} ${W.width}w`).join(", "),sizes:nZQ,width:K.width,height:G}}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 GGA.readdir(this.imagesDir,{withFileTypes:!0})}catch{return this.logger.debug("Images directory does not exist, nothing to optimize"),A}let B=Q.filter(($)=>$.isFile()&&/\.(png|jpe?g)$/i.test($.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 $ of B){let w=rb0(this.imagesDir,$.name),D=`/images/${$.name}`;try{let Y=await GGA.readFile(w),X=await this.optimize(Y,D);if(X)A[D]=X}catch(Y){this.logger.warn("Failed to optimize image",{file:$.name,error:Y instanceof Error?Y.message:String(Y)})}}return this.logger.debug(`Optimized ${Object.keys(A).length}/${B.length} images`),A}}function ob0(A,Q){if(A.format)return A.format;return Q.match(/^data:image\/([^;]+);/)?.[1]??"png"}function sb0(A){return A.match(/^data:image\/[^;]+;base64,(.+)$/)?.[1]??null}function RE(A){return A.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}class WGA{entityService;logger;imageMap={};imagesDir;optimizer;constructor(A,Q,B){this.entityService=A;this.logger=Q.child("ImageBuildService"),this.imagesDir=B,this.optimizer=new JGA(this.imagesDir,this.logger)}async resolveAll(A){let Q=[...new Set(A)];if(Q.length===0)return;await ab0.mkdir(this.imagesDir,{recursive:!0});let B=WZ(4);await Promise.all(Q.map(($)=>B(async()=>{try{await this.resolveImage($)}catch(w){this.logger.warn("Failed to resolve image",{imageId:$,error:w instanceof Error?w.message:String(w)})}}))),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=sb0(Q.content);if(!B){this.logger.warn("Could not extract base64 from image",{imageId:A});return}let $=Buffer.from(B,"base64"),w=ob0(Q.metadata,Q.content),D=`${A}.${w}`,Y=oZQ(this.imagesDir,D);await ab0.writeFile(Y,$);let X=`/images/${D}`,I=await this.optimizer.optimize($,X);if(I)this.imageMap[A]={src:I.src,srcset:I.srcset,sizes:I.sizes,width:I.width,height:I.height};else this.imageMap[A]={src:X,width:Q.metadata.width??0,height:Q.metadata.height??0};this.logger.debug("Resolved image",{imageId:A,optimized:Boolean(I)})}get(A){return this.imageMap[A]}getMap(){return this.imageMap}createImageRenderer(){let A=this.imageMap;return(Q,B,$)=>{let w=/^entity:\/\/image\/(.+)$/.exec(Q);if(!w?.[1])return;let D=A[w[1]];if(!D)return;let Y=[`src="${RE(D.src)}"`,`alt="${RE($)}"`];if(D.srcset)Y.push(`srcset="${RE(D.srcset)}"`);if(D.sizes)Y.push(`sizes="${RE(D.sizes)}"`);if(D.width)Y.push(`width="${D.width}"`);if(D.height)Y.push(`height="${D.height}"`);if(B)Y.push(`title="${RE(B)}"`);return Y.push('loading="lazy"'),Y.push('decoding="async"'),`<img ${Y.join(" ")}>`}}}var aZQ=FQ.extend({metadata:F.object({slug:F.string()}).passthrough()});class ow{static instance=null;static defaultStaticSiteBuilderFactory=hUA;logger;context;staticSiteBuilderFactory;routeRegistry;profileService;entityDisplay;imageBuildService=null;static setDefaultStaticSiteBuilderFactory(A){ow.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,B,$,w){return ow.instance??=new ow(A,ow.defaultStaticSiteBuilderFactory,Q,B,$,w),ow.instance}static resetInstance(){ow.instance=null}static createFresh(A,Q,B,$,w,D){return new ow(A,w??ow.defaultStaticSiteBuilderFactory,Q,B,$,D)}constructor(A,Q,B,$,w,D){this.logger=A,this.context=B,this.staticSiteBuilderFactory=Q,this.routeRegistry=$,this.profileService=w,this.entityDisplay=D,L7.getInstance().configure(D)}async getSiteInfo(){return Rk0(this.context.entityService,this.profileService,this.routeRegistry)}async build(A,Q){let B=eN0.parse(A),$=n5.from(Q),w=[],D=[];try{await $?.report({message:"Starting site build",progress:0,total:100}),await $?.report({message:"Generating dynamic routes",progress:10,total:100}),await new gUA(this.context,this.routeRegistry,this.entityDisplay).generateEntityRoutes();let X=B.workingDir??sZQ(B.outputDir,".preact-work"),I=this.staticSiteBuilderFactory({logger:this.logger.child("StaticSiteBuilder"),workingDir:X,outputDir:B.outputDir});if(B.cleanBeforeBuild)await I.clean();let K=this.routeRegistry.list();if(K.length===0)D.push("No routes registered for site build");await $?.report({message:`Building ${K.length} routes`,progress:20,total:100}),await $?.report({message:"Resolving images",progress:25,total:100}),this.imageBuildService=new WGA(this.context.entityService,this.logger,B.sharedImagesDir);let G=await this.collectAllImageIds();if(G.length>0)await this.imageBuildService.resolveAll(G);let W=B.siteConfig,Z={routes:K,pluginContext:this.context,siteConfig:{title:W.title,description:W.description,...W.url&&{url:W.url},...W.copyright&&{copyright:W.copyright},...W.themeMode&&{themeMode:W.themeMode},...W.analyticsScript&&{analyticsScript:W.analyticsScript}},headScripts:A.headScripts,...A.staticAssets&&{staticAssets:A.staticAssets},getContent:async(_,T)=>{let P=B.environment==="production";return this.getContentForSection(T,_,P)},getViewTemplate:(_)=>{return this.context.views.get(_)},layouts:B.layouts,getSiteInfo:async()=>{return this.getSiteInfo()},...B.themeCSS!==void 0&&{themeCSS:B.themeCSS},...A.slots&&{slots:A.slots},imageBuildService:this.imageBuildService},q=0,N=K.length+4;await I.build(Z,(_)=>{q++;let T=85+Math.round(q/N*10);$?.report({message:_,progress:T,total:100}).catch(()=>{})}),await $?.report({message:"Site build complete",progress:100,total:100});let M=K.length+1,L={success:w.length===0,outputDir:B.outputDir,filesGenerated:M,routesBuilt:K.length};if(w.length>0)L.errors=w;if(D.length>0)L.warnings=D;return L}catch(Y){let X=Error("Site build process failed");return this.logger.error("Site build failed",{error:X,originalError:Y}),w.push(X.message),{success:!1,outputDir:B.outputDir,filesGenerated:0,routesBuilt:0,errors:w}}}async getContentForSection(A,Q,B){if(!A.template)return A.content??null;let $=A.template,w=L7.getInstance();if(A.dataQuery){let Y={dataParams:A.dataQuery,fallback:A.content,publishedOnly:B},X=await this.context.templates.resolve($,Y);if(X)return this.enrichWithUrls(X,w);return null}let D=await this.context.templates.resolve($,{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content});if(D)return this.enrichWithUrls(D,w);return null}async enrichWithUrls(A,Q){if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((P)=>this.enrichWithUrls(P,Q)));if(typeof A!=="object")return A;let B=A,$={},w=Object.entries(B),D=await Promise.all(w.map(([,P])=>this.enrichWithUrls(P,Q)));for(let P=0;P<w.length;P++){let r=w[P];if(r)$[r[0]]=D[P]}let Y=aZQ.safeParse(B);if(!Y.success)return $;let X=Y.data,I=X.entityType,K=X.metadata.slug,G=this.entityDisplay?.[I],W=G?G.label:I.charAt(0).toUpperCase()+I.slice(1),Z=G?G.pluralName??G.label.toLowerCase()+"s":Vw(I),q=`/${Z}`,N=Z.charAt(0).toUpperCase()+Z.slice(1),M=uR(X),L=M?this.imageBuildService?.get(M):void 0,_={};if(L)_={coverImageUrl:L.src,coverImageWidth:L.width,coverImageHeight:L.height,...L.srcset&&{coverImageSrcset:L.srcset,coverImageSizes:L.sizes}};else{let P=await cR(X,this.context.entityService);if(P)_={coverImageUrl:P.url,coverImageWidth:P.width,coverImageHeight:P.height}}return{...$,...X,url:Q.generateUrl(I,K),typeLabel:W,listUrl:q,listLabel:N,..._}}async collectAllImageIds(){let A=new Set;try{let Q=this.context.entityService.getEntityTypes();for(let B of Q){if(B==="image")continue;let $=await this.context.entityService.listEntities(B);for(let w of $){let D=uR(w);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]}}w0();class ZGA{logger;routes=new Map;constructor(A){this.logger=A}register(A){let Q=Array.isArray(A)?A:[A];for(let B of Q){let $=AV.parse(B);if(this.routes.has($.path)){let w=this.routes.get($.path);this.logger.debug(`Overriding route "${$.path}" (was registered by plugin "${w?.pluginId}")`)}this.routes.set($.path,$)}}unregister(A){(Array.isArray(A)?A:[A]).forEach((B)=>this.routes.delete(B))}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,$]of this.routes.entries())if($.navigation?.show&&$.navigation.slot===A)Q.push({label:$.navigation.label??$.title,href:B,priority:$.navigation.priority});return Q.sort((B,$)=>B.priority-$.priority)}}class Sd{slots=new Map;register(A,Q){let B={...Q,priority:Q.priority??50},$=this.slots.get(A)??[];$.push(B),this.slots.set(A,$)}getSlot(A){return[...this.slots.get(A)??[]].sort((B,$)=>$.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 $=B.filter((w)=>w.pluginId!==Q);if($.length>0)this.slots.set(A,$);else this.slots.delete(A)}unregisterAll(A){for(let[Q,B]of this.slots){let $=B.filter((w)=>w.pluginId!==A);if($.length>0)this.slots.set(Q,$);else this.slots.delete(Q)}}getSlotNames(){return Array.from(this.slots.keys())}clear(){this.slots.clear()}}ZA();class FGA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,B,$){this.config=A;this.context=Q;this.pluginId=B;this.logger=$}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),B=this.debounces.get(Q);if(!B)B=new zZ(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,B);B.trigger()}setupAutoRebuild(){let A=new Set(["base"]),Q=async($)=>{let{entityType:w}=$.payload;if(!A.has(w))this.logger.debug(`Entity type ${w} will trigger rebuild`),this.requestBuild();return{success:!0}},B=["entity:created","entity:updated","entity:deleted"];for(let $ of B)this.unsubscribeFunctions.push(this.context.messaging.subscribe($,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})}}}w0();function tZQ(A,Q){return A.map((B)=>({...B,template:B.template.includes(":")?B.template:`${Q}:${B.template}`}))}function hd(A,Q,B){for(let $ of A)B.register({...$,pluginId:Q,sections:$.sections?tZQ($.sections,Q):[]})}function tb0(A,Q,B){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let w=Qe.parse($.payload),{routes:D,pluginId:Y}=w;return hd(D,Y,Q),{success:!0}}catch(w){return B.error("Failed to register routes",{error:w}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async($)=>{try{let w=Be.parse($.payload),{paths:D,pluginId:Y}=w;if(D)for(let X of D)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch(w){return B.error("Failed to unregister routes",{error:w}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async($)=>{try{let w=$e.parse($.payload);return{success:!0,data:{routes:Q.list(w.pluginId?w:void 0)}}}catch(w){return B.error("Failed to list routes",{error:w}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async($)=>{try{let w=we.parse($.payload);return{success:!0,data:{route:Q.get(w.path)}}}catch(w){return B.error("Failed to get route",{error:w}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}ZA();import{promises as Nf}from"fs";import{join as Lf}from"path";function eb0(A,Q){if(Q==="preview")return`User-agent: *
2398
2398
  Disallow: /
2399
2399
 
2400
2400
  Sitemap: ${A}/sitemap.xml
@@ -2423,7 +2423,7 @@ ${A.map((D)=>({url:`${Q}${D.path}`,lastmod:B,changefreq:D.path==="/"?"daily":"we
2423
2423
  <script src="https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js"></script>
2424
2424
  </body>
2425
2425
  </html>
2426
- `;async function BFQ(A,Q,B){let $=A.siteConfig.url??"https://example.com",w=Q.list(),D=eb0($,A.environment);await Nf.writeFile(Lf(A.outputDir,"robots.txt"),D,"utf-8"),B.info(`Generated robots.txt for ${A.environment} environment`);let Y=AT0(w,$);await Nf.writeFile(Lf(A.outputDir,"sitemap.xml"),Y,"utf-8"),B.info(`Generated sitemap.xml with ${w.length} URLs`)}async function $FQ(A,Q,B,$){if(!B.cms)return;let w=await Q.messaging.send("git-sync:get-repo-info",{});if("noop"in w||!w.success||!w.data?.repo){$.warn("CMS enabled but git-sync repo info unavailable \u2014 skipping CMS generation");return}let D=Q.entityService.getEntityTypes(),Y=Vf({repo:w.data.repo,branch:w.data.branch,...Q.siteUrl&&{baseUrl:Q.siteUrl},entityTypes:D,getFrontmatterSchema:(I)=>Q.entities.getEffectiveFrontmatterSchema(I),getAdapter:(I)=>Q.entities.getAdapter(I),...B.entityDisplay&&{entityDisplay:B.entityDisplay}}),X=Lf(A.outputDir,"admin");await Nf.mkdir(X,{recursive:!0}),await Nf.writeFile(Lf(X,"config.yml"),ND(Y),"utf-8"),await Nf.writeFile(Lf(X,"index.html"),zGA,"utf-8"),$.info("Generated CMS admin page and config.yml")}function BT0(A){let{context:Q,routeRegistry:B,config:$,logger:w}=A;Q.messaging.subscribe("site:build:completed",async(D)=>{try{let Y=D.payload;return w.info(`Received site:build:completed event for ${Y.environment} environment - generating SEO files`),await BFQ(Y,B,w),await $FQ(Y,Q,$,w),{success:!0}}catch(Y){return w.error("Failed to generate SEO files",Y),{success:!1}}})}w0();ZA();var $T0=F.object({environment:F.enum(["preview","production"]).optional(),outputDir:F.string(),workingDir:F.string().optional(),enableContentGeneration:F.boolean().optional(),siteConfig:F.object({title:F.string(),description:F.string(),url:F.string().optional(),analyticsScript:F.string().optional()}).optional()});ZA();class VGA extends NB{sendMessage;cfg;constructor(A,Q,B){super(A,{schema:$T0,jobTypeName:"site-build"});this.sendMessage=Q;this.cfg=B}async process(A,Q,B){let $=A.environment??"preview",w=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:$,outputDir:A.outputDir}),await B.report({progress:0,total:100,message:`Starting site build for ${$} 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:w,environment:$,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:$,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${$} environment`);let X=$==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage("site:build:completed",{outputDir:A.outputDir,environment:$,routesBuilt:Y.routesBuilt,siteConfig:{...A.siteConfig??this.cfg.defaultSiteConfig,url:X},generateEntityUrl:(I,K)=>L7.getInstance().generateUrl(I,K)},{broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:$,...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}}}ZA();w0();var wFQ=F.object({slot:F.enum(ez).optional().default("primary"),limit:F.number().optional()});class NGA{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 $=wFQ.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:$});let w=this.routeRegistry.getNavigationItems($.slot),D=$.limit?w.slice(0,$.limit):w,Y=D.map((I)=>({label:I.label,href:I.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:D.length,items:Y});let X={navigation:Y};return Q.parse(X)}}w0();ZA();var DFQ=F.object({environment:F.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function wT0(A,Q){return[g2(A,"build-site","Build a static site from registered routes",DFQ,async(B)=>{return Q(B.environment),{success:!0,message:`Site build requested${B.environment?` for ${B.environment}`:""} (debounced)`,data:{}}},{cli:{name:"build"}})]}ZA();w0();var DT0=F.object({previewOutputDir:F.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:F.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:F.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:F.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:FI.default({title:"Brain",description:"A knowledge management system"}),themeCSS:F.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:F.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:F.any().optional().describe("Template definitions to register"),routes:F.array(AV).optional().describe("Routes to register"),layouts:F.record(F.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:F.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:F.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:F.record(F.object({label:F.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:F.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:F.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:F.boolean().optional().describe("Enable pagination for list pages"),pageSize:F.number().optional().describe("Items per page (default: 10)"),navigation:F.object({show:F.boolean().optional().describe("Show in navigation"),slot:F.enum(ez).optional().describe("Navigation slot (primary or secondary)"),priority:F.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:F.record(F.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:F.object({}).optional().describe("Sveltia CMS configuration (enables /admin/ CMS, requires git-sync plugin)")});var YT0={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.31",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 LGA extends f8{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",YT0,{...A,layouts:Q},DT0);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new ZGA(A.logger),this._slotRegistry=new Sd,A.messaging.subscribe("plugin:site-builder:slot:register",async(Q)=>{let{slotName:B,pluginId:$,render:w,priority:D}=Q.payload;return this._slotRegistry?.register(B,{pluginId:$,render:w,...D!==void 0&&{priority:D}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(Q)=>{let{pluginId:B,script:$}=Q.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new NGA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=R7.getInstance(A.entityService,A.logger),A.messaging.subscribe("sync:initial:completed",async()=>{return await this.profileService?.initialize(),this.logger.info("AnchorProfileService initialized"),{success:!0}}),tb0(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)hd(this.config.routes,this.id,this.routeRegistry);if(this.siteBuilder=ow.getInstance(A.logger.child("SiteBuilder"),A,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new VGA(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 FGA(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 $=await this.getInstructions();if($)A.registerInstructions($)}return{success:!0}}),BT0({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 wT0(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 vH(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(($)=>({id:$.id,template:$.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 vH(A.entityService);return`## Your Site
2426
+ `;async function BFQ(A,Q,B){let $=A.siteConfig.url??"https://example.com",w=Q.list(),D=eb0($,A.environment);await Nf.writeFile(Lf(A.outputDir,"robots.txt"),D,"utf-8"),B.info(`Generated robots.txt for ${A.environment} environment`);let Y=AT0(w,$);await Nf.writeFile(Lf(A.outputDir,"sitemap.xml"),Y,"utf-8"),B.info(`Generated sitemap.xml with ${w.length} URLs`)}async function $FQ(A,Q,B,$){if(!B.cms)return;let w=await Q.messaging.send("git-sync:get-repo-info",{});if("noop"in w||!w.success||!w.data?.repo){$.warn("CMS enabled but git-sync repo info unavailable \u2014 skipping CMS generation");return}let D=Q.entityService.getEntityTypes(),Y=Vf({repo:w.data.repo,branch:w.data.branch,...Q.siteUrl&&{baseUrl:Q.siteUrl},entityTypes:D,getFrontmatterSchema:(I)=>Q.entities.getEffectiveFrontmatterSchema(I),getAdapter:(I)=>Q.entities.getAdapter(I),...B.entityDisplay&&{entityDisplay:B.entityDisplay}}),X=Lf(A.outputDir,"admin");await Nf.mkdir(X,{recursive:!0}),await Nf.writeFile(Lf(X,"config.yml"),ND(Y),"utf-8"),await Nf.writeFile(Lf(X,"index.html"),zGA,"utf-8"),$.info("Generated CMS admin page and config.yml")}function BT0(A){let{context:Q,routeRegistry:B,config:$,logger:w}=A;Q.messaging.subscribe("site:build:completed",async(D)=>{try{let Y=D.payload;return w.info(`Received site:build:completed event for ${Y.environment} environment - generating SEO files`),await BFQ(Y,B,w),await $FQ(Y,Q,$,w),{success:!0}}catch(Y){return w.error("Failed to generate SEO files",Y),{success:!1}}})}w0();ZA();var $T0=F.object({environment:F.enum(["preview","production"]).optional(),outputDir:F.string(),workingDir:F.string().optional(),enableContentGeneration:F.boolean().optional(),siteConfig:F.object({title:F.string(),description:F.string(),url:F.string().optional(),analyticsScript:F.string().optional()}).optional()});ZA();class VGA extends NB{sendMessage;cfg;constructor(A,Q,B){super(A,{schema:$T0,jobTypeName:"site-build"});this.sendMessage=Q;this.cfg=B}async process(A,Q,B){let $=A.environment??"preview",w=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:$,outputDir:A.outputDir}),await B.report({progress:0,total:100,message:`Starting site build for ${$} 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:w,environment:$,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:$,routesBuilt:Y.routesBuilt,success:Y.success}),Y.success){this.logger.info(`Emitting site:build:completed event for ${$} environment`);let X=$==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage("site:build:completed",{outputDir:A.outputDir,environment:$,routesBuilt:Y.routesBuilt,siteConfig:{...A.siteConfig??this.cfg.defaultSiteConfig,url:X},generateEntityUrl:(I,K)=>L7.getInstance().generateUrl(I,K)},{broadcast:!0})}return{success:Y.success,routesBuilt:Y.routesBuilt,outputDir:A.outputDir,environment:$,...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}}}ZA();w0();var wFQ=F.object({slot:F.enum(ez).optional().default("primary"),limit:F.number().optional()});class NGA{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 $=wFQ.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:$});let w=this.routeRegistry.getNavigationItems($.slot),D=$.limit?w.slice(0,$.limit):w,Y=D.map((I)=>({label:I.label,href:I.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:D.length,items:Y});let X={navigation:Y};return Q.parse(X)}}w0();ZA();var DFQ=F.object({environment:F.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function wT0(A,Q){return[g2(A,"build-site","Build a static site from registered routes",DFQ,async(B)=>{return Q(B.environment),{success:!0,message:`Site build requested${B.environment?` for ${B.environment}`:""} (debounced)`,data:{}}},{cli:{name:"build"}})]}ZA();w0();var DT0=F.object({previewOutputDir:F.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:F.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:F.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:F.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:FI.default({title:"Brain",description:"A knowledge management system"}),themeCSS:F.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:F.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:F.any().optional().describe("Template definitions to register"),routes:F.array(AV).optional().describe("Routes to register"),layouts:F.record(F.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:F.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:F.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:F.record(F.object({label:F.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:F.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:F.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:F.boolean().optional().describe("Enable pagination for list pages"),pageSize:F.number().optional().describe("Items per page (default: 10)"),navigation:F.object({show:F.boolean().optional().describe("Show in navigation"),slot:F.enum(ez).optional().describe("Navigation slot (primary or secondary)"),priority:F.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:F.record(F.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:F.object({}).optional().describe("Sveltia CMS configuration (enables /admin/ CMS, requires git-sync plugin)")});var YT0={name:"@brains/site-builder-plugin",private:!0,version:"0.2.0-alpha.32",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 LGA extends f8{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",YT0,{...A,layouts:Q},DT0);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new ZGA(A.logger),this._slotRegistry=new Sd,A.messaging.subscribe("plugin:site-builder:slot:register",async(Q)=>{let{slotName:B,pluginId:$,render:w,priority:D}=Q.payload;return this._slotRegistry?.register(B,{pluginId:$,render:w,...D!==void 0&&{priority:D}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(Q)=>{let{pluginId:B,script:$}=Q.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new NGA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=R7.getInstance(A.entityService,A.logger),A.messaging.subscribe("sync:initial:completed",async()=>{return await this.profileService?.initialize(),this.logger.info("AnchorProfileService initialized"),{success:!0}}),tb0(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)hd(this.config.routes,this.id,this.routeRegistry);if(this.siteBuilder=ow.getInstance(A.logger.child("SiteBuilder"),A,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new VGA(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 FGA(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 $=await this.getInstructions();if($)A.registerInstructions($)}return{success:!0}}),BT0({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 wT0(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 vH(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(($)=>({id:$.id,template:$.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 vH(A.entityService);return`## Your Site
2427
2427
  ${[`**Title:** ${Q.title}`,`**Description:** ${Q.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
2428
2428
  `)}`}catch{return}}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),ow.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function l3(A={}){return new LGA(A)}ZA();var XFQ=FI.extend({navigation:F.object({primary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()})),secondary:F.array(F.object({label:F.string(),href:F.string(),priority:F.number()}))}),copyright:F.string(),socialLinks:F.array(F.object({platform:F.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:F.string().describe("Profile or contact URL"),label:F.string().optional().describe("Optional display label")})).optional().describe("Social media links from profile entity")});import{h as IFQ,Fragment as KFQ}from"preact";function EGA({name:A,slots:Q}){if(!Q?.hasSlot(A))return null;let $=Q.getSlot(A).map((w)=>w.render());return IFQ(KFQ,{},...$)}w0();OI();Cf();ZA();var MGA=F.object({defaultPrompt:F.string().default("Write a blog post about my recent work and insights"),paginate:F.boolean().default(!0),pageSize:F.number().default(10)});w0();ZA();var GFQ=F.object({prompt:F.string().optional(),title:F.string().optional(),content:F.string().optional(),excerpt:F.string().optional(),coverImageId:F.string().optional(),seriesName:F.string().optional(),seriesIndex:F.number().optional(),skipAi:F.boolean().optional()}),fo2=M7.extend({title:F.string().optional(),slug:F.string().optional()});class CGA extends a5{constructor(A,Q){super(A,Q,{schema:GFQ,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:B,coverImageId:$,seriesName:w,seriesIndex:D,skipAi:Y}=A,{title:X,content:I,excerpt:K}=A;if(Y){if(!X)this.failEarly("Title is required when skipAi is true");I=I??`## Introduction
2429
2429
 
@@ -2470,7 +2470,7 @@ The excerpt should be clear, concise, and compelling.`});ZA();o8();OI();import{j
2470
2470
  Note: This is part of a series called "${B.seriesName}".`:""}`;return A.ai.generate({prompt:$,templateName:"blog:generation"})}),A.eval.registerHandler("generateExcerpt",async(Q)=>{let B=RFQ.parse(Q);return A.ai.generate({prompt:`Title: ${B.title}
2471
2471
 
2472
2472
  Content:
2473
- ${B.content}`,templateName:"blog:excerpt"})})}var LT0={name:"@brains/blog",private:!0,version:"0.2.0-alpha.31",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 PGA extends z2{entityType=p3.entityType;schema=PE;adapter=p3;constructor(A={}){super("blog",LT0,A,MGA)}getEntityTypeConfig(){return{weight:2}}createGenerationHandler(A){return new CGA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return ZT0()}getDataSources(){return[new jGA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (CT0(),MT0));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),await FT0(A,this.logger),qT0(A,this.logger),VT0(A,this.logger),NT0(A),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}}function _GA(A={}){return new PGA(A)}OI();Cf();w0();ZA();P6();var eD=F.object({title:F.string(),slug:F.string(),coverImageId:F.string().optional()}),OT0=eD.pick({title:!0,slug:!0}),fE=FQ.extend({metadata:OT0}),cd=fE.extend({frontmatter:eD}),ld=cd.extend({description:F.string().optional(),postCount:F.number(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()}),jT0=F.object({description:F.string().optional()});function d3(A){return new W8(jT0,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}P6();class kGA extends _Q{constructor(){super({entityType:"series",schema:fE,frontmatterSchema:eD,supportsCoverImage:!0,bodyFormatter:d3("")})}toMarkdown(A){let Q,B={};try{Q=this.parseFrontMatter(A.content,eD).coverImageId,B=d3(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},D=d3(A.metadata.title).format(B);return this.buildMarkdown(D,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,eD);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,eD);return d3(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var bE=new kGA;w0();ZA();d4();class fGA{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((w)=>[w.id,w])),$=new Set;for(let w of A){let D=a1(w);$.add(D);let Y=B.get(D),X=Y?.content??this.createSeriesContent(w),I=nB(X);if(Y?.contentHash===I)continue;let K={id:D,entityType:"series",content:X,contentHash:I,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:w,slug:a1(w)}};await this.entityService.upsertEntity(K),this.logger.debug(`Upserted series: ${w}`)}for(let w of Q)if(!$.has(w.id))await this.entityService.deleteEntity("series",w.id),this.logger.debug(`Deleted orphaned series: ${w.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=a1(A);if(await this.entityService.getEntity("series",Q))return;let $=this.createSeriesContent(A),w={id:Q,entityType:"series",content:$,contentHash:nB($),created:new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:A,slug:a1(A)}};await this.entityService.upsertEntity(w),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=a1(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 $=await this.entityService.listEntities(B,{limit:1000});for(let w of $){let D=this.getSeriesName(w);if(D)A.add(D)}}return A}createSeriesContent(A){let Q={title:A,slug:a1(A)};return d9("",Q)}}w0();ZA();var kFQ=F.object({entityType:F.literal("series"),query:F.object({id:F.string().optional(),limit:F.number().optional(),page:F.number().optional(),pageSize:F.number().optional()}).passthrough()}),fFQ=F.object({type:F.enum(["list","detail"]),seriesName:F.string().optional()});function bFQ(A){let Q=fFQ.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let B=kFQ.safeParse(A);if(B.success){let{query:$}=B.data;if($.id)return{type:"detail",seriesSlug:$.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function RT0(A){let Q=JQ(A.content,eD);return cd.parse({...A,frontmatter:Q.metadata})}class bGA{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 $=bFQ(A),w=B.entityService;if($.type==="list")return this.fetchSeriesList(Q,w);if($.seriesName)return this.fetchSeriesDetail($.seriesName,Q,w);if($.seriesSlug)return this.fetchSeriesDetailBySlug($.seriesSlug,Q,w);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let B=await Q.listEntities("series",{limit:1000}),$=await this.countEntitiesPerSeries(Q),w=B.map((D)=>{let Y=RT0(D),X=bE.parseBody(D.content);return{...Y,description:X.description,postCount:$.get(D.metadata.title)??0}});return this.logger.debug(`Found ${w.length} series entities`),A.parse({series:w})}async fetchSeriesDetail(A,Q,B,$){if(!$)$=(await B.listEntities("series",{filter:{metadata:{title:A}}}))[0];if(!$)throw Error(`Series not found: ${A}`);let w=RT0($),D=bE.parseBody($.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:{...w,description:D.description,postCount:Y.length},description:D.description})}async fetchSeriesDetailBySlug(A,Q,B){let w=(await B.listEntities("series",{filter:{metadata:{slug:A}}}))[0];if(!w)return this.logger.warn(`Series not found with slug: ${A}`),Q.parse({seriesName:A,posts:[]});return this.fetchSeriesDetail(w.metadata.title,Q,B,w)}async countEntitiesPerSeries(A){let Q=new Map,B=A.getEntityTypes();for(let $ of B){if($==="series")continue;let w=await A.listEntities($,{limit:1000});for(let D of w){let Y=this.getSeriesName(D);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let B=[],$=Q.getEntityTypes();for(let w of $){if(w==="series")continue;let D=await Q.listEntities(w,{filter:{metadata:{seriesName:A}}});B.push(...D)}return B.sort((w,D)=>{let Y=w.metadata.seriesIndex,X=D.metadata.seriesIndex;return(typeof Y==="number"?Y:999)-(typeof X==="number"?X:999)}),B}getSeriesName(A){let B=A.metadata.seriesName;return typeof B==="string"?B:void 0}}w0();ZA();d4();var TFQ=F.object({prompt:F.string().optional(),title:F.string().optional(),seriesId:F.string().optional()});class pd{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 $=await this.gatherMemberSummaries(B.metadata.title);if($.length===0)return{success:!1,error:`No members found in series: ${B.metadata.title}`};let w=A.prompt??`Series name: ${B.metadata.title}
2473
+ ${B.content}`,templateName:"blog:excerpt"})})}var LT0={name:"@brains/blog",private:!0,version:"0.2.0-alpha.32",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 PGA extends z2{entityType=p3.entityType;schema=PE;adapter=p3;constructor(A={}){super("blog",LT0,A,MGA)}getEntityTypeConfig(){return{weight:2}}createGenerationHandler(A){return new CGA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return ZT0()}getDataSources(){return[new jGA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (CT0(),MT0));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),await FT0(A,this.logger),qT0(A,this.logger),VT0(A,this.logger),NT0(A),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}}function _GA(A={}){return new PGA(A)}OI();Cf();w0();ZA();P6();var eD=F.object({title:F.string(),slug:F.string(),coverImageId:F.string().optional()}),OT0=eD.pick({title:!0,slug:!0}),fE=FQ.extend({metadata:OT0}),cd=fE.extend({frontmatter:eD}),ld=cd.extend({description:F.string().optional(),postCount:F.number(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()}),jT0=F.object({description:F.string().optional()});function d3(A){return new W8(jT0,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}P6();class kGA extends _Q{constructor(){super({entityType:"series",schema:fE,frontmatterSchema:eD,supportsCoverImage:!0,bodyFormatter:d3("")})}toMarkdown(A){let Q,B={};try{Q=this.parseFrontMatter(A.content,eD).coverImageId,B=d3(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},D=d3(A.metadata.title).format(B);return this.buildMarkdown(D,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,eD);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,eD);return d3(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var bE=new kGA;w0();ZA();d4();class fGA{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((w)=>[w.id,w])),$=new Set;for(let w of A){let D=a1(w);$.add(D);let Y=B.get(D),X=Y?.content??this.createSeriesContent(w),I=nB(X);if(Y?.contentHash===I)continue;let K={id:D,entityType:"series",content:X,contentHash:I,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:w,slug:a1(w)}};await this.entityService.upsertEntity(K),this.logger.debug(`Upserted series: ${w}`)}for(let w of Q)if(!$.has(w.id))await this.entityService.deleteEntity("series",w.id),this.logger.debug(`Deleted orphaned series: ${w.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=a1(A);if(await this.entityService.getEntity("series",Q))return;let $=this.createSeriesContent(A),w={id:Q,entityType:"series",content:$,contentHash:nB($),created:new Date().toISOString(),updated:new Date().toISOString(),metadata:{title:A,slug:a1(A)}};await this.entityService.upsertEntity(w),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=a1(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 $=await this.entityService.listEntities(B,{limit:1000});for(let w of $){let D=this.getSeriesName(w);if(D)A.add(D)}}return A}createSeriesContent(A){let Q={title:A,slug:a1(A)};return d9("",Q)}}w0();ZA();var kFQ=F.object({entityType:F.literal("series"),query:F.object({id:F.string().optional(),limit:F.number().optional(),page:F.number().optional(),pageSize:F.number().optional()}).passthrough()}),fFQ=F.object({type:F.enum(["list","detail"]),seriesName:F.string().optional()});function bFQ(A){let Q=fFQ.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let B=kFQ.safeParse(A);if(B.success){let{query:$}=B.data;if($.id)return{type:"detail",seriesSlug:$.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function RT0(A){let Q=JQ(A.content,eD);return cd.parse({...A,frontmatter:Q.metadata})}class bGA{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 $=bFQ(A),w=B.entityService;if($.type==="list")return this.fetchSeriesList(Q,w);if($.seriesName)return this.fetchSeriesDetail($.seriesName,Q,w);if($.seriesSlug)return this.fetchSeriesDetailBySlug($.seriesSlug,Q,w);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let B=await Q.listEntities("series",{limit:1000}),$=await this.countEntitiesPerSeries(Q),w=B.map((D)=>{let Y=RT0(D),X=bE.parseBody(D.content);return{...Y,description:X.description,postCount:$.get(D.metadata.title)??0}});return this.logger.debug(`Found ${w.length} series entities`),A.parse({series:w})}async fetchSeriesDetail(A,Q,B,$){if(!$)$=(await B.listEntities("series",{filter:{metadata:{title:A}}}))[0];if(!$)throw Error(`Series not found: ${A}`);let w=RT0($),D=bE.parseBody($.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:{...w,description:D.description,postCount:Y.length},description:D.description})}async fetchSeriesDetailBySlug(A,Q,B){let w=(await B.listEntities("series",{filter:{metadata:{slug:A}}}))[0];if(!w)return this.logger.warn(`Series not found with slug: ${A}`),Q.parse({seriesName:A,posts:[]});return this.fetchSeriesDetail(w.metadata.title,Q,B,w)}async countEntitiesPerSeries(A){let Q=new Map,B=A.getEntityTypes();for(let $ of B){if($==="series")continue;let w=await A.listEntities($,{limit:1000});for(let D of w){let Y=this.getSeriesName(D);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let B=[],$=Q.getEntityTypes();for(let w of $){if(w==="series")continue;let D=await Q.listEntities(w,{filter:{metadata:{seriesName:A}}});B.push(...D)}return B.sort((w,D)=>{let Y=w.metadata.seriesIndex,X=D.metadata.seriesIndex;return(typeof Y==="number"?Y:999)-(typeof X==="number"?X:999)}),B}getSeriesName(A){let B=A.metadata.seriesName;return typeof B==="string"?B:void 0}}w0();ZA();d4();var TFQ=F.object({prompt:F.string().optional(),title:F.string().optional(),seriesId:F.string().optional()});class pd{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 $=await this.gatherMemberSummaries(B.metadata.title);if($.length===0)return{success:!1,error:`No members found in series: ${B.metadata.title}`};let w=A.prompt??`Series name: ${B.metadata.title}
2474
2474
 
2475
2475
  Content in this series:
2476
2476
  ${$.join(`
@@ -2482,7 +2482,7 @@ Your task is to write a series description (2-3 sentences) that:
2482
2482
  3. Is engaging and makes readers want to explore the content
2483
2483
  4. Works well as a series overview on a website
2484
2484
 
2485
- Be concise and focus on what makes this series unique and valuable.`});var xT0={name:"@brains/series",private:!0,version:"0.2.0-alpha.31",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 TGA extends z2{entityType="series";schema=fE;adapter=bE;manager;constructor(){super("series",xT0)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new pd(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...bT0(),description:TT0}}getDataSources(){return[new bGA(this.logger.child("SeriesDataSource"))]}async onRegister(A){this.manager=new fGA(A.entityService,this.logger.child("SeriesManager"));let Q=this.manager;for(let B of["entity:created","entity:updated"])A.messaging.subscribe(B,async($)=>{try{let w=$.payload;if(w.entityType==="series")return{success:!0};if(w.entity){if(Q.getSeriesName(w.entity))await Q.handleEntityChange(w.entity)}return{success:!0}}catch(w){return this.logger.error("Failed to handle entity event for series",{error:w}),{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($){return this.logger.error("Failed to handle entity deletion for series",{error:$}),{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 pd(this.logger.child("SeriesGenerationHandler"),A),B=await A.entityService.listEntities("series",{limit:1000});for(let $ of B)try{if(!this.adapter.parseBody($.content).description)this.logger.info(`Generating description for series: ${$.metadata.title}`),await Q.process({seriesId:$.id})}catch(w){this.logger.error(`Failed to generate description for series: ${$.id}`,{error:w})}}}function xGA(){return new TGA}w0();ZA();w0();ZA();ZA();w0();var gFQ=F.enum(["draft","queued","published"]),rJ=F.object({title:F.string(),slug:F.string().optional(),description:F.string().optional(),author:F.string().optional(),status:gFQ,publishedAt:F.string().datetime().optional(),event:F.string().optional(),coverImageId:F.string().optional()}),yFQ=rJ.pick({title:!0,description:!0,status:!0,publishedAt:!0,coverImageId:!0}).extend({slug:F.string()}),dd=FQ.extend({entityType:F.literal("deck"),metadata:yFQ}),id=dd.extend({frontmatter:rJ,body:F.string()}),Rf=id.extend({url:F.string().optional(),typeLabel:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()});class vGA extends _Q{constructor(){super({entityType:"deck",schema:dd,frontmatterSchema:rJ,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,rJ),$={...B,slug:B.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontmatter(A),B=this.extractBody(A);this.validateSlideStructure(B);let $=Q.slug??a1(Q.title),w=Q.status;return{entityType:"deck",content:A,metadata:{slug:$,title:Q.title,description:Q.description,status:w,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 Pf=new vGA;ZA();o8();var mFQ=F.object({markdown:F.string().describe("Markdown content with slide separators (---)")}),SGA=E1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:mFQ,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:$KA,fullscreen:!0}});o8();ZA();var hGA=F.object({decks:F.array(id)}),gGA=F.object({decks:F.array(Rf),pageTitle:F.string().optional()});import{jsxDEV as yGA}from"preact/jsx-dev-runtime";var mGA=({decks:A,pageTitle:Q})=>{let B=A.map(($)=>({id:$.id,url:$.url,title:$.frontmatter.title,date:$.frontmatter.publishedAt??$.created,description:$.frontmatter.description}));return yGA("div",{className:"deck-list bg-theme",children:yGA("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:yGA(LH,{title:Q??"Presentations",items:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};ZA();class rd extends W8{constructor(){super(hGA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var uGA=E1({name:"deck-list",description:"List view of all presentation decks",schema:gGA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new rd,layout:{component:mGA}});ZA();w0();var uFQ=F.object({title:F.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:F.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:F.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),vT0=E1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:uFQ,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
2485
+ Be concise and focus on what makes this series unique and valuable.`});var xT0={name:"@brains/series",private:!0,version:"0.2.0-alpha.32",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 TGA extends z2{entityType="series";schema=fE;adapter=bE;manager;constructor(){super("series",xT0)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new pd(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...bT0(),description:TT0}}getDataSources(){return[new bGA(this.logger.child("SeriesDataSource"))]}async onRegister(A){this.manager=new fGA(A.entityService,this.logger.child("SeriesManager"));let Q=this.manager;for(let B of["entity:created","entity:updated"])A.messaging.subscribe(B,async($)=>{try{let w=$.payload;if(w.entityType==="series")return{success:!0};if(w.entity){if(Q.getSeriesName(w.entity))await Q.handleEntityChange(w.entity)}return{success:!0}}catch(w){return this.logger.error("Failed to handle entity event for series",{error:w}),{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($){return this.logger.error("Failed to handle entity deletion for series",{error:$}),{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 pd(this.logger.child("SeriesGenerationHandler"),A),B=await A.entityService.listEntities("series",{limit:1000});for(let $ of B)try{if(!this.adapter.parseBody($.content).description)this.logger.info(`Generating description for series: ${$.metadata.title}`),await Q.process({seriesId:$.id})}catch(w){this.logger.error(`Failed to generate description for series: ${$.id}`,{error:w})}}}function xGA(){return new TGA}w0();ZA();w0();ZA();ZA();w0();var gFQ=F.enum(["draft","queued","published"]),rJ=F.object({title:F.string(),slug:F.string().optional(),description:F.string().optional(),author:F.string().optional(),status:gFQ,publishedAt:F.string().datetime().optional(),event:F.string().optional(),coverImageId:F.string().optional()}),yFQ=rJ.pick({title:!0,description:!0,status:!0,publishedAt:!0,coverImageId:!0}).extend({slug:F.string()}),dd=FQ.extend({entityType:F.literal("deck"),metadata:yFQ}),id=dd.extend({frontmatter:rJ,body:F.string()}),Rf=id.extend({url:F.string().optional(),typeLabel:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()});class vGA extends _Q{constructor(){super({entityType:"deck",schema:dd,frontmatterSchema:rJ,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,rJ),$={...B,slug:B.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontmatter(A),B=this.extractBody(A);this.validateSlideStructure(B);let $=Q.slug??a1(Q.title),w=Q.status;return{entityType:"deck",content:A,metadata:{slug:$,title:Q.title,description:Q.description,status:w,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 Pf=new vGA;ZA();o8();var mFQ=F.object({markdown:F.string().describe("Markdown content with slide separators (---)")}),SGA=E1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:mFQ,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:$KA,fullscreen:!0}});o8();ZA();var hGA=F.object({decks:F.array(id)}),gGA=F.object({decks:F.array(Rf),pageTitle:F.string().optional()});import{jsxDEV as yGA}from"preact/jsx-dev-runtime";var mGA=({decks:A,pageTitle:Q})=>{let B=A.map(($)=>({id:$.id,url:$.url,title:$.frontmatter.title,date:$.frontmatter.publishedAt??$.created,description:$.frontmatter.description}));return yGA("div",{className:"deck-list bg-theme",children:yGA("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:yGA(LH,{title:Q??"Presentations",items:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};ZA();class rd extends W8{constructor(){super(hGA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var uGA=E1({name:"deck-list",description:"List view of all presentation decks",schema:gGA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new rd,layout:{component:mGA}});ZA();w0();var uFQ=F.object({title:F.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:F.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:F.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),vT0=E1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:uFQ,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
2486
2486
 
2487
2487
  Your task is to generate a complete slide deck based on the user's prompt.
2488
2488
 
@@ -2550,7 +2550,7 @@ Add your conclusion here`,I=I??`Presentation: ${Y}`,await this.reportProgress(Q,
2550
2550
  Note: This presentation is for "${w}".`:""}`,_=await this.context.ai.generate({prompt:L,templateName:"decks:generation"});Y=Y??_.title,X=X??_.content,I=I??_.description,await this.reportProgress(Q,{progress:50,message:`Generated deck: "${Y}"`})}else if(!I)await this.reportProgress(Q,{progress:30,message:"Generating description with AI"}),I=(await this.context.ai.generate({prompt:`Title: ${Y}
2551
2551
 
2552
2552
  Content:
2553
- ${X}`,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||!X)this.failEarly("Title and content are required");let G={slug:a1(Y),title:Y,status:"draft"},W=await xK({entityType:"deck",title:Y,deriveId:(N)=>N,regeneratePrompt:"Generate a different presentation deck title on the same topic.",context:this.context});if(W!==Y)G.title=W,G.slug=a1(W);let Z={title:G.title,status:G.status,slug:G.slug,description:I,author:$,event:w},q=d9(X,Z);return{id:W,content:q,metadata:G,title:W,resultExtras:{title:W,slug:G.slug},createOptions:{deduplicateId:!0}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var hT0={name:"@brains/decks",private:!0,version:"0.2.0-alpha.31",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 pGA extends z2{entityType=Pf.entityType;schema=Pf.schema;adapter=Pf;constructor(){super("decks",hT0)}createGenerationHandler(A){return new lGA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":SGA,"deck-list":uGA,generation:vT0,description:ST0}}getDataSources(){return[new cGA(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:$}=Q.payload;if(B!=="deck")return{success:!0};try{let w=await A.entityService.getEntity("deck",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Deck not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=new Date().toISOString(),Y={...w,metadata:{...w.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:$,result:{id:$}})}catch(w){await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:L0(w)})}return{success:!0}})}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let B=F.object({prompt:F.string(),event:F.string().optional()}).parse(Q);return A.ai.generate({prompt:`${B.prompt}${B.event?`
2553
+ ${X}`,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||!X)this.failEarly("Title and content are required");let G={slug:a1(Y),title:Y,status:"draft"},W=await xK({entityType:"deck",title:Y,deriveId:(N)=>N,regeneratePrompt:"Generate a different presentation deck title on the same topic.",context:this.context});if(W!==Y)G.title=W,G.slug=a1(W);let Z={title:G.title,status:G.status,slug:G.slug,description:I,author:$,event:w},q=d9(X,Z);return{id:W,content:q,metadata:G,title:W,resultExtras:{title:W,slug:G.slug},createOptions:{deduplicateId:!0}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var hT0={name:"@brains/decks",private:!0,version:"0.2.0-alpha.32",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 pGA extends z2{entityType=Pf.entityType;schema=Pf.schema;adapter=Pf;constructor(){super("decks",hT0)}createGenerationHandler(A){return new lGA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":SGA,"deck-list":uGA,generation:vT0,description:ST0}}getDataSources(){return[new cGA(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:$}=Q.payload;if(B!=="deck")return{success:!0};try{let w=await A.entityService.getEntity("deck",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Deck not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=new Date().toISOString(),Y={...w,metadata:{...w.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:$,result:{id:$}})}catch(w){await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:L0(w)})}return{success:!0}})}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let B=F.object({prompt:F.string(),event:F.string().optional()}).parse(Q);return A.ai.generate({prompt:`${B.prompt}${B.event?`
2554
2554
 
2555
2555
  Note: This presentation is for "${B.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let B=F.object({title:F.string(),content:F.string()}).parse(Q);return A.ai.generate({prompt:`Title: ${B.title}
2556
2556
 
@@ -2565,7 +2565,7 @@ Guidelines:
2565
2565
  3. Depth: Provide enough detail to be useful as a reference, but stay focused on the topic.
2566
2566
  4. Style: Informative and educational. Write as if explaining to yourself for future reference.
2567
2567
  5. Length: Adjust based on topic complexity - concise for simple topics, more detailed for complex ones.
2568
- 6. No meta-commentary: Just provide the content directly without phrases like "Here is..." or "This note covers..."`});w0();ZA();var mT0=F.object({prompt:F.string(),title:F.string().optional()}),iFQ=M7.extend({title:F.string().optional()});class nd extends a5{constructor(A,Q){super(A,Q,{schema:mT0,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"}),$=A.title??B.title;return await this.reportProgress(Q,{progress:50,message:`Generated note: "${$}"`}),{id:$,content:xE.createNoteContent($,B.body),metadata:{title:$},title:$,resultExtras:{title:$}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var uT0={name:"@brains/note",private:!0,version:"0.2.0-alpha.31",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 nGA extends z2{entityType=xE.entityType;schema=TE;adapter=xE;constructor(A={}){super("note",uT0,A,iGA)}createGenerationHandler(A){return new nd(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:rGA}}async onRegister(A){A.eval.registerHandler("generateNote",async(Q)=>{let B=F.object({prompt:F.string()}).parse(Q);return A.ai.generate({prompt:B.prompt,templateName:"note:generation"})})}}function i3(A={}){return new nGA(A)}w0();ZA();ZA();w0();var cT0=F.object({ref:F.string(),label:F.string()}),lT0=F.enum(["pending","draft","published"]),cH=F.object({status:lT0,title:F.string(),url:F.string().url(),description:F.string().optional(),keywords:F.array(F.string()),domain:F.string(),capturedAt:F.string().datetime(),source:cT0}),pT0=cH.pick({title:!0,status:!0}),ff=FQ.extend({entityType:F.literal("link"),metadata:pT0}),oGA=F.object({enableSummarization:F.boolean().default(!0).describe("Generate AI summaries for captured links"),autoExtractKeywords:F.boolean().default(!0).describe("Automatically extract keywords from content"),jinaApiKey:F.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});w0();class oJ extends _Q{constructor(){super({entityType:"link",schema:ff,frontmatterSchema:cH})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,keywords:A.keywords,domain:A.domain,capturedAt:A.capturedAt,source:A.source},B=A.summary??"";return this.buildMarkdown(B,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,cH),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 sGA=new oJ;w0();ZA();var nFQ=F.object({success:F.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:F.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:F.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:F.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:F.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false."),keywords:F.array(F.string()).describe("3-5 relevant keywords that categorize this content. Leave empty array if success is false.")}),dT0=E1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:nFQ,basePrompt:`You are an expert at extracting key information from webpage content.
2568
+ 6. No meta-commentary: Just provide the content directly without phrases like "Here is..." or "This note covers..."`});w0();ZA();var mT0=F.object({prompt:F.string(),title:F.string().optional()}),iFQ=M7.extend({title:F.string().optional()});class nd extends a5{constructor(A,Q){super(A,Q,{schema:mT0,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"}),$=A.title??B.title;return await this.reportProgress(Q,{progress:50,message:`Generated note: "${$}"`}),{id:$,content:xE.createNoteContent($,B.body),metadata:{title:$},title:$,resultExtras:{title:$}}}summarizeDataForLog(A){return{prompt:A.prompt,title:A.title}}}var uT0={name:"@brains/note",private:!0,version:"0.2.0-alpha.32",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 nGA extends z2{entityType=xE.entityType;schema=TE;adapter=xE;constructor(A={}){super("note",uT0,A,iGA)}createGenerationHandler(A){return new nd(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:rGA}}async onRegister(A){A.eval.registerHandler("generateNote",async(Q)=>{let B=F.object({prompt:F.string()}).parse(Q);return A.ai.generate({prompt:B.prompt,templateName:"note:generation"})})}}function i3(A={}){return new nGA(A)}w0();ZA();ZA();w0();var cT0=F.object({ref:F.string(),label:F.string()}),lT0=F.enum(["pending","draft","published"]),cH=F.object({status:lT0,title:F.string(),url:F.string().url(),description:F.string().optional(),keywords:F.array(F.string()),domain:F.string(),capturedAt:F.string().datetime(),source:cT0}),pT0=cH.pick({title:!0,status:!0}),ff=FQ.extend({entityType:F.literal("link"),metadata:pT0}),oGA=F.object({enableSummarization:F.boolean().default(!0).describe("Generate AI summaries for captured links"),autoExtractKeywords:F.boolean().default(!0).describe("Automatically extract keywords from content"),jinaApiKey:F.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});w0();class oJ extends _Q{constructor(){super({entityType:"link",schema:ff,frontmatterSchema:cH})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,keywords:A.keywords,domain:A.domain,capturedAt:A.capturedAt,source:A.source},B=A.summary??"";return this.buildMarkdown(B,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,cH),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 sGA=new oJ;w0();ZA();var nFQ=F.object({success:F.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:F.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:F.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:F.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:F.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false."),keywords:F.array(F.string()).describe("3-5 relevant keywords that categorize this content. Leave empty array if success is false.")}),dT0=E1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:nFQ,basePrompt:`You are an expert at extracting key information from webpage content.
2569
2569
 
2570
2570
  You will receive webpage content in markdown format. Your job is to extract structured information from it.
2571
2571
 
@@ -2583,7 +2583,7 @@ Focus only on information present in the provided content. Do not make up or hal
2583
2583
 
2584
2584
  `))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 tFQ}from"crypto";class r3{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(r3.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=tFQ("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}}}w0();ZA();var eFQ=F.object({url:F.string().url(),metadata:F.object({interfaceId:F.string().optional(),userId:F.string().optional(),channelId:F.string().optional(),channelName:F.string().optional(),timestamp:F.string().optional()}).optional()}),oAB=F.object({success:F.boolean(),entityId:F.string().optional(),title:F.string().optional(),url:F.string().optional(),status:F.enum(["pending","draft","published"]).optional(),error:F.string().optional()});class sd extends NB{context;linkAdapter;urlFetcher;constructor(A,Q,B){super(A,{schema:eFQ,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new oJ,this.urlFetcher=new vE(B?.jinaApiKey?{jinaApiKey:B.jinaApiKey}:void 0)}async process(A,Q,B){let{url:$,metadata:w}=A;try{await B.report({progress:GQ.START,total:100,message:"Starting link capture"});let D=r3.generateEntityId($);await B.report({progress:GQ.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:$,entityId:D});let{frontmatter:q}=this.linkAdapter.parseLinkContent(Y.content);return{success:!0,entityId:Y.id,title:q.title,url:$,status:Y.metadata.status}}await B.report({progress:GQ.FETCH,total:100,message:"Fetching webpage content"});let X=await this.urlFetcher.fetch($);if(!X.success){if(X.errorType==="url_not_found"||X.errorType==="url_unreachable")return this.logger.warn("Link URL not accessible",{url:$,errorType:X.errorType,error:X.error}),{success:!1,error:`Could not capture link: ${X.error}`}}await B.report({progress:GQ.PROCESS,total:100,message:"Extracting content with AI"});let I=await this.context.ai.generate({templateName:"link:extraction",prompt:X.success?`Extract structured information from this webpage content:
2585
2585
 
2586
- ${X.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${X.error}"`,data:{url:$,hasContent:X.success},interfacePermissionGrant:"public"});this.logger.debug("AI extraction result",{result:I}),await B.report({progress:GQ.EXTRACT,total:100,message:"Processing extraction results"});let K=this.resolveSource(w),G=new Date().toISOString();if(I.success===!1||!I.title||!I.description||!I.summary){let q=I.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await B.report({progress:GQ.SAVE,total:100,message:"Saving link as pending"});let N=this.linkAdapter.createLinkContent({status:"pending",title:q,url:$,description:I.description,summary:I.summary,keywords:I.keywords,domain:new URL($).hostname,capturedAt:G,source:K}),M=await this.context.entityService.createEntity({id:D,entityType:"link",content:N,metadata:{status:"pending",title:q}});return await B.report({progress:GQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:M.entityId,title:q,url:$,status:"pending"}}await B.report({progress:GQ.SAVE,total:100,message:`Saving link: "${I.title}"`});let W=this.linkAdapter.createLinkContent({status:"draft",title:I.title,url:$,description:I.description,summary:I.summary,keywords:I.keywords,domain:new URL($).hostname,capturedAt:G,source:K}),Z=await this.context.entityService.createEntity({id:D,entityType:"link",content:W,metadata:{status:"draft",title:I.title}});return await B.report({progress:GQ.COMPLETE,total:100,message:`Link captured: "${I.title}"`}),{success:!0,entityId:Z.entityId,title:I.title,url:$,status:"draft"}}catch(D){return this.logger.error("Link capture job failed",{error:D,jobId:Q,data:A}),I6.failure(D)}}resolveSource(A){let Q=A?.channelId,B=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:B??Q};let $=A?.interfaceId??"cli";return{ref:`${$}:local`,label:$.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}var nT0={name:"@brains/link",private:!0,version:"0.2.0-alpha.31",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 BJA extends z2{entityType=sGA.entityType;schema=ff;adapter=sGA;shell;constructor(A={}){super("link",nT0,A,oGA)}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 sd(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,X=typeof D?.status==="string"?D.status:void 0,I=this.extractFirstUrl(A.content);if(Y&&X&&I){let K=a1(I)||a1(Y)||`${A.entityType}-${Date.now()}`,G=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await B.entityService.createEntity({id:K,entityType:A.entityType,content:A.content,metadata:{title:Y,status:X},created:G,updated:G})).entityId,status:"created"}}}}}catch{}let $=this.extractFirstUrl(A.content,A.prompt,A.title);if($){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:$,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(w){return{kind:"handled",result:{success:!1,error:w instanceof Error?w.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 sd(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:dT0,"link-list":iT0,"link-detail":rT0}}getDataSources(){return[new QJA(this.logger.child("LinksDataSource"))]}async onRegister(A){A.eval.registerHandler("extractContent",async(Q)=>{let{url:B}=F.object({url:F.string().url()}).parse(Q),w=await new vE(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(B);if(!w.success)return{success:!1,error:w.error,errorType:w.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
2586
+ ${X.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${X.error}"`,data:{url:$,hasContent:X.success},interfacePermissionGrant:"public"});this.logger.debug("AI extraction result",{result:I}),await B.report({progress:GQ.EXTRACT,total:100,message:"Processing extraction results"});let K=this.resolveSource(w),G=new Date().toISOString();if(I.success===!1||!I.title||!I.description||!I.summary){let q=I.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await B.report({progress:GQ.SAVE,total:100,message:"Saving link as pending"});let N=this.linkAdapter.createLinkContent({status:"pending",title:q,url:$,description:I.description,summary:I.summary,keywords:I.keywords,domain:new URL($).hostname,capturedAt:G,source:K}),M=await this.context.entityService.createEntity({id:D,entityType:"link",content:N,metadata:{status:"pending",title:q}});return await B.report({progress:GQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:M.entityId,title:q,url:$,status:"pending"}}await B.report({progress:GQ.SAVE,total:100,message:`Saving link: "${I.title}"`});let W=this.linkAdapter.createLinkContent({status:"draft",title:I.title,url:$,description:I.description,summary:I.summary,keywords:I.keywords,domain:new URL($).hostname,capturedAt:G,source:K}),Z=await this.context.entityService.createEntity({id:D,entityType:"link",content:W,metadata:{status:"draft",title:I.title}});return await B.report({progress:GQ.COMPLETE,total:100,message:`Link captured: "${I.title}"`}),{success:!0,entityId:Z.entityId,title:I.title,url:$,status:"draft"}}catch(D){return this.logger.error("Link capture job failed",{error:D,jobId:Q,data:A}),I6.failure(D)}}resolveSource(A){let Q=A?.channelId,B=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:B??Q};let $=A?.interfaceId??"cli";return{ref:`${$}:local`,label:$.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}var nT0={name:"@brains/link",private:!0,version:"0.2.0-alpha.32",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 BJA extends z2{entityType=sGA.entityType;schema=ff;adapter=sGA;shell;constructor(A={}){super("link",nT0,A,oGA)}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 sd(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,X=typeof D?.status==="string"?D.status:void 0,I=this.extractFirstUrl(A.content);if(Y&&X&&I){let K=a1(I)||a1(Y)||`${A.entityType}-${Date.now()}`,G=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await B.entityService.createEntity({id:K,entityType:A.entityType,content:A.content,metadata:{title:Y,status:X},created:G,updated:G})).entityId,status:"created"}}}}}catch{}let $=this.extractFirstUrl(A.content,A.prompt,A.title);if($){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:$,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(w){return{kind:"handled",result:{success:!1,error:w instanceof Error?w.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 sd(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:dT0,"link-list":iT0,"link-detail":rT0}}getDataSources(){return[new QJA(this.logger.child("LinksDataSource"))]}async onRegister(A){A.eval.registerHandler("extractContent",async(Q)=>{let{url:B}=F.object({url:F.string().url()}).parse(Q),w=await new vE(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(B);if(!w.success)return{success:!1,error:w.error,errorType:w.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
2587
2587
 
2588
2588
  ${w.content}`,data:{url:B,hasContent:!0},interfacePermissionGrant:"public"})})}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[B]=r3.extractUrls(Q);if(B)return B}return}}function oT0(A={}){return new BJA(A)}var n3=oT0;ZA();var Z0B=F.object({id:F.string().optional(),metadata:F.object({conversationId:F.string().optional(),interfaceId:F.string().optional(),userId:F.string().optional(),messageId:F.string().optional(),timestamp:F.string().optional()}).optional()});w0();ZA();o8();ZA();w0();var sT0=F.enum(["draft","published"]),A4=F.object({title:F.string(),slug:F.string().optional(),status:sT0,publishedAt:F.string().datetime().optional(),description:F.string(),year:F.number(),coverImageId:F.string().optional(),url:F.string().url().optional()}),aT0=A4.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:F.string()}),SE=FQ.extend({entityType:F.literal("project"),metadata:aT0}),ad=F.object({context:F.string(),problem:F.string(),solution:F.string(),outcome:F.string()}),Tf=SE.extend({frontmatter:A4,body:F.string(),structuredContent:ad.optional(),coverImageUrl:F.string().optional()}),hE=Tf.extend({url:F.string().optional(),typeLabel:F.string().optional(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()}),Q3Q=Tf.extend({url:F.string(),typeLabel:F.string(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()});w0();ZA();ZA();class $JA extends W8{constructor(){super(ad,{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 wJA=new $JA;class DJA extends _Q{constructor(){super({entityType:"project",schema:SE,frontmatterSchema:A4,supportsCoverImage:!0,bodyFormatter:wJA})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,A4),$={...B,slug:B.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,A4),B=Q.slug??a1(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,A4)}parseStructuredContent(A){return wJA.parse(this.extractBody(A.content))}createProjectContent(A,Q){let B=wJA.format(Q);return this.buildMarkdown(B,A)}}var sJ=new DJA;ZA();var YJA=F.object({});import{jsxDEV as aw,Fragment as $3Q}from"preact/jsx-dev-runtime";var B3Q=({project:A})=>{let{frontmatter:Q,url:B,coverImageUrl:$}=A;return aw(V2,{href:B,children:[$&&aw("img",{src:$,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),aw(K$,{children:Q.title},void 0,!1,void 0,this),aw("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},XJA=({projects:A,pageTitle:Q,pagination:B,baseUrl:$="/projects"})=>{let w=Q??"Projects",D=B?.totalItems??A.length,Y=`Browse all ${D} ${D===1?"project":"projects"}`;return aw($3Q,{children:[aw(iQ,{title:w,description:Y},void 0,!1,void 0,this),aw("div",{className:"project-list bg-theme",children:aw("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[aw("h1",{className:"text-4xl font-bold text-heading mb-12",children:w},void 0,!1,void 0,this),aw("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((X)=>aw(B3Q,{project:X},X.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&aw("div",{className:"mt-12",children:aw(MY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},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 XB,Fragment as tT0}from"preact/jsx-dev-runtime";var w3Q=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return XB("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:XB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?XB(V2,{href:A.url,variant:"compact",children:[XB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),XB("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):XB("div",{},void 0,!1,void 0,this),Q&&XB(V2,{href:Q.url,variant:"compact",className:"md:text-right",children:[XB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),XB("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)},td=({title:A,content:Q})=>{if(!Q)return null;return XB("section",{className:"mb-12",children:[XB("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),XB(EY,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},IJA=({project:A,prevProject:Q,nextProject:B})=>{let{frontmatter:$,structuredContent:w,metadata:D,coverImageUrl:Y}=A;return XB(tT0,{children:[XB(iQ,{title:$.title,description:$.description,...Y&&{ogImage:Y},ogType:"article"},void 0,!1,void 0,this),XB("article",{className:"project-detail",children:XB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:XB("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&XB(NH,{src:Y,alt:$.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),XB("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:$.title},void 0,!1,void 0,this),XB("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[XB("span",{className:"text-sm",children:D.year},void 0,!1,void 0,this),$.url&&XB(tT0,{children:[XB("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),XB("a",{href:$.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),XB("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:$.description},void 0,!1,void 0,this),w&&XB("div",{className:"case-study",children:[XB(td,{title:"Context",content:w.context},void 0,!1,void 0,this),XB(td,{title:"Problem",content:w.problem},void 0,!1,void 0,this),XB(td,{title:"Solution",content:w.solution},void 0,!1,void 0,this),XB(td,{title:"Outcome",content:w.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),XB(w3Q,{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)};ZA();w0();var D3Q=F.object({title:F.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:F.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:F.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:F.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:F.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:F.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),KJA=E1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:D3Q,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
2589
2589
 
@@ -2602,7 +2602,7 @@ Guidelines:
2602
2602
  CRITICAL: Only include information that can be derived from the provided content. If information is missing, keep that section brief rather than inventing details.
2603
2603
 
2604
2604
  Tone: Professional but accessible. Write for someone evaluating real work.
2605
- Structure: Use markdown formatting. Break long sections into paragraphs for readability.`});w0();ZA();var Y3Q=F.object({prompt:F.string(),year:F.number(),title:F.string().optional()}),n0B=M7.extend({title:F.string().optional()});class ed extends a5{constructor(A,Q){super(A,Q,{schema:Y3Q,jobTypeName:"project-generation",entityType:"project"})}async generate(A,Q){let{prompt:B,year:$}=A;await this.reportProgress(Q,{progress:10,message:"Generating project content with AI"});let w=await this.context.ai.generate({prompt:B,templateName:"portfolio:generation"}),D=A.title??w.title,Y=a1(D);await this.reportProgress(Q,{progress:50,message:`Generated project: "${D}"`});let X={title:D,slug:Y,status:"draft",description:w.description,year:$},I={context:w.context,problem:w.problem,solution:w.solution,outcome:w.outcome};return{id:Y,content:sJ.createProjectContent(X,I),metadata:{title:D,slug:Y,status:"draft",year:$},title:D,resultExtras:{title:D}}}summarizeDataForLog(A){return{prompt:A.prompt.substring(0,100),year:A.year,title:A.title}}}w0();w0();function X3Q(A){let Q=JQ(A.content,A4),B=sJ.parseStructuredContent(A);return Tf.parse({...A,frontmatter:Q.metadata,body:Q.content,structuredContent:B})}class Ai extends i9{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 X3Q(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 eT0={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.31",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 K3Q=F.object({projects:F.array(hE),pageTitle:F.string().optional(),pagination:j7.nullable(),baseUrl:F.string().optional()});class HJA extends z2{entityType=sJ.entityType;schema=SE;adapter=sJ;constructor(A={}){super("portfolio",eT0,A,YJA)}createGenerationHandler(A){return new ed(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":E1({name:"project-list",description:"Portfolio project list page template",schema:K3Q,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:XJA}}),"project-detail":E1({name:"project-detail",description:"Individual project case study template",schema:F.object({project:hE,prevProject:hE.nullable(),nextProject:hE.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:IJA}}),generation:KJA}}getDataSources(){return[new Ai(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=F.object({prompt:F.string(),year:F.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:$}=Q.payload;if(B!=="project")return{success:!0};try{let w=await A.entityService.getEntity("project",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Project not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=JQ(w.content,A4),Y=new Date().toISOString(),X=d9(D.content,{...D.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({...w,content:X,metadata:{...w.metadata,status:"published",publishedAt:Y}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:$,publishedAt:Y})}catch(w){await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:L0(w)})}return{success:!0}})}}function UJA(A={}){return new HJA(A)}w0();ZA();ZA();var Ax0=F.object({includeEntityTypes:F.array(F.string()).default([]),minRelevanceScore:F.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:F.number().min(0).max(1).default(0.85),autoMerge:F.boolean().default(!0),enableAutoExtraction:F.boolean().default(!0)});w0();ZA();w0();var H3Q=F.object({aliases:F.array(F.string()).optional()}),Qi=FQ.extend({entityType:F.literal("topic"),metadata:H3Q}),_1B=F.object({content:F.string(),keywords:F.array(F.string())}),Qx0=F.object({title:F.string().describe("Topic title"),keywords:F.array(F.string()).optional().describe("Topic keywords")}),k1B=F.object({timeWindowHours:F.number().min(1),minRelevanceScore:F.number().min(0).max(1)}),f1B=F.object({topicIds:F.array(F.string()).min(2),similarityThreshold:F.number().min(0).max(1)});class tw extends _Q{constructor(){super({entityType:"topic",schema:Qi,frontmatterSchema:Qx0})}buildFrontmatter(A,Q){return{title:A,...Q.length>0&&{keywords:Q}}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title,Q.keywords))}fromMarkdown(A){return{content:A,entityType:"topic"}}extractMetadata(A){return{aliases:A.metadata.aliases??[]}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),$=this.buildMarkdown("",this.buildFrontmatter(Q.title,Q.keywords)).match(/^---\n[\s\S]*?\n---/);return $?$[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),keywords:Q.keywords??[],formatted:A,title:Q.title}}catch{return{content:A,keywords:[],formatted:A,title:"Unknown Topic"}}return{content:A,keywords:[],formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title,A.keywords))}}ZA();var Bx0=40,U3Q=new tw;async function Bi(A,Q=Bx0){return(await A.listEntities("topic",{limit:Q})).map(($)=>U3Q.parseTopicBody($.content).title).filter(($)=>$.trim().length>0)}function $i(A){let Q=(A.existingTopicTitles??[]).slice(0,Bx0),B=Q.length>0?`
2605
+ Structure: Use markdown formatting. Break long sections into paragraphs for readability.`});w0();ZA();var Y3Q=F.object({prompt:F.string(),year:F.number(),title:F.string().optional()}),n0B=M7.extend({title:F.string().optional()});class ed extends a5{constructor(A,Q){super(A,Q,{schema:Y3Q,jobTypeName:"project-generation",entityType:"project"})}async generate(A,Q){let{prompt:B,year:$}=A;await this.reportProgress(Q,{progress:10,message:"Generating project content with AI"});let w=await this.context.ai.generate({prompt:B,templateName:"portfolio:generation"}),D=A.title??w.title,Y=a1(D);await this.reportProgress(Q,{progress:50,message:`Generated project: "${D}"`});let X={title:D,slug:Y,status:"draft",description:w.description,year:$},I={context:w.context,problem:w.problem,solution:w.solution,outcome:w.outcome};return{id:Y,content:sJ.createProjectContent(X,I),metadata:{title:D,slug:Y,status:"draft",year:$},title:D,resultExtras:{title:D}}}summarizeDataForLog(A){return{prompt:A.prompt.substring(0,100),year:A.year,title:A.title}}}w0();w0();function X3Q(A){let Q=JQ(A.content,A4),B=sJ.parseStructuredContent(A);return Tf.parse({...A,frontmatter:Q.metadata,body:Q.content,structuredContent:B})}class Ai extends i9{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 X3Q(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 eT0={name:"@brains/portfolio",private:!0,version:"0.2.0-alpha.32",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 K3Q=F.object({projects:F.array(hE),pageTitle:F.string().optional(),pagination:j7.nullable(),baseUrl:F.string().optional()});class HJA extends z2{entityType=sJ.entityType;schema=SE;adapter=sJ;constructor(A={}){super("portfolio",eT0,A,YJA)}createGenerationHandler(A){return new ed(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":E1({name:"project-list",description:"Portfolio project list page template",schema:K3Q,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:XJA}}),"project-detail":E1({name:"project-detail",description:"Individual project case study template",schema:F.object({project:hE,prevProject:hE.nullable(),nextProject:hE.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:IJA}}),generation:KJA}}getDataSources(){return[new Ai(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=F.object({prompt:F.string(),year:F.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:$}=Q.payload;if(B!=="project")return{success:!0};try{let w=await A.entityService.getEntity("project",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Project not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=JQ(w.content,A4),Y=new Date().toISOString(),X=d9(D.content,{...D.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({...w,content:X,metadata:{...w.metadata,status:"published",publishedAt:Y}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:$,publishedAt:Y})}catch(w){await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:L0(w)})}return{success:!0}})}}function UJA(A={}){return new HJA(A)}w0();ZA();ZA();var Ax0=F.object({includeEntityTypes:F.array(F.string()).default([]),minRelevanceScore:F.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:F.number().min(0).max(1).default(0.85),autoMerge:F.boolean().default(!0),enableAutoExtraction:F.boolean().default(!0)});w0();ZA();w0();var H3Q=F.object({aliases:F.array(F.string()).optional()}),Qi=FQ.extend({entityType:F.literal("topic"),metadata:H3Q}),_1B=F.object({content:F.string(),keywords:F.array(F.string())}),Qx0=F.object({title:F.string().describe("Topic title"),keywords:F.array(F.string()).optional().describe("Topic keywords")}),k1B=F.object({timeWindowHours:F.number().min(1),minRelevanceScore:F.number().min(0).max(1)}),f1B=F.object({topicIds:F.array(F.string()).min(2),similarityThreshold:F.number().min(0).max(1)});class tw extends _Q{constructor(){super({entityType:"topic",schema:Qi,frontmatterSchema:Qx0})}buildFrontmatter(A,Q){return{title:A,...Q.length>0&&{keywords:Q}}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title,Q.keywords))}fromMarkdown(A){return{content:A,entityType:"topic"}}extractMetadata(A){return{aliases:A.metadata.aliases??[]}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),$=this.buildMarkdown("",this.buildFrontmatter(Q.title,Q.keywords)).match(/^---\n[\s\S]*?\n---/);return $?$[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),keywords:Q.keywords??[],formatted:A,title:Q.title}}catch{return{content:A,keywords:[],formatted:A,title:"Unknown Topic"}}return{content:A,keywords:[],formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title,A.keywords))}}ZA();var Bx0=40,U3Q=new tw;async function Bi(A,Q=Bx0){return(await A.listEntities("topic",{limit:Q})).map(($)=>U3Q.parseTopicBody($.content).title).filter(($)=>$.trim().length>0)}function $i(A){let Q=(A.existingTopicTitles??[]).slice(0,Bx0),B=Q.length>0?`
2606
2606
 
2607
2607
  Existing topic titles to reuse when they clearly fit:
2608
2608
  ${Q.map(($)=>`- ${$}`).join(`
@@ -2710,13 +2710,13 @@ RULES:
2710
2710
  Return JSON with:
2711
2711
  - title
2712
2712
  - content
2713
- - keywords`,requiredPermission:"public"});o8();ZA();var O3Q=F.object({id:F.string(),title:F.string(),summary:F.string(),keywords:F.array(F.string()),created:F.string(),updated:F.string()}),vf=F.object({topics:F.array(O3Q),totalCount:F.number()});import{jsxDEV as gY}from"preact/jsx-dev-runtime";var WJA=({topics:A,totalCount:Q})=>{return gY("div",{className:"topic-list-container w-full max-w-4xl mx-auto p-6 bg-theme",children:[gY(LY,{title:"Topics",count:Q,singularLabel:"topic",description:"discovered from your knowledge base"},void 0,!1,void 0,this),gY("div",{className:"space-y-6",children:A.map((B)=>gY(V2,{variant:"vertical",children:[gY(K$,{href:`/topics/${B.id}`,className:"text-xl",children:B.title},void 0,!1,void 0,this),gY("p",{className:"text-theme-muted mb-4",children:B.summary},void 0,!1,void 0,this),gY(H$,{tags:B.keywords,maxVisible:5,variant:"muted",className:"mb-3"},void 0,!1,void 0,this),gY(Q7,{children:gY("div",{className:"flex justify-between text-sm text-theme-muted",children:gY("time",{dateTime:B.updated,children:["Updated ",g8(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&&gY(iw,{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)};ZA();class Ii extends W8{constructor(){super(vf,{title:"Topic List",mappings:[{key:"topics",label:"Topics",type:"array",itemType:"object"},{key:"totalCount",label:"Total Count",type:"number"}]})}}var Zx0=E1({name:"topics:topic-list",description:"List view of all discovered topics",schema:vf,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Ii,layout:{component:WJA}});o8();ZA();var Sf=F.object({id:F.string(),title:F.string(),content:F.string(),keywords:F.array(F.string()),created:F.string(),updated:F.string()});import{jsxDEV as aJ}from"preact/jsx-dev-runtime";var ZJA=({title:A,content:Q,keywords:B,created:$,updated:w})=>{return aJ("article",{className:"topic-detail-container max-w-4xl mx-auto p-6 bg-theme",children:[aJ(Z3,{title:A,created:$,updated:w},void 0,!1,void 0,this),aJ("div",{className:"prose prose-lg max-w-none mb-8 text-theme-muted",children:aJ("div",{dangerouslySetInnerHTML:{__html:Q}},void 0,!1,void 0,this)},void 0,!1,void 0,this),B.length>0&&aJ("section",{className:"mb-8",children:[aJ("h2",{className:"text-xl font-semibold mb-3 text-theme",children:"Keywords"},void 0,!1,void 0,this),aJ(H$,{tags:B,maxVisible:B.length,size:"sm"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aJ(J3,{href:"/topics",children:"Back to Topics"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};ZA();class Ki extends W8{constructor(){super(Sf,{title:"Topic Detail",mappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"content",label:"Content",type:"string"},{key:"keywords",label:"Keywords",type:"array",itemType:"string"},{key:"created",label:"Created",type:"string"},{key:"updated",label:"Updated",type:"string"}]})}}var Fx0=E1({name:"topics:topic-detail",description:"Detailed view of a single topic",schema:Sf,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Ki,layout:{component:ZJA}});w0();ZA();class FJA extends i9{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 tw;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:$G(Q.content,200),keywords:Q.keywords,created:A.created,updated:A.updated}}buildListResult(A,Q,B){return{topics:A,totalCount:A.length}}async fetch(A,Q,B){let{query:$}=this.parseQuery(A);if($.id){let D=await B.entityService.getEntity(this.config.entityType,$.id);if(!D)throw Error(`Entity not found: ${$.id}`);let Y=this.adapter.parseTopicBody(D.content);return Q.parse({id:D.id,title:Y.title,content:Y.content,keywords:Y.keywords,created:D.created,updated:D.updated})}return super.fetch(A,Q,B)}}d4();function qx0(){let A=new tw;return async(Q)=>{if(!Q.hasEntityType("topic"))return{topics:[]};return{topics:(await Q.listEntities("topic")).map((w)=>{let D=A.parseTopicBody(w.content);return{topic:w.id,title:D.title,keywords:D.keywords}})}}}var zx0={name:"@brains/topics",private:!0,version:"0.2.0-alpha.31",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 R3Q=new tw;function P3Q(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 Vx0 extends z2{entityType="topic";schema=Qi;adapter=R3Q;autoExtractionEnabled=!1;initialDerivationDone=!1;constructor(A={}){super("topics",zx0,A,Ax0)}getEntityTypeConfig(){return{weight:0.5}}getTemplates(){return{extraction:Jx0,"merge-synthesis":Wx0,"topic-list":Zx0,"topic-detail":Fx0}}getDataSources(){return[new FJA(this.logger.child("TopicsDataSource"))]}async onRegister(A){let Q=new Xi(A,this.logger);A.jobs.registerHandler("process-single",Q);let B=new JJA(A,this.logger);if(A.jobs.registerHandler("extract",B),A.insights.register("topic-distribution",qx0()),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((w)=>{let D=this.adapter.parseTopicBody(w.content),Y=P3Q(D.content);return{id:w.id,name:D.title||w.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 $=async(w)=>{if(!this.autoExtractionEnabled)return{success:!0};let{entityType:D,entity:Y}=w.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",$),A.messaging.subscribe("entity:updated",$)}}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 Yi(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 Q4(Q.entityService,this.logger),$=await B.listTopics();for(let D of $)await B.deleteTopic(D.id);if(A.length===0)return{deleted:$.length,created:0,skipped:0,batches:0};let w=await Yi(A,Q,this.logger);return{deleted:$.length,...w}}async getEntitiesToExtract(A){let Q=this.getExtractableEntityTypes(A),B=[];for(let $ of Q){let w=await A.entityService.listEntities($);for(let D of w){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 xf(A,this.logger),B=F.object({entityType:F.string(),content:F.string(),metadata:F.record(F.unknown()).optional()}),$=(N,M="")=>({id:`eval${M}-${Date.now()}`,entityType:N.entityType,content:N.content,contentHash:nB(N.content),metadata:N.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}),w=async(N,M,L="")=>{let _=$(N,L);return Q.extractFromEntity(_,M)},D=B.extend({minRelevanceScore:F.number().optional()});A.eval.registerHandler("extractFromEntity",async(N)=>{let M=D.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore;return w(M,L)});let Y=F.object({contentA:B,contentB:B,minRelevanceScore:F.number().optional()});A.eval.registerHandler("checkMergeSimilarity",async(N)=>{let M=Y.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore,[_,T]=await Promise.all([w(M.contentA,L,"-a"),w(M.contentB,L,"-b")]),P=_.map((g)=>g.title.toLowerCase()),r=T.map((g)=>g.title.toLowerCase()),n=P.filter((g)=>r.includes(g));return{topicsA:_.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),topicsB:T.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),matchingTitles:n,wouldMerge:n.length>0}});let X=F.object({title:F.string(),content:F.string(),keywords:F.array(F.string())}),I=F.object({existingTopics:F.array(X),incomingTopic:X,threshold:F.number().optional()});A.eval.registerHandler("detectMergeCandidate",async(N)=>{let M=I.parse(N),L=M.threshold??this.config.mergeSimilarityThreshold,_=new Q4(A.entityService,this.logger);for(let P of M.existingTopics)await _.createTopic(P);let T=await _.findMergeCandidate({title:M.incomingTopic.title,keywords:M.incomingTopic.keywords},L);return{found:T!==null,candidateTitle:T?.title,candidateScore:T?.score}});let K=F.object({existingAliases:F.array(F.string()).optional(),canonicalTitle:F.string(),candidateAliases:F.array(F.string())});A.eval.registerHandler("mergeAliases",async(N)=>{let M=K.parse(N);return{aliases:new Q4(A.entityService,this.logger).mergeAliases(M.existingAliases,M.canonicalTitle,M.candidateAliases)}});let G=F.object({existingTopics:F.array(X.extend({aliases:F.array(F.string()).optional()})).default([]),incomingTopic:X.extend({relevanceScore:F.number().min(0).max(1).optional()}),threshold:F.number().optional()});A.eval.registerHandler("processTopicWithAutoMerge",async(N)=>{let M=G.parse(N),L=new Q4(A.entityService,this.logger);for(let n of M.existingTopics)await L.createTopic({title:n.title,content:n.content,keywords:n.keywords,metadata:{aliases:n.aliases??[]}});let _=new Xi(A,this.logger),T=n5.from(async()=>{});if(!T)throw Error("Failed to create progress reporter");let P=await _.process({topic:{title:M.incomingTopic.title,content:M.incomingTopic.content,keywords:M.incomingTopic.keywords,relevanceScore:M.incomingTopic.relevanceScore??0.9},sourceEntityId:"eval-source",sourceEntityType:"post",autoMerge:!0,mergeSimilarityThreshold:M.threshold??this.config.mergeSimilarityThreshold},`eval-job-${Date.now()}`,T),r=await A.entityService.listEntities("topic");return{...P,topicCount:r.length,topics:r.map((n)=>{let g=this.adapter.parseTopicBody(n.content);return{id:n.id,title:g.title,content:g.content,keywords:g.keywords,metadata:n.metadata}})}});let W=F.object({entities:F.array(B).min(1),minRelevanceScore:F.number().optional()}),Z=F.object({existingTopics:F.array(X).optional(),entities:F.array(B)});A.eval.registerHandler("rebuildTopics",async(N)=>{let M=Z.parse(N),L=new Q4(A.entityService,this.logger);for(let r of M.existingTopics??[])await L.createTopic(r);let _=M.entities.map((r,n)=>$(r,`-rebuild-${n}`)),T=await this.replaceAllTopics(_,A),P=await A.entityService.listEntities("topic");return{...T,topicCount:P.length,topics:P.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,keywords:n.keywords,metadata:r.metadata}})}}),A.eval.registerHandler("extractSequentially",async(N)=>{let M=W.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore,_=new Q4(A.entityService,this.logger),T=[];for(let[r,n]of M.entities.entries()){let g=$(n,`-sequential-${r}`),x=await Q.extractFromEntity(g,L);for(let S of x)await _.createTopic({title:S.title,content:S.content,keywords:S.keywords});T.push({extractedTitles:x.map((S)=>S.title)})}let P=await A.entityService.listEntities("topic");return{totalTopics:P.length,perEntity:T,topics:P.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,keywords:n.keywords}})}});let q=F.object({entities:F.array(B)});A.eval.registerHandler("batchExtract",async(N)=>{let L=q.parse(N).entities.map((P,r)=>$(P,`-batch-${r}`)),_=await Yi(L,A,this.logger),T=await A.entityService.listEntities("topic");return{..._,topics:T.map((P)=>{let r=this.adapter.parseTopicBody(P.content);return{id:P.id,title:r.title,content:r.content,keywords:r.keywords}})}})}}function Hi(A){return new Vx0(A)}w0();ZA();w0();var Nx0=F.enum(["linkedin"]),Lx0=F.enum(["draft","queued","published","failed"]),Ex0=F.enum(["post","deck"]),B4=F.object({title:F.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Nx0.describe("Target platform"),status:Lx0,coverImageId:F.string().optional().describe("Image entity ID for post image"),publishedAt:F.string().datetime().optional(),platformPostId:F.string().optional().describe("ID from platform after publishing"),sourceEntityId:F.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Ex0.optional().describe("Source entity type (post, deck)")}),Mx0=B4.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:F.string().describe("URL-friendly identifier: {platform}-{title}")}),gE=FQ.extend({entityType:F.literal("social-post"),metadata:Mx0}),Ui=gE.extend({frontmatter:B4,body:F.string()}),Gi=Ui.extend({url:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional(),typeLabel:F.string().optional(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()});w0();ZA();class qJA extends _Q{constructor(){super({entityType:"social-post",schema:gE,frontmatterSchema:B4,supportsCoverImage:!0})}toMarkdown(A){let Q="",B={};try{B=this.parseFrontMatter(A.content,B4),Q=this.extractBody(A.content)}catch{Q=A.content}let $={...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,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,B4),B=`${Q.platform}-${a1(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,B4)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}}var r7=new qJA;w0();w0();ZA();var _3Q=UG.extend({platform:F.enum(["linkedin"]).optional(),status:F.enum(["draft","queued","published","failed"]).optional(),sortByQueue:F.boolean().optional(),nextInQueue:F.boolean().optional()}),k3Q=GG.extend({query:_3Q.optional()});function Cx0(A){let Q=JQ(A.content,B4);return Ui.parse({...A,frontmatter:Q.metadata,body:Q.content})}class Ji extends i9{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=k3Q.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Cx0(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:$}=this.parseQuery(A),w=B.entityService;if($.nextInQueue)return this.fetchNextInQueue(Q,w);if($.id){let{item:G}=await this.fetchDetail($.id,w);return Q.parse(this.buildDetailResult(G,null))}let D={};if($.platform)D.platform=$.platform;if($.status)D.status=$.status;let Y=Object.keys(D).length>0,X=$.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:I,pagination:K}=await this.fetchList($,w,{...Y&&{filter:{metadata:D}},sortFields:X});return Q.parse(this.buildListResult(I,K,$))}async fetchNextInQueue(A,Q){let $=(await Q.listEntities(this.config.entityType,{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}))[0],w=$?Cx0($):null;return A.parse({post:w})}}ZA();var Ox0=F.object({accessToken:F.string().optional(),refreshToken:F.string().optional(),organizationId:F.string().optional()}),zJA=F.object({linkedin:Ox0.optional(),publishInterval:F.number().default(3600000),enabled:F.boolean().default(!0),defaultPrompt:F.string().default("Create an engaging social media post that drives engagement"),maxRetries:F.number().default(3),autoGenerateOnBlogPublish:F.boolean().default(!1)});w0();ZA();NJA();import{jsxDEV as h6,Fragment as T3Q}from"preact/jsx-dev-runtime";function f3Q(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function b3Q(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var Zi=({posts:A,pageTitle:Q,pagination:B,baseUrl:$="/social-posts"})=>{let w=Q??"Social Posts",D=B?.totalItems??A.length,Y=`Browse all ${D} social ${D===1?"post":"posts"}`;return h6(T3Q,{children:[h6(iQ,{title:w,description:Y},void 0,!1,void 0,this),h6("div",{className:"social-post-list bg-theme",children:h6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[h6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:w},void 0,!1,void 0,this),A.length===0?h6("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):h6("ul",{className:"space-y-6",children:A.map((X)=>h6("li",{children:h6(V2,{href:X.url,variant:"horizontal",children:h6("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&h6("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),h6("div",{className:"flex-1 min-w-0",children:[h6("div",{className:"flex items-start justify-between gap-4 mb-2",children:[h6("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),h6("time",{className:"text-sm text-theme-muted shrink-0",children:b3Q(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h6("div",{className:"flex items-center gap-2 mb-3",children:[h6(l7,{status:X.frontmatter.status},void 0,!1,void 0,this),h6("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),h6("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h6("p",{className:"text-theme leading-relaxed",children:f3Q(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&h6(MY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as g6,Fragment as x3Q}from"preact/jsx-dev-runtime";function jx0(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var Fi=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,B=A.body.slice(0,160),$=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return g6(x3Q,{children:[g6(iQ,{title:Q,description:B},void 0,!1,void 0,this),g6("section",{className:"social-post-detail",children:g6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:g6("div",{className:"max-w-3xl mx-auto",children:[g6(oD,{items:$},void 0,!1,void 0,this),g6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),g6("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[g6(l7,{status:A.frontmatter.status},void 0,!1,void 0,this),g6("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),g6("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&&g6(NH,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),g6(V2,{className:"p-8 mb-8",children:g6("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),g6("div",{className:"space-y-4 text-sm text-theme-muted",children:[g6("div",{children:[g6("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",jx0(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&g6("div",{children:[g6("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",jx0(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&g6("div",{children:g6("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 hf(A){return`social-media:${A}`}var LJA=F.object({prompt:F.string().optional(),platform:F.enum(["linkedin"]).optional(),sourceEntityType:F.enum(["post","deck"]).optional(),sourceEntityId:F.string().optional(),title:F.string().optional().describe("Required when content is provided directly"),content:F.string().optional(),addToQueue:F.boolean().optional(),generateImage:F.boolean().optional().describe("Auto-generate cover image for post")}),v3Q=M7.extend({slug:F.string().optional()});class o3 extends a5{constructor(A,Q){super(A,Q,{schema:LJA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let B=A.platform??"linkedin",$=A.addToQueue??!1,{prompt:w,sourceEntityType:D,sourceEntityId:Y}=A,{content:X,title:I}=A;if(X&&I)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!I){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:X,templateName:hf(B)});I=L.title,X=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 T=F.object({slug:F.string()}).safeParse(L.metadata),P=T.success?T.data.slug:Y,r=await this.context.ai.generate({prompt:`Create an engaging ${B} post to promote this ${D}:
2713
+ - keywords`,requiredPermission:"public"});o8();ZA();var O3Q=F.object({id:F.string(),title:F.string(),summary:F.string(),keywords:F.array(F.string()),created:F.string(),updated:F.string()}),vf=F.object({topics:F.array(O3Q),totalCount:F.number()});import{jsxDEV as gY}from"preact/jsx-dev-runtime";var WJA=({topics:A,totalCount:Q})=>{return gY("div",{className:"topic-list-container w-full max-w-4xl mx-auto p-6 bg-theme",children:[gY(LY,{title:"Topics",count:Q,singularLabel:"topic",description:"discovered from your knowledge base"},void 0,!1,void 0,this),gY("div",{className:"space-y-6",children:A.map((B)=>gY(V2,{variant:"vertical",children:[gY(K$,{href:`/topics/${B.id}`,className:"text-xl",children:B.title},void 0,!1,void 0,this),gY("p",{className:"text-theme-muted mb-4",children:B.summary},void 0,!1,void 0,this),gY(H$,{tags:B.keywords,maxVisible:5,variant:"muted",className:"mb-3"},void 0,!1,void 0,this),gY(Q7,{children:gY("div",{className:"flex justify-between text-sm text-theme-muted",children:gY("time",{dateTime:B.updated,children:["Updated ",g8(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&&gY(iw,{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)};ZA();class Ii extends W8{constructor(){super(vf,{title:"Topic List",mappings:[{key:"topics",label:"Topics",type:"array",itemType:"object"},{key:"totalCount",label:"Total Count",type:"number"}]})}}var Zx0=E1({name:"topics:topic-list",description:"List view of all discovered topics",schema:vf,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Ii,layout:{component:WJA}});o8();ZA();var Sf=F.object({id:F.string(),title:F.string(),content:F.string(),keywords:F.array(F.string()),created:F.string(),updated:F.string()});import{jsxDEV as aJ}from"preact/jsx-dev-runtime";var ZJA=({title:A,content:Q,keywords:B,created:$,updated:w})=>{return aJ("article",{className:"topic-detail-container max-w-4xl mx-auto p-6 bg-theme",children:[aJ(Z3,{title:A,created:$,updated:w},void 0,!1,void 0,this),aJ("div",{className:"prose prose-lg max-w-none mb-8 text-theme-muted",children:aJ("div",{dangerouslySetInnerHTML:{__html:Q}},void 0,!1,void 0,this)},void 0,!1,void 0,this),B.length>0&&aJ("section",{className:"mb-8",children:[aJ("h2",{className:"text-xl font-semibold mb-3 text-theme",children:"Keywords"},void 0,!1,void 0,this),aJ(H$,{tags:B,maxVisible:B.length,size:"sm"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aJ(J3,{href:"/topics",children:"Back to Topics"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};ZA();class Ki extends W8{constructor(){super(Sf,{title:"Topic Detail",mappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"content",label:"Content",type:"string"},{key:"keywords",label:"Keywords",type:"array",itemType:"string"},{key:"created",label:"Created",type:"string"},{key:"updated",label:"Updated",type:"string"}]})}}var Fx0=E1({name:"topics:topic-detail",description:"Detailed view of a single topic",schema:Sf,dataSourceId:"topics:entities",requiredPermission:"public",formatter:new Ki,layout:{component:ZJA}});w0();ZA();class FJA extends i9{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 tw;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:$G(Q.content,200),keywords:Q.keywords,created:A.created,updated:A.updated}}buildListResult(A,Q,B){return{topics:A,totalCount:A.length}}async fetch(A,Q,B){let{query:$}=this.parseQuery(A);if($.id){let D=await B.entityService.getEntity(this.config.entityType,$.id);if(!D)throw Error(`Entity not found: ${$.id}`);let Y=this.adapter.parseTopicBody(D.content);return Q.parse({id:D.id,title:Y.title,content:Y.content,keywords:Y.keywords,created:D.created,updated:D.updated})}return super.fetch(A,Q,B)}}d4();function qx0(){let A=new tw;return async(Q)=>{if(!Q.hasEntityType("topic"))return{topics:[]};return{topics:(await Q.listEntities("topic")).map((w)=>{let D=A.parseTopicBody(w.content);return{topic:w.id,title:D.title,keywords:D.keywords}})}}}var zx0={name:"@brains/topics",private:!0,version:"0.2.0-alpha.32",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 R3Q=new tw;function P3Q(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 Vx0 extends z2{entityType="topic";schema=Qi;adapter=R3Q;autoExtractionEnabled=!1;initialDerivationDone=!1;constructor(A={}){super("topics",zx0,A,Ax0)}getEntityTypeConfig(){return{weight:0.5}}getTemplates(){return{extraction:Jx0,"merge-synthesis":Wx0,"topic-list":Zx0,"topic-detail":Fx0}}getDataSources(){return[new FJA(this.logger.child("TopicsDataSource"))]}async onRegister(A){let Q=new Xi(A,this.logger);A.jobs.registerHandler("process-single",Q);let B=new JJA(A,this.logger);if(A.jobs.registerHandler("extract",B),A.insights.register("topic-distribution",qx0()),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((w)=>{let D=this.adapter.parseTopicBody(w.content),Y=P3Q(D.content);return{id:w.id,name:D.title||w.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 $=async(w)=>{if(!this.autoExtractionEnabled)return{success:!0};let{entityType:D,entity:Y}=w.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",$),A.messaging.subscribe("entity:updated",$)}}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 Yi(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 Q4(Q.entityService,this.logger),$=await B.listTopics();for(let D of $)await B.deleteTopic(D.id);if(A.length===0)return{deleted:$.length,created:0,skipped:0,batches:0};let w=await Yi(A,Q,this.logger);return{deleted:$.length,...w}}async getEntitiesToExtract(A){let Q=this.getExtractableEntityTypes(A),B=[];for(let $ of Q){let w=await A.entityService.listEntities($);for(let D of w){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 xf(A,this.logger),B=F.object({entityType:F.string(),content:F.string(),metadata:F.record(F.unknown()).optional()}),$=(N,M="")=>({id:`eval${M}-${Date.now()}`,entityType:N.entityType,content:N.content,contentHash:nB(N.content),metadata:N.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}),w=async(N,M,L="")=>{let _=$(N,L);return Q.extractFromEntity(_,M)},D=B.extend({minRelevanceScore:F.number().optional()});A.eval.registerHandler("extractFromEntity",async(N)=>{let M=D.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore;return w(M,L)});let Y=F.object({contentA:B,contentB:B,minRelevanceScore:F.number().optional()});A.eval.registerHandler("checkMergeSimilarity",async(N)=>{let M=Y.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore,[_,T]=await Promise.all([w(M.contentA,L,"-a"),w(M.contentB,L,"-b")]),P=_.map((g)=>g.title.toLowerCase()),r=T.map((g)=>g.title.toLowerCase()),n=P.filter((g)=>r.includes(g));return{topicsA:_.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),topicsB:T.map((g)=>({title:g.title,relevanceScore:g.relevanceScore})),matchingTitles:n,wouldMerge:n.length>0}});let X=F.object({title:F.string(),content:F.string(),keywords:F.array(F.string())}),I=F.object({existingTopics:F.array(X),incomingTopic:X,threshold:F.number().optional()});A.eval.registerHandler("detectMergeCandidate",async(N)=>{let M=I.parse(N),L=M.threshold??this.config.mergeSimilarityThreshold,_=new Q4(A.entityService,this.logger);for(let P of M.existingTopics)await _.createTopic(P);let T=await _.findMergeCandidate({title:M.incomingTopic.title,keywords:M.incomingTopic.keywords},L);return{found:T!==null,candidateTitle:T?.title,candidateScore:T?.score}});let K=F.object({existingAliases:F.array(F.string()).optional(),canonicalTitle:F.string(),candidateAliases:F.array(F.string())});A.eval.registerHandler("mergeAliases",async(N)=>{let M=K.parse(N);return{aliases:new Q4(A.entityService,this.logger).mergeAliases(M.existingAliases,M.canonicalTitle,M.candidateAliases)}});let G=F.object({existingTopics:F.array(X.extend({aliases:F.array(F.string()).optional()})).default([]),incomingTopic:X.extend({relevanceScore:F.number().min(0).max(1).optional()}),threshold:F.number().optional()});A.eval.registerHandler("processTopicWithAutoMerge",async(N)=>{let M=G.parse(N),L=new Q4(A.entityService,this.logger);for(let n of M.existingTopics)await L.createTopic({title:n.title,content:n.content,keywords:n.keywords,metadata:{aliases:n.aliases??[]}});let _=new Xi(A,this.logger),T=n5.from(async()=>{});if(!T)throw Error("Failed to create progress reporter");let P=await _.process({topic:{title:M.incomingTopic.title,content:M.incomingTopic.content,keywords:M.incomingTopic.keywords,relevanceScore:M.incomingTopic.relevanceScore??0.9},sourceEntityId:"eval-source",sourceEntityType:"post",autoMerge:!0,mergeSimilarityThreshold:M.threshold??this.config.mergeSimilarityThreshold},`eval-job-${Date.now()}`,T),r=await A.entityService.listEntities("topic");return{...P,topicCount:r.length,topics:r.map((n)=>{let g=this.adapter.parseTopicBody(n.content);return{id:n.id,title:g.title,content:g.content,keywords:g.keywords,metadata:n.metadata}})}});let W=F.object({entities:F.array(B).min(1),minRelevanceScore:F.number().optional()}),Z=F.object({existingTopics:F.array(X).optional(),entities:F.array(B)});A.eval.registerHandler("rebuildTopics",async(N)=>{let M=Z.parse(N),L=new Q4(A.entityService,this.logger);for(let r of M.existingTopics??[])await L.createTopic(r);let _=M.entities.map((r,n)=>$(r,`-rebuild-${n}`)),T=await this.replaceAllTopics(_,A),P=await A.entityService.listEntities("topic");return{...T,topicCount:P.length,topics:P.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,keywords:n.keywords,metadata:r.metadata}})}}),A.eval.registerHandler("extractSequentially",async(N)=>{let M=W.parse(N),L=M.minRelevanceScore??this.config.minRelevanceScore,_=new Q4(A.entityService,this.logger),T=[];for(let[r,n]of M.entities.entries()){let g=$(n,`-sequential-${r}`),x=await Q.extractFromEntity(g,L);for(let S of x)await _.createTopic({title:S.title,content:S.content,keywords:S.keywords});T.push({extractedTitles:x.map((S)=>S.title)})}let P=await A.entityService.listEntities("topic");return{totalTopics:P.length,perEntity:T,topics:P.map((r)=>{let n=this.adapter.parseTopicBody(r.content);return{id:r.id,title:n.title,content:n.content,keywords:n.keywords}})}});let q=F.object({entities:F.array(B)});A.eval.registerHandler("batchExtract",async(N)=>{let L=q.parse(N).entities.map((P,r)=>$(P,`-batch-${r}`)),_=await Yi(L,A,this.logger),T=await A.entityService.listEntities("topic");return{..._,topics:T.map((P)=>{let r=this.adapter.parseTopicBody(P.content);return{id:P.id,title:r.title,content:r.content,keywords:r.keywords}})}})}}function Hi(A){return new Vx0(A)}w0();ZA();w0();var Nx0=F.enum(["linkedin"]),Lx0=F.enum(["draft","queued","published","failed"]),Ex0=F.enum(["post","deck"]),B4=F.object({title:F.string().describe("Short descriptive title (3-6 words) for file naming"),platform:Nx0.describe("Target platform"),status:Lx0,coverImageId:F.string().optional().describe("Image entity ID for post image"),publishedAt:F.string().datetime().optional(),platformPostId:F.string().optional().describe("ID from platform after publishing"),sourceEntityId:F.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Ex0.optional().describe("Source entity type (post, deck)")}),Mx0=B4.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:F.string().describe("URL-friendly identifier: {platform}-{title}")}),gE=FQ.extend({entityType:F.literal("social-post"),metadata:Mx0}),Ui=gE.extend({frontmatter:B4,body:F.string()}),Gi=Ui.extend({url:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional(),typeLabel:F.string().optional(),coverImageUrl:F.string().optional(),coverImageWidth:F.number().optional(),coverImageHeight:F.number().optional()});w0();ZA();class qJA extends _Q{constructor(){super({entityType:"social-post",schema:gE,frontmatterSchema:B4,supportsCoverImage:!0})}toMarkdown(A){let Q="",B={};try{B=this.parseFrontMatter(A.content,B4),Q=this.extractBody(A.content)}catch{Q=A.content}let $={...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,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,B4),B=`${Q.platform}-${a1(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,B4)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}}var r7=new qJA;w0();w0();ZA();var _3Q=UG.extend({platform:F.enum(["linkedin"]).optional(),status:F.enum(["draft","queued","published","failed"]).optional(),sortByQueue:F.boolean().optional(),nextInQueue:F.boolean().optional()}),k3Q=GG.extend({query:_3Q.optional()});function Cx0(A){let Q=JQ(A.content,B4);return Ui.parse({...A,frontmatter:Q.metadata,body:Q.content})}class Ji extends i9{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=k3Q.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return Cx0(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:$}=this.parseQuery(A),w=B.entityService;if($.nextInQueue)return this.fetchNextInQueue(Q,w);if($.id){let{item:G}=await this.fetchDetail($.id,w);return Q.parse(this.buildDetailResult(G,null))}let D={};if($.platform)D.platform=$.platform;if($.status)D.status=$.status;let Y=Object.keys(D).length>0,X=$.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:I,pagination:K}=await this.fetchList($,w,{...Y&&{filter:{metadata:D}},sortFields:X});return Q.parse(this.buildListResult(I,K,$))}async fetchNextInQueue(A,Q){let $=(await Q.listEntities(this.config.entityType,{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}))[0],w=$?Cx0($):null;return A.parse({post:w})}}ZA();var Ox0=F.object({accessToken:F.string().optional(),refreshToken:F.string().optional(),organizationId:F.string().optional()}),zJA=F.object({linkedin:Ox0.optional(),publishInterval:F.number().default(3600000),enabled:F.boolean().default(!0),defaultPrompt:F.string().default("Create an engaging social media post that drives engagement"),maxRetries:F.number().default(3),autoGenerateOnBlogPublish:F.boolean().default(!1)});w0();ZA();NJA();import{jsxDEV as h6,Fragment as T3Q}from"preact/jsx-dev-runtime";function f3Q(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function b3Q(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var Zi=({posts:A,pageTitle:Q,pagination:B,baseUrl:$="/social-posts"})=>{let w=Q??"Social Posts",D=B?.totalItems??A.length,Y=`Browse all ${D} social ${D===1?"post":"posts"}`;return h6(T3Q,{children:[h6(iQ,{title:w,description:Y},void 0,!1,void 0,this),h6("div",{className:"social-post-list bg-theme",children:h6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[h6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:w},void 0,!1,void 0,this),A.length===0?h6("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):h6("ul",{className:"space-y-6",children:A.map((X)=>h6("li",{children:h6(V2,{href:X.url,variant:"horizontal",children:h6("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&h6("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),h6("div",{className:"flex-1 min-w-0",children:[h6("div",{className:"flex items-start justify-between gap-4 mb-2",children:[h6("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),h6("time",{className:"text-sm text-theme-muted shrink-0",children:b3Q(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h6("div",{className:"flex items-center gap-2 mb-3",children:[h6(l7,{status:X.frontmatter.status},void 0,!1,void 0,this),h6("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),h6("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h6("p",{className:"text-theme leading-relaxed",children:f3Q(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&h6(MY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as g6,Fragment as x3Q}from"preact/jsx-dev-runtime";function jx0(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var Fi=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,B=A.body.slice(0,160),$=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return g6(x3Q,{children:[g6(iQ,{title:Q,description:B},void 0,!1,void 0,this),g6("section",{className:"social-post-detail",children:g6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:g6("div",{className:"max-w-3xl mx-auto",children:[g6(oD,{items:$},void 0,!1,void 0,this),g6("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),g6("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[g6(l7,{status:A.frontmatter.status},void 0,!1,void 0,this),g6("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),g6("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&&g6(NH,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),g6(V2,{className:"p-8 mb-8",children:g6("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),g6("div",{className:"space-y-4 text-sm text-theme-muted",children:[g6("div",{children:[g6("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",jx0(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&g6("div",{children:[g6("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",jx0(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&g6("div",{children:g6("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 hf(A){return`social-media:${A}`}var LJA=F.object({prompt:F.string().optional(),platform:F.enum(["linkedin"]).optional(),sourceEntityType:F.enum(["post","deck"]).optional(),sourceEntityId:F.string().optional(),title:F.string().optional().describe("Required when content is provided directly"),content:F.string().optional(),addToQueue:F.boolean().optional(),generateImage:F.boolean().optional().describe("Auto-generate cover image for post")}),v3Q=M7.extend({slug:F.string().optional()});class o3 extends a5{constructor(A,Q){super(A,Q,{schema:LJA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let B=A.platform??"linkedin",$=A.addToQueue??!1,{prompt:w,sourceEntityType:D,sourceEntityId:Y}=A,{content:X,title:I}=A;if(X&&I)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!I){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:X,templateName:hf(B)});I=L.title,X=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 T=F.object({slug:F.string()}).safeParse(L.metadata),P=T.success?T.data.slug:Y,r=await this.context.ai.generate({prompt:`Create an engaging ${B} post to promote this ${D}:
2714
2714
 
2715
2715
  Source: ${D}/${P}
2716
2716
 
2717
2717
  ${L.content}`,templateName:hf(B)});I=r.title,X=r.content,await this.reportProgress(Q,{progress:50,message:"Social post generated from source"})}else if(w){await this.reportProgress(Q,{progress:10,message:"Generating social post with AI"});let L=await this.context.ai.generate({prompt:w,templateName:hf(B)});I=L.title,X=L.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!X||!I)this.failEarly("Content or title was not generated");let G={title:I,platform:B,status:$?"queued":"draft",...Y&&{sourceEntityId:Y},...D&&{sourceEntityType:D}},W=r7.createPostContent(G,X),q=r7.fromMarkdown(W).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let N=await xK({entityType:"social-post",title:I,deriveId:(L)=>`${B}-${a1(L)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),M=W;if(N!==I){q.title=N,q.slug=`${B}-${a1(N)}`;let L={...G,title:N};M=r7.createPostContent(L,X)}return{id:q.slug,content:M,metadata:q,title:N,resultExtras:{slug:q.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,$){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: ${w}`,title:`${w} 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 EJA{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 $=await this.getAuthor(),w=null;if(B)w=await this.uploadImage($,B);let D={shareCommentary:{text:A},shareMediaCategory:w?"IMAGE":"NONE",...w&&{media:[{status:"READY",media:w}]}},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:$,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":D},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!Y.ok){let K=await Y.text();throw this.logger.error("LinkedIn API error",{status:Y.status,error:K}),Error(`LinkedIn API error: ${Y.status} - ${K}`)}let X=Y.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:X,hasImage:!!w});let I={id:X};if(X)I.url=`https://www.linkedin.com/feed/update/${X}`;return I}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 X=await B.text();return this.logger.warn("LinkedIn image upload registration failed",{status:B.status,error:X}),null}let $=await B.json(),w=$.value.uploadMechanism["com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"].uploadUrl,D=$.value.asset,Y=await fetch(w,{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 $=await B.json();return this.cachedUserId=`urn:li:person:${$.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 MJA(A,Q){return new EJA(A,Q)}w0();ZA();o8();NJA();var S3Q=F.object({posts:F.array(Gi),totalCount:F.number().optional(),pagination:j7.nullable(),baseUrl:F.string().optional()}),h3Q=F.object({post:Gi});function Rx0(){return{linkedin:Wi,"social-post-list":E1({name:"social-post-list",description:"Social post list page template",schema:S3Q,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:Zi}}),"social-post-detail":E1({name:"social-post-detail",description:"Individual social post template",schema:h3Q,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:Fi}})}}ZA();var g3Q=F.object({prompt:F.string().optional(),content:F.string().optional(),platform:F.enum(["linkedin"]).default("linkedin")}),y3Q=F.object({prompt:F.string().optional(),content:F.string().optional(),title:F.string().optional(),platform:F.enum(["linkedin"]).optional()});function Px0(A){A.eval.registerHandler("generation",async(Q)=>{let B=g3Q.parse(Q),$=B.content?`Create an engaging LinkedIn post to share this content:
2718
2718
 
2719
- ${B.content}`:B.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:$,templateName:`social-media:${B.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let B=y3Q.parse(Q),$=[],w=n5.from(async(K)=>{let G={progress:K.progress};if(K.message!==void 0)G.message=K.message;$.push(G)});if(!w)throw Error("Failed to create progress reporter");let Y=await new o3(A.logger,A).process(B,`eval-${Date.now()}`,w),X=!1,I;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity("social-post",Y.entityId);X=!!K,I=K?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:I,progressSteps:$}})}ZA();w0();class gf{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 $=await this.entityService.getEntity("social-post",B);if(!$){await this.reportFailure(Q,B,`Post not found: ${B}`);return}if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:B});return}let w=$.metadata.platform,D=this.providers.get(w);if(!D){await this.reportFailure(Q,B,`No provider configured for platform: ${w}`);return}let Y=JQ($.content,B4),X;if(Y.metadata.coverImageId)X=await this.fetchImageData(Y.metadata.coverImageId);try{let I=await D.publish(Y.content,$.metadata,X),K=new Date().toISOString(),G=I.id||void 0,W={...Y.metadata,status:"published",publishedAt:K,...G&&{platformPostId:G}},Z=r7.createPostContent(W,Y.content);await this.entityService.updateEntity({...$,content:Z,metadata:{...$.metadata,status:"published",publishedAt:K,platformPostId:G}}),await this.reportSuccess(Q,B,I.id),this.logger.info(`Post published successfully: ${B}`,{platform:w,platformPostId:G})}catch(I){let K=I instanceof Error?I.message:String(I),G={...Y.metadata,status:"failed"},W=r7.createPostContent(G,Y.content);await this.entityService.updateEntity({...$,content:W,metadata:{...$.metadata,status:"failed"}}),await this.reportFailure(Q,B,K),this.logger.error(`Post publish failed: ${B}`,{platform:w,error:K})}}catch($){let w=L0($);this.logger.error("Unexpected error in publish handler",{entityId:B,error:w}),await this.reportFailure(Q,B,w)}}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 $=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!$?.[1]||!$[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let w=$[1],D=$[2];return{data:Buffer.from(D,"base64"),mimeType:w}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function _x0(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 $=Q.values().next().value;return await A.messaging.send("publish:register",{entityType:"social-post",provider:$}),B.info("Registered social-post with publish-pipeline"),{success:!0}})}function kx0(A,Q,B){let $=new gf({sendMessage:A.messaging.send,logger:B.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q});A.messaging.subscribe("publish:execute",async(w)=>{return await $.handle(w.payload),{success:!0}}),B.debug("Subscribed to publish:execute messages")}ZA();function fx0(A,Q){A.messaging.subscribe("entity:updated",async(B)=>{let{entityType:$,entityId:w,entity:D}=B.payload;if($!=="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:w}},limit:1})).length>0)return Q.debug(`Social post already exists for ${w}, skipping auto-generate`),{success:!0};return await A.messaging.send("social:auto-generate",{sourceEntityType:$,sourceEntityId:w,platform:"linkedin"}),Q.info(`Auto-generate social post triggered for queued post ${w}`),{success:!0}}catch(X){let I=L0(X);return Q.error(`Failed to trigger auto-generate for ${w}:`,{error:I}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function bx0(A,Q){A.messaging.subscribe("social:auto-generate",async(B)=>{let{sourceEntityType:$,sourceEntityId:w,platform:D}=B.payload;try{let Y=await A.jobs.enqueue(`${r7.entityType}:generation`,{sourceEntityType:$,sourceEntityId:w,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 X=L0(Y);return Q.error(`Failed to enqueue social post generation for ${w}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Tx0(A,Q){A.messaging.subscribe("generate:execute",async(B)=>{let{entityType:$}=B.payload;if($!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let w=await A.entityService.listEntities("post",{filter:{metadata:{status:"published"}},limit:5});if(w.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 X of w)if((await A.entityService.listEntities("social-post",{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1})).length===0){D=X;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(`${r7.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(w){let D=L0(w);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 xx0={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.31",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 CJA extends z2{entityType=r7.entityType;schema=gE;adapter=r7;providers=new Map;constructor(A){super("social-media",xx0,A,zJA)}createGenerationHandler(A){return new o3(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Rx0()}getDataSources(){return[new Ji(this.logger.child("SocialPostDataSource"))]}async onRegister(A){if(this.initializeProviders(),_x0(A,this.providers,this.logger),kx0(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)fx0(A,this.logger),bx0(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Tx0(A,this.logger),Px0(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=MJA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function yf(A){return new CJA(A)}ZA();var u3Q=F.enum(["draft","queued","published","failed"]),sBB=F.object({status:u3Q.default("draft"),queueOrder:F.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:F.string().datetime().optional()});class OJA{name="internal";async publish(A,Q){return{id:"internal"}}}var y6={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"},jI={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"};ZA();var c3Q=F.object({skipIfDraftExists:F.boolean().optional(),minSourceEntities:F.number().optional(),maxUnpublishedDrafts:F.number().optional(),sourceEntityType:F.string().optional()}),vx0=F.object({entitySchedules:F.record(F.string(),F.string()).optional(),generationSchedules:F.record(F.string(),F.string()).optional(),generationConditions:F.record(F.string(),c3Q).optional(),maxRetries:F.number().optional().default(3),retryBaseDelayMs:F.number().optional().default(5000)});class RI{static instance=null;queues=new Map;static getInstance(){return RI.instance??=new RI,RI.instance}static resetInstance(){RI.instance=null}static createFresh(){return new RI}constructor(){}async add(A,Q){let B=this.getOrCreateQueue(A),$=B.find((Y)=>Y.entityId===Q);if($)return{position:$.position};let w=B.length+1,D={entityId:Q,entityType:A,position:w,queuedAt:new Date().toISOString()};return B.push(D),{position:w}}async remove(A,Q){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((w)=>w.entityId===Q);if($===-1)return;B.splice($,1),this.recalculatePositions(B)}async reorder(A,Q,B){let $=this.queues.get(A);if(!$)return;let w=$.findIndex((X)=>X.entityId===Q);if(w===-1)return;let[D]=$.splice(w,1);if(!D)return;let Y=Math.max(0,Math.min(B-1,$.length));$.splice(Y,0,D),this.recalculatePositions($)}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 PI{static instance=null;providers=new Map;defaultProvider=new OJA;static getInstance(){return PI.instance??=new PI,PI.instance}static resetInstance(){PI.instance=null}static createFresh(){return new PI}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())}}ZA();ZA();async function Sx0(A,Q){let B={entityType:A.entityType,entityId:A.entityId};if(Q.messageBus)await Q.messageBus.send(y6.EXECUTE,B,"publish-service");Q.onExecute?.(B)}async function hx0(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 $=await Q.entityService.getEntity(A.entityType,A.entityId);if(!$){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:`Entity not found: ${A.entityType}/${A.entityId}`,retryCount:0,willRetry:!1});return}try{let w=await B.publish($.content,$.metadata);Q.retryTracker.clearRetries(A.entityId),Q.onPublish?.({entityType:A.entityType,entityId:A.entityId,result:w})}catch(w){let D=L0(w);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 gx0(A,Q,B,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send(y6.COMPLETED,{entityType:A,entityId:Q,result:B},"publish-service");$.onPublish?.({entityType:A,entityId:Q,result:B})}function yx0(A,Q,B,$){$.retryTracker.recordFailure(Q,B);let w=$.retryTracker.getRetryInfo(Q),D={entityType:A,entityId:Q,error:B,retryCount:w?.retryCount??1,willRetry:w?.willRetry??!1};if($.messageBus)$.messageBus.send(y6.FAILED,D,"publish-service");$.onFailed?.(D)}async function mx0(A,Q){let B=Q.generationConditions[A];if(B&&Q.onCheckGenerationConditions){let w=await Q.onCheckGenerationConditions(A,B);if(!w.shouldGenerate){if(Q.messageBus)Q.messageBus.send(jI.SKIPPED,{entityType:A,reason:w.reason??"Conditions not met"},"content-pipeline");return}}let $={entityType:A};if(Q.messageBus)await Q.messageBus.send(jI.EXECUTE,$,"content-pipeline");Q.onGenerate?.($)}function ux0(A,Q,B){if(B)B.send(jI.COMPLETED,{entityType:A,entityId:Q},"content-pipeline")}function cx0(A,Q,B){if(B)B.send(jI.FAILED,{entityType:A,error:Q},"content-pipeline")}var l3Q=1000;class yY{static instance=null;config;publishJobs=new Map;generationJobs=new Map;immediateIntervalJob=null;running=!1;static getInstance(A){return yY.instance??=new yY(A),yY.instance}static resetInstance(){if(yY.instance)yY.instance.stop();yY.instance=null}static createFresh(A){return new yY(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(l3Q,()=>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 Sx0(A,this.publishDeps);else await hx0(A,this.publishDeps)}completePublish(A,Q,B){gx0(A,Q,B,this.publishDeps)}failPublish(A,Q,B){yx0(A,Q,B,this.publishDeps)}async publishDirect(A,Q,B,$){return this.config.providerRegistry.get(A).publish(B,$)}async handleTriggerGeneration(A){if(!this.running)return;try{await mx0(A,this.generationDeps)}catch(Q){this.config.logger.error(`Generation trigger error for ${A}:`,Q)}}completeGeneration(A,Q){ux0(A,Q,this.config.messageBus)}failGeneration(A,Q){cx0(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($){throw Error(`Invalid ${B} cron expression for ${A}: "${Q}" - ${L0($)}`)}}}var lx0={maxRetries:3,baseDelayMs:5000};class _I{static instance=null;retries=new Map;config;static getInstance(A){return _I.instance??=new _I(A??lx0),_I.instance}static resetInstance(){_I.instance=null}static createFresh(A){return new _I(A??lx0)}constructor(A){this.config=A}recordFailure(A,Q){let $=(this.retries.get(A)?.retryCount??0)+1,w=this.config.baseDelayMs*Math.pow(2,$-1),D=Date.now()+w;this.retries.set(A,{entityId:A,retryCount:$,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 F$(A,Q,B,$,w,D,Y,X){return F$.fromTZ(F$.tp(A,Q,B,$,w,D,Y),X)}F$.fromTZISO=(A,Q,B)=>F$.fromTZ(p3Q(A,Q),B);F$.fromTZ=function(A,Q){let B=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),$=jJA(A.tz,B),w=new Date(B.getTime()-$),D=jJA(A.tz,w);if(D-$===0)return w;{let Y=new Date(B.getTime()-D),X=jJA(A.tz,Y);if(X-D===0)return Y;if(!Q&&X-D>0)return Y;if(Q)throw Error("Invalid date passed to fromTZ()");return w}};F$.toTZ=function(A,Q){let B=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),$=new Date(B);return{y:$.getFullYear(),m:$.getMonth()+1,d:$.getDate(),h:$.getHours(),i:$.getMinutes(),s:$.getSeconds(),tz:Q}};F$.tp=(A,Q,B,$,w,D,Y)=>({y:A,m:Q,d:B,h:$,i:w,s:D,tz:Y});function jJA(A,Q=new Date){let B=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],$=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${$} GMT`)-Date.parse(`${$} ${B}`)}function p3Q(A,Q){let B=new Date(Date.parse(A));if(isNaN(B))throw Error("minitz: Invalid ISO8601 passed to parser.");let $=A.substring(9);return A.includes("Z")||$.includes("-")||$.includes("+")?F$.tp(B.getUTCFullYear(),B.getUTCMonth()+1,B.getUTCDate(),B.getUTCHours(),B.getUTCMinutes(),B.getUTCSeconds(),"Etc/UTC"):F$.tp(B.getFullYear(),B.getMonth()+1,B.getDate(),B.getHours(),B.getMinutes(),B.getSeconds(),Q)}F$.minitz=F$;var RJA=32,uf=31|RJA,rx0=[1,2,4,8,16],px0=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 $4(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,uf),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,B,$){let w=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 w.fill($);let Y=Q.split(",");if(Y.length>1)for(let X=0;X<Y.length;X++)this.partToArray(A,Y[X],B,$);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,B,$):Q.indexOf("-")!==-1?this.handleRange(Q,A,B,$):Q.indexOf("/")!==-1?this.handleStepping(Q,A,B,$):Q!==""&&this.handleNumber(Q,A,B,$)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===5?/[^/*0-9,\-#L]+/:/[^/*0-9,-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,B,$){let w=this.extractNth(A,Q),D=parseInt(w[0],10)+B;if(isNaN(D))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,D,w[1]||$)}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,$){let w=this.extractNth(A,Q),D=w[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(D===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,I]=D,K=parseInt(Y,10)+B,G=parseInt(X,10)+B,W=parseInt(I,10);if(isNaN(K))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(G))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(W))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(W===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(W>this[Q].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[Q].length+")");if(K>G)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let Z=K;Z<=G;Z+=W)this.setPart(Q,Z,w[1]||$)}extractNth(A,Q){let B=A,$;if(B.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");$=B.split("#")[1],B=B.split("#")[0]}return[B,$]}handleRange(A,Q,B,$){let w=this.extractNth(A,Q),D=w[0].split("-");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(D[0],10)+B,X=parseInt(D[1],10)+B;if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(X))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(Y>X)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let I=Y;I<=X;I++)this.setPart(Q,I,w[1]||$)}handleStepping(A,Q,B,$){let w=this.extractNth(A,Q),D=w[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 X=parseInt(D[1],10);if(isNaN(X))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(X===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(X>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let I=Y;I<this[Q].length;I+=X)this.setPart(Q,I,w[1]||$)}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]|RJA;else if(Q===uf)this.dayOfWeek[A]=uf;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|rx0[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},dx0=[31,28,31,30,31,30,31,31,30,31,30,31],lH=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],$4=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,$)).getUTCDay(),Y=0;for(let X=1;X<=$;X++)new Date(Date.UTC(Q,B,X)).getUTCDay()===D&&Y++;if(w&uf&&rx0[Y-1]&w)return!0;if(w&RJA){let X=new Date(Date.UTC(Q,B+1,0)).getUTCDate();for(let I=$+1;I<=X;I++)if(new Date(Date.UTC(Q,B,I)).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=F$.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>dx0[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=F$.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(F$.fromTZISO(Q,this.tz))}findNext(Q,B,$,w){let D=this[B],Y;$.lastDayOfMonth&&(this.month!==1?Y=dx0[this.month]:Y=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let X=!$.starDOW&&B=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let I=this[B]+w;I<$[B].length;I++){let K=$[B][I];if(B==="day"&&$.lastDayOfMonth&&I-w==Y&&(K=1),B==="day"&&!$.starDOW){let G=$.dayOfWeek[(X+(I-w-1))%7];if(G&&G&uf)G=this.isNthWeekdayOfMonth(this.year,this.month,I-w,G)?1:0;else if(G)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${G}`);Q.legacyMode&&!$.starDOM?K=K||G:K=K&&G}if(K)return this[B]=I-w,D!==this[B]?2:1}return 3}recurse(Q,B,$){let w=this.findNext(B,lH[$][0],Q,lH[$][2]);if(w>1){let D=$+1;for(;D<lH.length;)this[lH[D][0]]=-lH[D][2],D++;if(w===3)return this[lH[$][1]]++,this[lH[$][0]]=-lH[$][2],this.apply(),this.recurse(Q,B,0);if(this.apply())return this.recurse(Q,B,$-1)}return $+=1,$>=lH.length?this:this.year>=3000?null:this.recurse(Q,B,$)}increment(Q,B,$){return this.second+=B.interval!==void 0&&B.interval>1&&$?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)):F$.fromTZ(F$.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function d3Q(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 $4(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new $4(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 mf(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function i3Q(A){return mf(A)}function r3Q(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var ix0=30000,qi=[],PJA=class{name;options;_states;fn;constructor(A,Q,B){let $,w;if(mf(Q))w=Q;else if(typeof Q=="object")$=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(mf(B))w=B;else if(typeof B=="object")$=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=$?.name,this.options=d3Q($),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:$?$.maxRuns:void 0,paused:$?$.paused:!1,pattern:new px0("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new $4(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new px0(A,this.options.timezone),this.name){if(qi.find((D)=>D.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");qi.push(this)}return w!==void 0&&i3Q(w)&&(this.fn=w,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=[],$=Q||this._states.currentRun||void 0;for(;A--&&($=this.nextRun($));)B.push($);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,$=!this._states.kill;return Q&&B&&$&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof $4||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new $4(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=qi.indexOf(this);A>=0&&qi.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>ix0&&(Q=ix0),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(B),Q),this._states.currentTimeout&&this.options.unref&&r3Q(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new $4(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){mf(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new $4(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(),$=this._states.blocking&&this.options.protect;B&&!$?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):B&&$&&mf(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 $4(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let $=this._states.once||new $4(A,this.options.timezone||this.options.utcOffset);return!B&&$!==this._states.once&&($=$.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||$===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&$.getTime()>=this.options.stopAt.getTime()?null:$}_calculatePreviousRun(A,Q){let B=new $4(void 0,this.options.timezone||this.options.utcOffset),$=A;if(this.options.startAt.getTime()<=B.getTime()){$=this.options.startAt;let w=$.getTime()+this.options.interval*1000;for(;w<=B.getTime();)$=new $4($,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),w=$.getTime()+this.options.interval*1000;Q=!0}return $===null&&($=void 0),[$,Q]}};class zi{scheduleCron(A,Q){let B=new PJA(A,()=>{Q()});return{stop:()=>B.stop()}}scheduleInterval(A,Q){let B=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(B)}}validateCron(A){new PJA(A).stop()}}w0();ZA();var _JA=F.object({action:F.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:F.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:F.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:F.number().optional().describe("New position for reorder action (1-based)")}),kJA=F.object({position:F.number(),entityType:F.string(),entityId:F.string(),queuedAt:F.string()}),n3Q=F.object({success:F.literal(!0),message:F.string().optional(),data:F.object({queue:F.array(kJA).optional(),entityType:F.string().optional(),entityId:F.string().optional(),position:F.number().optional()}).optional()}),o3Q=F.object({success:F.literal(!1),error:F.string(),code:F.string().optional()}),fJA=F.union([n3Q,o3Q]);function Vi(A,Q,B){return{...g2(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",_JA,async(w)=>{let{action:D,entityType:Y,entityId:X,position:I}=w;switch(D){case"list":return s3Q(B,Y);case"add":return a3Q(B,Y,X);case"remove":return t3Q(B,Y,X);case"reorder":return e3Q(B,Y,X,I);default:return{success:!1,error:`Unknown action: ${D}`}}}),outputSchema:fJA}}async function s3Q(A,Q){let B=[];if(Q)B=await A.list(Q);else{let w=A.getRegisteredTypes();for(let D of w){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((w,D)=>({position:D+1,entityType:w.entityType,entityId:w.entityId,queuedAt:w.queuedAt}))},message:`${B.length} items in queue`}}async function a3Q(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 $=await A.add(Q,B);return{success:!0,data:{entityType:Q,entityId:B,position:$.position},message:`Added to queue at position ${$.position}`}}async function t3Q(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 e3Q(A,Q,B,$){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($===void 0)return{success:!1,error:"position is required for reorder action"};if($<1)return{success:!1,error:"position must be a positive number"};return await A.reorder(Q,B,$),{success:!0,data:{entityType:Q,entityId:B,position:$},message:`Moved to position ${$}`}}w0();ZA();var bJA=F.object({entityType:F.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:F.string().optional().describe("Entity ID to publish"),slug:F.string().optional().describe("Entity slug to publish")}),AqQ=F.object({success:F.literal(!0),message:F.string().optional(),data:F.object({entityType:F.string().optional(),entityId:F.string().optional(),platformId:F.string().optional(),url:F.string().optional()}).optional()}),QqQ=F.object({success:F.literal(!1),error:F.string(),code:F.string().optional()}),TJA=F.union([AqQ,QqQ]);function Ni(A,Q,B){return{...g2(Q,"publish","Publish an entity directly to its platform. Works with any registered entity type (social-post, post, deck, etc.)",bJA,async(w)=>{let{entityType:D,id:Y,slug:X}=w;if(!Y&&!X)return{success:!1,error:"Either 'id' or 'slug' must be provided"};let I=null;if(Y)I=await A.entityService.getEntity(D,Y);else if(X)I=(await A.entityService.listEntities(D,{filter:{metadata:{slug:X}},limit:1}))[0]??null;if(!I)return{success:!1,error:`Entity not found: ${D}:${Y??X}`};if(I.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 K=B.get(D),G=I.content,W;try{let N=JQ(I.content,F.record(F.unknown()));G=N.content;let M=N.metadata.coverImageId;W=typeof M==="string"?M:void 0}catch{}let Z;if(W){let N=await A.entityService.getEntity("image",W);if(N?.content){let M=N.content.match(/^data:([^;]+);base64,(.+)$/);if(M?.[1]&&M[2])Z={data:Buffer.from(M[2],"base64"),mimeType:M[1]}}}let q=await K.publish(G,I.metadata,Z);return await A.entityService.updateEntity({...I,metadata:{...I.metadata,status:"published",publishedAt:new Date().toISOString(),platformId:q.id}}),{success:!0,data:{entityType:D,entityId:I.id,platformId:q.id,url:q.url},message:`Published ${D}:${I.id}`}}),outputSchema:TJA}}w0();ZA();function nx0(A,Q){let{logger:B}=Q;A.messaging.subscribe(y6.REGISTER,async($)=>BqQ(Q,$.payload)),A.messaging.subscribe(y6.QUEUE,async($)=>$qQ(A,Q,$.payload)),A.messaging.subscribe(y6.DIRECT,async($)=>wqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REMOVE,async($)=>DqQ(Q,$.payload)),A.messaging.subscribe(y6.REORDER,async($)=>YqQ(Q,$.payload)),A.messaging.subscribe(y6.LIST,async($)=>XqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REPORT_SUCCESS,async($)=>IqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REPORT_FAILURE,async($)=>KqQ(A,Q,$.payload)),B.debug("Subscribed to publish messages"),A.messaging.subscribe(jI.REPORT_SUCCESS,async($)=>{let{entityType:w,entityId:D}=$.payload;return Q.scheduler.completeGeneration(w,D),B.info("Generation completed",{entityType:w,entityId:D}),{success:!0}}),A.messaging.subscribe(jI.REPORT_FAILURE,async($)=>{let{entityType:w,error:D}=$.payload;return Q.scheduler.failGeneration(w,D),B.warn("Generation failed",{entityType:w,error:D}),{success:!0}}),B.debug("Subscribed to generation messages")}async function BqQ(A,Q){let{entityType:B,provider:$}=Q;try{if($)A.providerRegistry.register(B,$),A.logger.info(`Registered provider for entity type: ${B}`,{providerName:$.name});return{success:!0}}catch(w){let D=L0(w);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function $qQ(A,Q,B){let{entityType:$,entityId:w}=B;try{let D=await Q.queueManager.add($,w);return await A.messaging.send(y6.QUEUED,{entityType:$,entityId:w,position:D.position}),Q.logger.debug(`Entity queued: ${w}`,{entityType:$,position:D.position}),{success:!0}}catch(D){let Y=L0(D);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function wqQ(A,Q,B){let{entityType:$,entityId:w}=B;return await A.messaging.send(y6.EXECUTE,{entityType:$,entityId:w}),Q.logger.debug(`Direct publish requested: ${w}`,{entityType:$}),{success:!0}}async function DqQ(A,Q){let{entityType:B,entityId:$}=Q;try{return await A.queueManager.remove(B,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:B}),{success:!0}}catch(w){let D=L0(w);return A.logger.error(`Failed to remove entity: ${D}`),{success:!1}}}async function YqQ(A,Q){let{entityType:B,entityId:$,position:w}=Q;try{return await A.queueManager.reorder(B,$,w),A.logger.debug(`Entity reordered: ${$}`,{entityType:B,newPosition:w}),{success:!0}}catch(D){let Y=L0(D);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function XqQ(A,Q,B){let{entityType:$}=B;try{let w=await Q.queueManager.list($);return await A.messaging.send(y6.LIST_RESPONSE,{entityType:$,queue:w.map((D)=>({entityId:D.entityId,position:D.position,queuedAt:D.queuedAt}))}),{success:!0}}catch(w){let D=L0(w);return Q.logger.error(`Failed to list queue: ${D}`),{success:!1}}}async function IqQ(A,Q,B){let{entityType:$,entityId:w,result:D}=B;return Q.retryTracker.clearRetries(w),await A.messaging.send(y6.COMPLETED,{entityType:$,entityId:w,result:D}),Q.logger.info(`Publish reported success: ${w}`,{entityType:$}),{success:!0}}async function KqQ(A,Q,B){let{entityType:$,entityId:w,error:D}=B;Q.retryTracker.recordFailure(w,D);let Y=Q.retryTracker.getRetryInfo(w);return await A.messaging.send(y6.FAILED,{entityType:$,entityId:w,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1}),Q.logger.info(`Publish reported failure: ${w}`,{entityType:$,error:D,retryCount:Y?.retryCount,willRetry:Y?.willRetry}),{success:!0}}ZA();async function ox0(A,Q,B,$){try{if($.skipIfDraftExists!==!1){if((await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:1})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if($.maxUnpublishedDrafts!==void 0){let w=await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:$.maxUnpublishedDrafts+1});if(w.length>=$.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${w.length}/${$.maxUnpublishedDrafts})`}}if($.minSourceEntities!==void 0&&$.sourceEntityType){let w=await A.listEntities($.sourceEntityType,{publishedOnly:!0,limit:$.minSourceEntities});if(w.length<$.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${w.length}/${$.minSourceEntities} ${$.sourceEntityType})`}}return{shouldGenerate:!0}}catch(w){return Q.error("Failed to check generation conditions",{entityType:B,error:L0(w)}),{shouldGenerate:!1,reason:`Condition check failed: ${L0(w)}`}}}function sx0(A){let{context:Q,config:B,queueManager:$,providerRegistry:w,retryTracker:D,logger:Y}=A,X={send:async(I,K)=>{return Q.messaging.send(I,K)},subscribe:()=>()=>{}};return yY.createFresh({queueManager:$,providerRegistry:w,retryTracker:D,logger:Y,backend:new zi,...B.entitySchedules&&{entitySchedules:B.entitySchedules},...B.generationSchedules&&{generationSchedules:B.generationSchedules},...B.generationConditions&&{generationConditions:B.generationConditions},messageBus:X,entityService:Q.entityService,onPublish:(I)=>{Q.messaging.send(y6.COMPLETED,{entityType:I.entityType,entityId:I.entityId,result:I.result})},onFailed:(I)=>{Q.messaging.send(y6.FAILED,{entityType:I.entityType,entityId:I.entityId,error:I.error,retryCount:I.retryCount,willRetry:I.willRetry})},onCheckGenerationConditions:(I,K)=>ox0(Q.entityService,Y,I,K),onGenerate:(I)=>{Y.info(`Generation triggered for ${I.entityType}`),Q.messaging.send(jI.EXECUTE,{entityType:I.entityType})}})}async function ax0(A,Q,B){let $=A.getEntityTypes();for(let D of $){let Y=await A.listEntities(D,{filter:{metadata:{status:"queued"}}});for(let X of Y)await Q.add(X.entityType,X.id)}let w=0;for(let D of $){let Y=await Q.list(D);w+=Y.length}if(w>0)B.info(`Rebuilt queue with ${w} queued entities`)}var tx0={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.31",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 xJA extends f8{pluginContext;queueManager;providerRegistry;retryTracker;scheduler;constructor(A){super("content-pipeline",tx0,A??{},vx0)}async onRegister(A){this.pluginContext=A,this.queueManager=RI.createFresh(),this.providerRegistry=PI.createFresh(),this.retryTracker=_I.createFresh({maxRetries:this.config.maxRetries,baseDelayMs:this.config.retryBaseDelayMs}),this.scheduler=sx0({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,logger:this.logger}),nx0(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 ax0(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:15,rendererName:"PipelineWidget",dataProvider:async()=>{let Q=A.entityService.getEntityTypes(),B=[],$={draft:0,queued:0,published:0,failed:0};for(let w of Q){let D=await A.entityService.listEntities(w);for(let Y of D){let X=Y.metadata.status;if(X!=="draft"&&X!=="queued"&&X!=="published"&&X!=="failed")continue;$[X]++;let I=Y.metadata.title;B.push({id:Y.id,title:typeof I==="string"?I:Y.id,type:w,status:X})}}return{summary:$,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[Vi(this.pluginContext,this.id,this.queueManager),Ni(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(){RI.resetInstance(),PI.resetInstance(),_I.resetInstance()}}function vJA(A){return new xJA(A)}w0();ZA();var ex0=F.object({accountId:F.string().describe("Cloudflare account ID"),apiToken:F.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:F.string().describe("Cloudflare Web Analytics site tag")}),SJA=F.object({cloudflare:ex0.optional()});w0();ZA();var UqQ=F.object({date:F.string().describe("Single date in YYYY-MM-DD format").optional(),days:F.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:F.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:F.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:F.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function GqQ(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 $=[];if(!B)return $;return $.push(g2(A,"query",`Query website analytics from Cloudflare.
2719
+ ${B.content}`:B.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:$,templateName:`social-media:${B.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let B=y3Q.parse(Q),$=[],w=n5.from(async(K)=>{let G={progress:K.progress};if(K.message!==void 0)G.message=K.message;$.push(G)});if(!w)throw Error("Failed to create progress reporter");let Y=await new o3(A.logger,A).process(B,`eval-${Date.now()}`,w),X=!1,I;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity("social-post",Y.entityId);X=!!K,I=K?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:I,progressSteps:$}})}ZA();w0();class gf{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 $=await this.entityService.getEntity("social-post",B);if(!$){await this.reportFailure(Q,B,`Post not found: ${B}`);return}if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:B});return}let w=$.metadata.platform,D=this.providers.get(w);if(!D){await this.reportFailure(Q,B,`No provider configured for platform: ${w}`);return}let Y=JQ($.content,B4),X;if(Y.metadata.coverImageId)X=await this.fetchImageData(Y.metadata.coverImageId);try{let I=await D.publish(Y.content,$.metadata,X),K=new Date().toISOString(),G=I.id||void 0,W={...Y.metadata,status:"published",publishedAt:K,...G&&{platformPostId:G}},Z=r7.createPostContent(W,Y.content);await this.entityService.updateEntity({...$,content:Z,metadata:{...$.metadata,status:"published",publishedAt:K,platformPostId:G}}),await this.reportSuccess(Q,B,I.id),this.logger.info(`Post published successfully: ${B}`,{platform:w,platformPostId:G})}catch(I){let K=I instanceof Error?I.message:String(I),G={...Y.metadata,status:"failed"},W=r7.createPostContent(G,Y.content);await this.entityService.updateEntity({...$,content:W,metadata:{...$.metadata,status:"failed"}}),await this.reportFailure(Q,B,K),this.logger.error(`Post publish failed: ${B}`,{platform:w,error:K})}}catch($){let w=L0($);this.logger.error("Unexpected error in publish handler",{entityId:B,error:w}),await this.reportFailure(Q,B,w)}}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 $=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!$?.[1]||!$[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let w=$[1],D=$[2];return{data:Buffer.from(D,"base64"),mimeType:w}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function _x0(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 $=Q.values().next().value;return await A.messaging.send("publish:register",{entityType:"social-post",provider:$}),B.info("Registered social-post with publish-pipeline"),{success:!0}})}function kx0(A,Q,B){let $=new gf({sendMessage:A.messaging.send,logger:B.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q});A.messaging.subscribe("publish:execute",async(w)=>{return await $.handle(w.payload),{success:!0}}),B.debug("Subscribed to publish:execute messages")}ZA();function fx0(A,Q){A.messaging.subscribe("entity:updated",async(B)=>{let{entityType:$,entityId:w,entity:D}=B.payload;if($!=="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:w}},limit:1})).length>0)return Q.debug(`Social post already exists for ${w}, skipping auto-generate`),{success:!0};return await A.messaging.send("social:auto-generate",{sourceEntityType:$,sourceEntityId:w,platform:"linkedin"}),Q.info(`Auto-generate social post triggered for queued post ${w}`),{success:!0}}catch(X){let I=L0(X);return Q.error(`Failed to trigger auto-generate for ${w}:`,{error:I}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function bx0(A,Q){A.messaging.subscribe("social:auto-generate",async(B)=>{let{sourceEntityType:$,sourceEntityId:w,platform:D}=B.payload;try{let Y=await A.jobs.enqueue(`${r7.entityType}:generation`,{sourceEntityType:$,sourceEntityId:w,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 X=L0(Y);return Q.error(`Failed to enqueue social post generation for ${w}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Tx0(A,Q){A.messaging.subscribe("generate:execute",async(B)=>{let{entityType:$}=B.payload;if($!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let w=await A.entityService.listEntities("post",{filter:{metadata:{status:"published"}},limit:5});if(w.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 X of w)if((await A.entityService.listEntities("social-post",{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1})).length===0){D=X;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(`${r7.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(w){let D=L0(w);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 xx0={name:"@brains/social-media",private:!0,version:"0.2.0-alpha.32",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 CJA extends z2{entityType=r7.entityType;schema=gE;adapter=r7;providers=new Map;constructor(A){super("social-media",xx0,A,zJA)}createGenerationHandler(A){return new o3(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Rx0()}getDataSources(){return[new Ji(this.logger.child("SocialPostDataSource"))]}async onRegister(A){if(this.initializeProviders(),_x0(A,this.providers,this.logger),kx0(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)fx0(A,this.logger),bx0(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Tx0(A,this.logger),Px0(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=MJA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function yf(A){return new CJA(A)}ZA();var u3Q=F.enum(["draft","queued","published","failed"]),sBB=F.object({status:u3Q.default("draft"),queueOrder:F.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:F.string().datetime().optional()});class OJA{name="internal";async publish(A,Q){return{id:"internal"}}}var y6={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"},jI={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"};ZA();var c3Q=F.object({skipIfDraftExists:F.boolean().optional(),minSourceEntities:F.number().optional(),maxUnpublishedDrafts:F.number().optional(),sourceEntityType:F.string().optional()}),vx0=F.object({entitySchedules:F.record(F.string(),F.string()).optional(),generationSchedules:F.record(F.string(),F.string()).optional(),generationConditions:F.record(F.string(),c3Q).optional(),maxRetries:F.number().optional().default(3),retryBaseDelayMs:F.number().optional().default(5000)});class RI{static instance=null;queues=new Map;static getInstance(){return RI.instance??=new RI,RI.instance}static resetInstance(){RI.instance=null}static createFresh(){return new RI}constructor(){}async add(A,Q){let B=this.getOrCreateQueue(A),$=B.find((Y)=>Y.entityId===Q);if($)return{position:$.position};let w=B.length+1,D={entityId:Q,entityType:A,position:w,queuedAt:new Date().toISOString()};return B.push(D),{position:w}}async remove(A,Q){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((w)=>w.entityId===Q);if($===-1)return;B.splice($,1),this.recalculatePositions(B)}async reorder(A,Q,B){let $=this.queues.get(A);if(!$)return;let w=$.findIndex((X)=>X.entityId===Q);if(w===-1)return;let[D]=$.splice(w,1);if(!D)return;let Y=Math.max(0,Math.min(B-1,$.length));$.splice(Y,0,D),this.recalculatePositions($)}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 PI{static instance=null;providers=new Map;defaultProvider=new OJA;static getInstance(){return PI.instance??=new PI,PI.instance}static resetInstance(){PI.instance=null}static createFresh(){return new PI}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())}}ZA();ZA();async function Sx0(A,Q){let B={entityType:A.entityType,entityId:A.entityId};if(Q.messageBus)await Q.messageBus.send(y6.EXECUTE,B,"publish-service");Q.onExecute?.(B)}async function hx0(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 $=await Q.entityService.getEntity(A.entityType,A.entityId);if(!$){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:`Entity not found: ${A.entityType}/${A.entityId}`,retryCount:0,willRetry:!1});return}try{let w=await B.publish($.content,$.metadata);Q.retryTracker.clearRetries(A.entityId),Q.onPublish?.({entityType:A.entityType,entityId:A.entityId,result:w})}catch(w){let D=L0(w);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 gx0(A,Q,B,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send(y6.COMPLETED,{entityType:A,entityId:Q,result:B},"publish-service");$.onPublish?.({entityType:A,entityId:Q,result:B})}function yx0(A,Q,B,$){$.retryTracker.recordFailure(Q,B);let w=$.retryTracker.getRetryInfo(Q),D={entityType:A,entityId:Q,error:B,retryCount:w?.retryCount??1,willRetry:w?.willRetry??!1};if($.messageBus)$.messageBus.send(y6.FAILED,D,"publish-service");$.onFailed?.(D)}async function mx0(A,Q){let B=Q.generationConditions[A];if(B&&Q.onCheckGenerationConditions){let w=await Q.onCheckGenerationConditions(A,B);if(!w.shouldGenerate){if(Q.messageBus)Q.messageBus.send(jI.SKIPPED,{entityType:A,reason:w.reason??"Conditions not met"},"content-pipeline");return}}let $={entityType:A};if(Q.messageBus)await Q.messageBus.send(jI.EXECUTE,$,"content-pipeline");Q.onGenerate?.($)}function ux0(A,Q,B){if(B)B.send(jI.COMPLETED,{entityType:A,entityId:Q},"content-pipeline")}function cx0(A,Q,B){if(B)B.send(jI.FAILED,{entityType:A,error:Q},"content-pipeline")}var l3Q=1000;class yY{static instance=null;config;publishJobs=new Map;generationJobs=new Map;immediateIntervalJob=null;running=!1;static getInstance(A){return yY.instance??=new yY(A),yY.instance}static resetInstance(){if(yY.instance)yY.instance.stop();yY.instance=null}static createFresh(A){return new yY(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(l3Q,()=>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 Sx0(A,this.publishDeps);else await hx0(A,this.publishDeps)}completePublish(A,Q,B){gx0(A,Q,B,this.publishDeps)}failPublish(A,Q,B){yx0(A,Q,B,this.publishDeps)}async publishDirect(A,Q,B,$){return this.config.providerRegistry.get(A).publish(B,$)}async handleTriggerGeneration(A){if(!this.running)return;try{await mx0(A,this.generationDeps)}catch(Q){this.config.logger.error(`Generation trigger error for ${A}:`,Q)}}completeGeneration(A,Q){ux0(A,Q,this.config.messageBus)}failGeneration(A,Q){cx0(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($){throw Error(`Invalid ${B} cron expression for ${A}: "${Q}" - ${L0($)}`)}}}var lx0={maxRetries:3,baseDelayMs:5000};class _I{static instance=null;retries=new Map;config;static getInstance(A){return _I.instance??=new _I(A??lx0),_I.instance}static resetInstance(){_I.instance=null}static createFresh(A){return new _I(A??lx0)}constructor(A){this.config=A}recordFailure(A,Q){let $=(this.retries.get(A)?.retryCount??0)+1,w=this.config.baseDelayMs*Math.pow(2,$-1),D=Date.now()+w;this.retries.set(A,{entityId:A,retryCount:$,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 F$(A,Q,B,$,w,D,Y,X){return F$.fromTZ(F$.tp(A,Q,B,$,w,D,Y),X)}F$.fromTZISO=(A,Q,B)=>F$.fromTZ(p3Q(A,Q),B);F$.fromTZ=function(A,Q){let B=new Date(Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)),$=jJA(A.tz,B),w=new Date(B.getTime()-$),D=jJA(A.tz,w);if(D-$===0)return w;{let Y=new Date(B.getTime()-D),X=jJA(A.tz,Y);if(X-D===0)return Y;if(!Q&&X-D>0)return Y;if(Q)throw Error("Invalid date passed to fromTZ()");return w}};F$.toTZ=function(A,Q){let B=A.toLocaleString("en-US",{timeZone:Q}).replace(/[\u202f]/," "),$=new Date(B);return{y:$.getFullYear(),m:$.getMonth()+1,d:$.getDate(),h:$.getHours(),i:$.getMinutes(),s:$.getSeconds(),tz:Q}};F$.tp=(A,Q,B,$,w,D,Y)=>({y:A,m:Q,d:B,h:$,i:w,s:D,tz:Y});function jJA(A,Q=new Date){let B=Q.toLocaleString("en-US",{timeZone:A,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],$=Q.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${$} GMT`)-Date.parse(`${$} ${B}`)}function p3Q(A,Q){let B=new Date(Date.parse(A));if(isNaN(B))throw Error("minitz: Invalid ISO8601 passed to parser.");let $=A.substring(9);return A.includes("Z")||$.includes("-")||$.includes("+")?F$.tp(B.getUTCFullYear(),B.getUTCMonth()+1,B.getUTCDate(),B.getUTCHours(),B.getUTCMinutes(),B.getUTCSeconds(),"Etc/UTC"):F$.tp(B.getFullYear(),B.getMonth()+1,B.getDate(),B.getHours(),B.getMinutes(),B.getSeconds(),Q)}F$.minitz=F$;var RJA=32,uf=31|RJA,rx0=[1,2,4,8,16],px0=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 $4(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,uf),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,B,$){let w=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 w.fill($);let Y=Q.split(",");if(Y.length>1)for(let X=0;X<Y.length;X++)this.partToArray(A,Y[X],B,$);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,B,$):Q.indexOf("-")!==-1?this.handleRange(Q,A,B,$):Q.indexOf("/")!==-1?this.handleStepping(Q,A,B,$):Q!==""&&this.handleNumber(Q,A,B,$)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===5?/[^/*0-9,\-#L]+/:/[^/*0-9,-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,B,$){let w=this.extractNth(A,Q),D=parseInt(w[0],10)+B;if(isNaN(D))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,D,w[1]||$)}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,$){let w=this.extractNth(A,Q),D=w[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(D===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,I]=D,K=parseInt(Y,10)+B,G=parseInt(X,10)+B,W=parseInt(I,10);if(isNaN(K))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(G))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(W))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(W===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(W>this[Q].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[Q].length+")");if(K>G)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let Z=K;Z<=G;Z+=W)this.setPart(Q,Z,w[1]||$)}extractNth(A,Q){let B=A,$;if(B.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");$=B.split("#")[1],B=B.split("#")[0]}return[B,$]}handleRange(A,Q,B,$){let w=this.extractNth(A,Q),D=w[0].split("-");if(D.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(D[0],10)+B,X=parseInt(D[1],10)+B;if(isNaN(Y))throw TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(X))throw TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(Y>X)throw TypeError("CronPattern: From value is larger than to value: '"+A+"'");for(let I=Y;I<=X;I++)this.setPart(Q,I,w[1]||$)}handleStepping(A,Q,B,$){let w=this.extractNth(A,Q),D=w[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 X=parseInt(D[1],10);if(isNaN(X))throw TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(X===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(X>this[Q].length)throw TypeError("CronPattern: Syntax error, max steps for part is ("+this[Q].length+")");for(let I=Y;I<this[Q].length;I+=X)this.setPart(Q,I,w[1]||$)}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]|RJA;else if(Q===uf)this.dayOfWeek[A]=uf;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|rx0[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},dx0=[31,28,31,30,31,30,31,31,30,31,30,31],lH=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],$4=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,$)).getUTCDay(),Y=0;for(let X=1;X<=$;X++)new Date(Date.UTC(Q,B,X)).getUTCDay()===D&&Y++;if(w&uf&&rx0[Y-1]&w)return!0;if(w&RJA){let X=new Date(Date.UTC(Q,B+1,0)).getUTCDate();for(let I=$+1;I<=X;I++)if(new Date(Date.UTC(Q,B,I)).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=F$.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>dx0[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=F$.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(F$.fromTZISO(Q,this.tz))}findNext(Q,B,$,w){let D=this[B],Y;$.lastDayOfMonth&&(this.month!==1?Y=dx0[this.month]:Y=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let X=!$.starDOW&&B=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let I=this[B]+w;I<$[B].length;I++){let K=$[B][I];if(B==="day"&&$.lastDayOfMonth&&I-w==Y&&(K=1),B==="day"&&!$.starDOW){let G=$.dayOfWeek[(X+(I-w-1))%7];if(G&&G&uf)G=this.isNthWeekdayOfMonth(this.year,this.month,I-w,G)?1:0;else if(G)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${G}`);Q.legacyMode&&!$.starDOM?K=K||G:K=K&&G}if(K)return this[B]=I-w,D!==this[B]?2:1}return 3}recurse(Q,B,$){let w=this.findNext(B,lH[$][0],Q,lH[$][2]);if(w>1){let D=$+1;for(;D<lH.length;)this[lH[D][0]]=-lH[D][2],D++;if(w===3)return this[lH[$][1]]++,this[lH[$][0]]=-lH[$][2],this.apply(),this.recurse(Q,B,0);if(this.apply())return this.recurse(Q,B,$-1)}return $+=1,$>=lH.length?this:this.year>=3000?null:this.recurse(Q,B,$)}increment(Q,B,$){return this.second+=B.interval!==void 0&&B.interval>1&&$?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)):F$.fromTZ(F$.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function d3Q(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 $4(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new $4(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 mf(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function i3Q(A){return mf(A)}function r3Q(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var ix0=30000,qi=[],PJA=class{name;options;_states;fn;constructor(A,Q,B){let $,w;if(mf(Q))w=Q;else if(typeof Q=="object")$=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(mf(B))w=B;else if(typeof B=="object")$=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=$?.name,this.options=d3Q($),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:$?$.maxRuns:void 0,paused:$?$.paused:!1,pattern:new px0("* * * * *")},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new $4(A,this.options.timezone||this.options.utcOffset):this._states.pattern=new px0(A,this.options.timezone),this.name){if(qi.find((D)=>D.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");qi.push(this)}return w!==void 0&&i3Q(w)&&(this.fn=w,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=[],$=Q||this._states.currentRun||void 0;for(;A--&&($=this.nextRun($));)B.push($);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,$=!this._states.kill;return Q&&B&&$&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof $4||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new $4(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=qi.indexOf(this);A>=0&&qi.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>ix0&&(Q=ix0),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(B),Q),this._states.currentTimeout&&this.options.unref&&r3Q(this._states.currentTimeout),this)}async _trigger(A){if(this._states.blocking=!0,this._states.currentRun=new $4(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){mf(this.options.catch)&&this.options.catch(Q,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new $4(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(),$=this._states.blocking&&this.options.protect;B&&!$?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):B&&$&&mf(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 $4(A,this.options.timezone||this.options.utcOffset),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let $=this._states.once||new $4(A,this.options.timezone||this.options.utcOffset);return!B&&$!==this._states.once&&($=$.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||$===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&$.getTime()>=this.options.stopAt.getTime()?null:$}_calculatePreviousRun(A,Q){let B=new $4(void 0,this.options.timezone||this.options.utcOffset),$=A;if(this.options.startAt.getTime()<=B.getTime()){$=this.options.startAt;let w=$.getTime()+this.options.interval*1000;for(;w<=B.getTime();)$=new $4($,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),w=$.getTime()+this.options.interval*1000;Q=!0}return $===null&&($=void 0),[$,Q]}};class zi{scheduleCron(A,Q){let B=new PJA(A,()=>{Q()});return{stop:()=>B.stop()}}scheduleInterval(A,Q){let B=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(B)}}validateCron(A){new PJA(A).stop()}}w0();ZA();var _JA=F.object({action:F.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:F.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:F.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:F.number().optional().describe("New position for reorder action (1-based)")}),kJA=F.object({position:F.number(),entityType:F.string(),entityId:F.string(),queuedAt:F.string()}),n3Q=F.object({success:F.literal(!0),message:F.string().optional(),data:F.object({queue:F.array(kJA).optional(),entityType:F.string().optional(),entityId:F.string().optional(),position:F.number().optional()}).optional()}),o3Q=F.object({success:F.literal(!1),error:F.string(),code:F.string().optional()}),fJA=F.union([n3Q,o3Q]);function Vi(A,Q,B){return{...g2(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",_JA,async(w)=>{let{action:D,entityType:Y,entityId:X,position:I}=w;switch(D){case"list":return s3Q(B,Y);case"add":return a3Q(B,Y,X);case"remove":return t3Q(B,Y,X);case"reorder":return e3Q(B,Y,X,I);default:return{success:!1,error:`Unknown action: ${D}`}}}),outputSchema:fJA}}async function s3Q(A,Q){let B=[];if(Q)B=await A.list(Q);else{let w=A.getRegisteredTypes();for(let D of w){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((w,D)=>({position:D+1,entityType:w.entityType,entityId:w.entityId,queuedAt:w.queuedAt}))},message:`${B.length} items in queue`}}async function a3Q(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 $=await A.add(Q,B);return{success:!0,data:{entityType:Q,entityId:B,position:$.position},message:`Added to queue at position ${$.position}`}}async function t3Q(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 e3Q(A,Q,B,$){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($===void 0)return{success:!1,error:"position is required for reorder action"};if($<1)return{success:!1,error:"position must be a positive number"};return await A.reorder(Q,B,$),{success:!0,data:{entityType:Q,entityId:B,position:$},message:`Moved to position ${$}`}}w0();ZA();var bJA=F.object({entityType:F.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:F.string().optional().describe("Entity ID to publish"),slug:F.string().optional().describe("Entity slug to publish")}),AqQ=F.object({success:F.literal(!0),message:F.string().optional(),data:F.object({entityType:F.string().optional(),entityId:F.string().optional(),platformId:F.string().optional(),url:F.string().optional()}).optional()}),QqQ=F.object({success:F.literal(!1),error:F.string(),code:F.string().optional()}),TJA=F.union([AqQ,QqQ]);function Ni(A,Q,B){return{...g2(Q,"publish","Publish an entity directly to its platform. Works with any registered entity type (social-post, post, deck, etc.)",bJA,async(w)=>{let{entityType:D,id:Y,slug:X}=w;if(!Y&&!X)return{success:!1,error:"Either 'id' or 'slug' must be provided"};let I=null;if(Y)I=await A.entityService.getEntity(D,Y);else if(X)I=(await A.entityService.listEntities(D,{filter:{metadata:{slug:X}},limit:1}))[0]??null;if(!I)return{success:!1,error:`Entity not found: ${D}:${Y??X}`};if(I.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 K=B.get(D),G=I.content,W;try{let N=JQ(I.content,F.record(F.unknown()));G=N.content;let M=N.metadata.coverImageId;W=typeof M==="string"?M:void 0}catch{}let Z;if(W){let N=await A.entityService.getEntity("image",W);if(N?.content){let M=N.content.match(/^data:([^;]+);base64,(.+)$/);if(M?.[1]&&M[2])Z={data:Buffer.from(M[2],"base64"),mimeType:M[1]}}}let q=await K.publish(G,I.metadata,Z);return await A.entityService.updateEntity({...I,metadata:{...I.metadata,status:"published",publishedAt:new Date().toISOString(),platformId:q.id}}),{success:!0,data:{entityType:D,entityId:I.id,platformId:q.id,url:q.url},message:`Published ${D}:${I.id}`}}),outputSchema:TJA}}w0();ZA();function nx0(A,Q){let{logger:B}=Q;A.messaging.subscribe(y6.REGISTER,async($)=>BqQ(Q,$.payload)),A.messaging.subscribe(y6.QUEUE,async($)=>$qQ(A,Q,$.payload)),A.messaging.subscribe(y6.DIRECT,async($)=>wqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REMOVE,async($)=>DqQ(Q,$.payload)),A.messaging.subscribe(y6.REORDER,async($)=>YqQ(Q,$.payload)),A.messaging.subscribe(y6.LIST,async($)=>XqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REPORT_SUCCESS,async($)=>IqQ(A,Q,$.payload)),A.messaging.subscribe(y6.REPORT_FAILURE,async($)=>KqQ(A,Q,$.payload)),B.debug("Subscribed to publish messages"),A.messaging.subscribe(jI.REPORT_SUCCESS,async($)=>{let{entityType:w,entityId:D}=$.payload;return Q.scheduler.completeGeneration(w,D),B.info("Generation completed",{entityType:w,entityId:D}),{success:!0}}),A.messaging.subscribe(jI.REPORT_FAILURE,async($)=>{let{entityType:w,error:D}=$.payload;return Q.scheduler.failGeneration(w,D),B.warn("Generation failed",{entityType:w,error:D}),{success:!0}}),B.debug("Subscribed to generation messages")}async function BqQ(A,Q){let{entityType:B,provider:$}=Q;try{if($)A.providerRegistry.register(B,$),A.logger.info(`Registered provider for entity type: ${B}`,{providerName:$.name});return{success:!0}}catch(w){let D=L0(w);return A.logger.error(`Failed to register provider: ${D}`),{success:!1}}}async function $qQ(A,Q,B){let{entityType:$,entityId:w}=B;try{let D=await Q.queueManager.add($,w);return await A.messaging.send(y6.QUEUED,{entityType:$,entityId:w,position:D.position}),Q.logger.debug(`Entity queued: ${w}`,{entityType:$,position:D.position}),{success:!0}}catch(D){let Y=L0(D);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function wqQ(A,Q,B){let{entityType:$,entityId:w}=B;return await A.messaging.send(y6.EXECUTE,{entityType:$,entityId:w}),Q.logger.debug(`Direct publish requested: ${w}`,{entityType:$}),{success:!0}}async function DqQ(A,Q){let{entityType:B,entityId:$}=Q;try{return await A.queueManager.remove(B,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:B}),{success:!0}}catch(w){let D=L0(w);return A.logger.error(`Failed to remove entity: ${D}`),{success:!1}}}async function YqQ(A,Q){let{entityType:B,entityId:$,position:w}=Q;try{return await A.queueManager.reorder(B,$,w),A.logger.debug(`Entity reordered: ${$}`,{entityType:B,newPosition:w}),{success:!0}}catch(D){let Y=L0(D);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function XqQ(A,Q,B){let{entityType:$}=B;try{let w=await Q.queueManager.list($);return await A.messaging.send(y6.LIST_RESPONSE,{entityType:$,queue:w.map((D)=>({entityId:D.entityId,position:D.position,queuedAt:D.queuedAt}))}),{success:!0}}catch(w){let D=L0(w);return Q.logger.error(`Failed to list queue: ${D}`),{success:!1}}}async function IqQ(A,Q,B){let{entityType:$,entityId:w,result:D}=B;return Q.retryTracker.clearRetries(w),await A.messaging.send(y6.COMPLETED,{entityType:$,entityId:w,result:D}),Q.logger.info(`Publish reported success: ${w}`,{entityType:$}),{success:!0}}async function KqQ(A,Q,B){let{entityType:$,entityId:w,error:D}=B;Q.retryTracker.recordFailure(w,D);let Y=Q.retryTracker.getRetryInfo(w);return await A.messaging.send(y6.FAILED,{entityType:$,entityId:w,error:D,retryCount:Y?.retryCount??1,willRetry:Y?.willRetry??!1}),Q.logger.info(`Publish reported failure: ${w}`,{entityType:$,error:D,retryCount:Y?.retryCount,willRetry:Y?.willRetry}),{success:!0}}ZA();async function ox0(A,Q,B,$){try{if($.skipIfDraftExists!==!1){if((await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:1})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if($.maxUnpublishedDrafts!==void 0){let w=await A.listEntities(B,{filter:{metadata:{status:"draft"}},limit:$.maxUnpublishedDrafts+1});if(w.length>=$.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${w.length}/${$.maxUnpublishedDrafts})`}}if($.minSourceEntities!==void 0&&$.sourceEntityType){let w=await A.listEntities($.sourceEntityType,{publishedOnly:!0,limit:$.minSourceEntities});if(w.length<$.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${w.length}/${$.minSourceEntities} ${$.sourceEntityType})`}}return{shouldGenerate:!0}}catch(w){return Q.error("Failed to check generation conditions",{entityType:B,error:L0(w)}),{shouldGenerate:!1,reason:`Condition check failed: ${L0(w)}`}}}function sx0(A){let{context:Q,config:B,queueManager:$,providerRegistry:w,retryTracker:D,logger:Y}=A,X={send:async(I,K)=>{return Q.messaging.send(I,K)},subscribe:()=>()=>{}};return yY.createFresh({queueManager:$,providerRegistry:w,retryTracker:D,logger:Y,backend:new zi,...B.entitySchedules&&{entitySchedules:B.entitySchedules},...B.generationSchedules&&{generationSchedules:B.generationSchedules},...B.generationConditions&&{generationConditions:B.generationConditions},messageBus:X,entityService:Q.entityService,onPublish:(I)=>{Q.messaging.send(y6.COMPLETED,{entityType:I.entityType,entityId:I.entityId,result:I.result})},onFailed:(I)=>{Q.messaging.send(y6.FAILED,{entityType:I.entityType,entityId:I.entityId,error:I.error,retryCount:I.retryCount,willRetry:I.willRetry})},onCheckGenerationConditions:(I,K)=>ox0(Q.entityService,Y,I,K),onGenerate:(I)=>{Y.info(`Generation triggered for ${I.entityType}`),Q.messaging.send(jI.EXECUTE,{entityType:I.entityType})}})}async function ax0(A,Q,B){let $=A.getEntityTypes();for(let D of $){let Y=await A.listEntities(D,{filter:{metadata:{status:"queued"}}});for(let X of Y)await Q.add(X.entityType,X.id)}let w=0;for(let D of $){let Y=await Q.list(D);w+=Y.length}if(w>0)B.info(`Rebuilt queue with ${w} queued entities`)}var tx0={name:"@brains/content-pipeline",private:!0,version:"0.2.0-alpha.32",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 xJA extends f8{pluginContext;queueManager;providerRegistry;retryTracker;scheduler;constructor(A){super("content-pipeline",tx0,A??{},vx0)}async onRegister(A){this.pluginContext=A,this.queueManager=RI.createFresh(),this.providerRegistry=PI.createFresh(),this.retryTracker=_I.createFresh({maxRetries:this.config.maxRetries,baseDelayMs:this.config.retryBaseDelayMs}),this.scheduler=sx0({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,logger:this.logger}),nx0(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 ax0(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:15,rendererName:"PipelineWidget",dataProvider:async()=>{let Q=A.entityService.getEntityTypes(),B=[],$={draft:0,queued:0,published:0,failed:0};for(let w of Q){let D=await A.entityService.listEntities(w);for(let Y of D){let X=Y.metadata.status;if(X!=="draft"&&X!=="queued"&&X!=="published"&&X!=="failed")continue;$[X]++;let I=Y.metadata.title;B.push({id:Y.id,title:typeof I==="string"?I:Y.id,type:w,status:X})}}return{summary:$,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[Vi(this.pluginContext,this.id,this.queueManager),Ni(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(){RI.resetInstance(),PI.resetInstance(),_I.resetInstance()}}function vJA(A){return new xJA(A)}w0();ZA();var ex0=F.object({accountId:F.string().describe("Cloudflare account ID"),apiToken:F.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:F.string().describe("Cloudflare Web Analytics site tag")}),SJA=F.object({cloudflare:ex0.optional()});w0();ZA();var UqQ=F.object({date:F.string().describe("Single date in YYYY-MM-DD format").optional(),days:F.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:F.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:F.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:F.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function GqQ(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 $=[];if(!B)return $;return $.push(g2(A,"query",`Query website analytics from Cloudflare.
2720
2720
 
2721
2721
  Date range options (use only one):
2722
2722
  - No params: yesterday only
@@ -2854,7 +2854,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,UqQ,
2854
2854
  }
2855
2855
  }
2856
2856
  }
2857
- `,variables:B})});if(!$.ok){let Y=await $.text();throw Error(`Cloudflare API error: ${$.status} - ${Y}`)}let w=await $.json();if(w.errors&&w.errors.length>0)throw Error(`Cloudflare GraphQL error: ${w.errors.map((Y)=>Y.message).join(", ")}`);return(w.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((Y)=>({country:Y.dimensions.countryName,visits:Y.sum.visits}))}}ZA();var gJA=7,JqQ=10;function Bv0(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=yz(),B=px(gJA),$=wG(B),w=wG(Q);try{let[D,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:w}),A.getTopPages({startDate:$,endDate:w,limit:JqQ})]);return{days:gJA,startDate:$,endDate:w,pageviews:D.pageviews,visitors:D.visitors,topPages:Y}}catch(D){return{error:D instanceof Error?D.message:"Failed to fetch analytics",days:gJA}}}}var $v0={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.31",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 wv0 extends f8{cloudflareClient;constructor(A={}){super("analytics",$v0,A,SJA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new hJA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",Bv0(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:Qv0(Q)}),{success:!0}})}async getTools(){return Av0(this.id,this.getContext(),this.cloudflareClient)}}function ZqQ(A={}){return new wv0(A)}var Li=ZqQ;w0();function yJA(A){return`<!doctype html>
2857
+ `,variables:B})});if(!$.ok){let Y=await $.text();throw Error(`Cloudflare API error: ${$.status} - ${Y}`)}let w=await $.json();if(w.errors&&w.errors.length>0)throw Error(`Cloudflare GraphQL error: ${w.errors.map((Y)=>Y.message).join(", ")}`);return(w.data.viewer.accounts[0]?.rumPageloadEventsAdaptiveGroups??[]).map((Y)=>({country:Y.dimensions.countryName,visits:Y.sum.visits}))}}ZA();var gJA=7,JqQ=10;function Bv0(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=yz(),B=px(gJA),$=wG(B),w=wG(Q);try{let[D,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:w}),A.getTopPages({startDate:$,endDate:w,limit:JqQ})]);return{days:gJA,startDate:$,endDate:w,pageviews:D.pageviews,visitors:D.visitors,topPages:Y}}catch(D){return{error:D instanceof Error?D.message:"Failed to fetch analytics",days:gJA}}}}var $v0={name:"@brains/analytics",private:!0,version:"0.2.0-alpha.32",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 wv0 extends f8{cloudflareClient;constructor(A={}){super("analytics",$v0,A,SJA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new hJA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",Bv0(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:Qv0(Q)}),{success:!0}})}async getTools(){return Av0(this.id,this.getContext(),this.cloudflareClient)}}function ZqQ(A={}){return new wv0(A)}var Li=ZqQ;w0();function yJA(A){return`<!doctype html>
2858
2858
  <html>
2859
2859
  <head>
2860
2860
  <meta charset="utf-8" />
@@ -2865,7 +2865,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,UqQ,
2865
2865
  </head>
2866
2866
  <body></body>
2867
2867
  </html>
2868
- `}ZA();var Dv0={name:"@brains/cms",private:!0,version:"0.2.0-alpha.31",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 qqQ=F.object({label:F.string().optional(),pluralName:F.string().optional()}).passthrough(),zqQ=F.object({entityDisplay:F.record(qqQ).optional(),routePath:F.string().default("/")});function VqQ(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function NqQ(A){let Q=A.entityDisplay;return Q?{entityDisplay:Q}:{}}async function LqQ(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:$}=Q.data;if(!B||!$)throw Error("CMS config unavailable: git-sync repo info incomplete");return{repo:B,branch:$}}async function EqQ(A,Q={}){let{repo:B,branch:$}=await LqQ(A);return Vf({repo:B,branch:$,...A.siteUrl&&{baseUrl:A.siteUrl},entityTypes:A.entityService.getEntityTypes(),getFrontmatterSchema:(w)=>A.entities.getEffectiveFrontmatterSchema(w),getAdapter:(w)=>A.entities.getAdapter(w),...Q.entityDisplay&&{entityDisplay:Q.entityDisplay}})}async function Yv0(A,Q={}){return ND(await EqQ(A,Q))}class Ei extends f8{constructor(A={}){super("admin",Dv0,A,zqQ)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40})}getWebRoutes(){let A=VqQ(this.config.routePath);return[{path:this.config.routePath,method:"GET",public:!0,handler:async()=>{return new Response(yJA({cmsConfigPath:A}),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:A,method:"GET",public:!0,handler:async()=>{try{let Q=await Yv0(this.getContext(),NqQ(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 tJ(A){return new Ei(A)}w0();ZA();ZA();var cf=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],MqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number().default(50),section:F.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:F.enum(cf)});class Mi{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})}unregister(A,Q){if(Q)this.widgets.delete(`${A}:${Q}`);else for(let B of this.widgets.keys())if(B.startsWith(`${A}:`))this.widgets.delete(B)}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}}ZA();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($)=>{let w=await $.dataProvider(),{dataProvider:D,...Y}=$;return{key:`${$.pluginId}:${$.id}`,widget:Y,data:w}}));for(let $=0;$<B.length;$++){let w=B[$],D=Q[$];if(!w||!D)continue;if(w.status==="fulfilled")A[w.value.key]={widget:w.value.widget,data:w.value.data};else this.logger.error("Widget data provider failed",{widgetId:D.id,pluginId:D.pluginId,error:L0(w.reason)})}return{widgets:A}}async fetch(A,Q,B){return await this.getDashboardData()}}ZA();var Xv0=`
2868
+ `}ZA();var Dv0={name:"@brains/cms",private:!0,version:"0.2.0-alpha.32",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 qqQ=F.object({label:F.string().optional(),pluralName:F.string().optional()}).passthrough(),zqQ=F.object({entityDisplay:F.record(qqQ).optional(),routePath:F.string().default("/")});function VqQ(A){return`${A.endsWith("/")?A:`${A}/`}config.yml`}function NqQ(A){let Q=A.entityDisplay;return Q?{entityDisplay:Q}:{}}async function LqQ(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:$}=Q.data;if(!B||!$)throw Error("CMS config unavailable: git-sync repo info incomplete");return{repo:B,branch:$}}async function EqQ(A,Q={}){let{repo:B,branch:$}=await LqQ(A);return Vf({repo:B,branch:$,...A.siteUrl&&{baseUrl:A.siteUrl},entityTypes:A.entityService.getEntityTypes(),getFrontmatterSchema:(w)=>A.entities.getEffectiveFrontmatterSchema(w),getAdapter:(w)=>A.entities.getAdapter(w),...Q.entityDisplay&&{entityDisplay:Q.entityDisplay}})}async function Yv0(A,Q={}){return ND(await EqQ(A,Q))}class Ei extends f8{constructor(A={}){super("admin",Dv0,A,zqQ)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40})}getWebRoutes(){let A=VqQ(this.config.routePath);return[{path:this.config.routePath,method:"GET",public:!0,handler:async()=>{return new Response(yJA({cmsConfigPath:A}),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:A,method:"GET",public:!0,handler:async()=>{try{let Q=await Yv0(this.getContext(),NqQ(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 tJ(A){return new Ei(A)}w0();ZA();ZA();var cf=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],MqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number().default(50),section:F.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:F.enum(cf)});class Mi{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})}unregister(A,Q){if(Q)this.widgets.delete(`${A}:${Q}`);else for(let B of this.widgets.keys())if(B.startsWith(`${A}:`))this.widgets.delete(B)}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}}ZA();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($)=>{let w=await $.dataProvider(),{dataProvider:D,...Y}=$;return{key:`${$.pluginId}:${$.id}`,widget:Y,data:w}}));for(let $=0;$<B.length;$++){let w=B[$],D=Q[$];if(!w||!D)continue;if(w.status==="fulfilled")A[w.value.key]={widget:w.value.widget,data:w.value.data};else this.logger.error("Widget data provider failed",{widgetId:D.id,pluginId:D.pluginId,error:L0(w.reason)})}return{widgets:A}}async fetch(A,Q,B){return await this.getDashboardData()}}ZA();var Xv0=`
2869
2869
  :root {
2870
2870
  --ink: #0a0819;
2871
2871
  --ink-raised: #14112b;
@@ -3501,7 +3501,7 @@ body::after {
3501
3501
  <script>${hqQ}</script>
3502
3502
  </body>
3503
3503
  </html>
3504
- `}var Wv0={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.31",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:*"},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 yqQ=F.object({version:F.string().default("1.0.0"),routePath:F.string().default("/dashboard")}),mqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number().default(50),section:F.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:F.enum(cf),dataProvider:F.function().returns(F.promise(F.unknown()))}),uqQ=F.object({pluginId:F.string(),widgetId:F.string().optional()});class mJA extends f8{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A){super("dashboard",Wv0,A??{},yqQ)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new Mi(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=mqQ.parse(Q.payload),$={id:B.id,pluginId:B.pluginId,title:B.title,description:B.description,priority:B.priority,section:B.section,rendererName:B.rendererName,dataProvider:B.dataProvider};return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:B.id,pluginId:B.pluginId}),{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=uqQ.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(),X=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),K={title:Y.name||$.model||"Brain Dashboard",baseUrl:X,widgets:B.widgets,character:D,profile:Y,appInfo:$,entityCounts:w};return new Response(Jv0(K),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function s3(A){return new mJA(A)}ZA();var cqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number(),section:F.enum(["primary","secondary","sidebar"]),rendererName:F.enum(cf)}),lqQ=F.object({widget:cqQ,data:F.unknown()}),pqQ=F.object({widgets:F.record(lqQ)});ZA();w0();ZA();import{h as wzQ}from"preact";ZA();d4();w0();var yE=F.enum(["draft","queued","published","failed"]),lf=F.object({subject:F.string(),status:yE,entityIds:F.array(F.string()).optional(),scheduledFor:F.string().datetime().optional(),sentAt:F.string().datetime().optional(),buttondownId:F.string().optional(),sourceEntityType:F.string().optional()}),Zv0=lf.pick({subject:!0,status:!0,entityIds:!0,scheduledFor:!0,sentAt:!0,buttondownId:!0,sourceEntityType:!0}),pf=FQ.extend({entityType:F.literal("newsletter"),metadata:Zv0});w0();class Fv0 extends _Q{constructor(){super({entityType:"newsletter",schema:pf,frontmatterSchema:lf})}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 qv0=new Fv0;w0();w0();ZA();var dqQ=UG.extend({status:F.enum(["draft","queued","published","failed"]).optional()}),iqQ=GG.extend({query:dqQ.optional()});function zv0(A){try{let{content:Q}=JQ(A.content,lf);return Q}catch{return A.content}}class uJA extends i9{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=iqQ.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=zv0(A),B={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:$G(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:$}=this.parseQuery(A),w=B.entityService;if($.id)return this.fetchSingleNewsletter($.id,Q,w);let D=$.status,Y=D?{filter:{metadata:{status:D}}}:void 0,{items:X,pagination:I}=await this.fetchList($,w,Y);return Q.parse(this.buildListResult(X,I,$))}async fetchSingleNewsletter(A,Q,B){let $=await B.getEntity(this.config.entityType,A);if(!$)throw Error(`Newsletter not found: ${A}`);let w=await this.resolveNavigation($,B),D=[];if($.metadata.entityIds?.length){let I=$.metadata.sourceEntityType??"post";D=(await Promise.all($.metadata.entityIds.map(async(G)=>{let W=await B.getEntity(I,G);if(W){let Z=W.metadata;return{id:G,title:Z.title??G,url:`/${I}s/${Z.slug??G}`}}return null}))).filter((G)=>G!==null)}let Y=zv0($),X={id:$.id,subject:$.metadata.subject,status:$.metadata.status,content:Y,created:$.created,updated:$.updated,sentAt:$.metadata.sentAt,scheduledFor:$.metadata.scheduledFor,newsletter:$,prevNewsletter:w.prev?{id:w.prev.id,subject:w.prev.subject,url:w.prev.url}:null,nextNewsletter:w.next?{id:w.next.id,subject:w.next.subject,url:w.next.url}:null,sourceEntities:D.length>0?D:void 0};return Q.parse(X)}}w0();ZA();var rqQ=F.object({prompt:F.string().optional().describe("AI generation prompt"),sourceEntityIds:F.array(F.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:F.enum(["post"]).optional().describe("Type of source entities"),content:F.string().optional().describe("Direct content (skip AI)"),subject:F.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:F.boolean().optional().describe("Create as queued (true) or draft (false)")});class cJA extends a5{constructor(A,Q){super(A,Q,{schema:rqQ,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let B=A.addToQueue??!1,{prompt:$,sourceEntityIds:w,sourceEntityType:D}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(w&&w.length>0){let Z=D??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${w.length} source entities`});let N=(await Promise.all(w.map((P)=>this.context.entityService.getEntity(Z,P)))).filter((P)=>P!=null);if(N.length===0)this.failEarly(`No source entities found for IDs: ${w.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${N.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
3504
+ `}var Wv0={name:"@brains/dashboard",private:!0,version:"0.2.0-alpha.32",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:*"},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 yqQ=F.object({version:F.string().default("1.0.0"),routePath:F.string().default("/dashboard")}),mqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number().default(50),section:F.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:F.enum(cf),dataProvider:F.function().returns(F.promise(F.unknown()))}),uqQ=F.object({pluginId:F.string(),widgetId:F.string().optional()});class mJA extends f8{widgetRegistry=null;datasource=null;siteUrl;ctx;constructor(A){super("dashboard",Wv0,A??{},yqQ)}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new Mi(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=mqQ.parse(Q.payload),$={id:B.id,pluginId:B.pluginId,title:B.title,description:B.description,priority:B.priority,section:B.section,rendererName:B.rendererName,dataProvider:B.dataProvider};return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:B.id,pluginId:B.pluginId}),{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=uqQ.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(),X=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),K={title:Y.name||$.model||"Brain Dashboard",baseUrl:X,widgets:B.widgets,character:D,profile:Y,appInfo:$,entityCounts:w};return new Response(Jv0(K),{headers:{"Content-Type":"text/html; charset=utf-8"}})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function s3(A){return new mJA(A)}ZA();var cqQ=F.object({id:F.string(),pluginId:F.string(),title:F.string(),description:F.string().optional(),priority:F.number(),section:F.enum(["primary","secondary","sidebar"]),rendererName:F.enum(cf)}),lqQ=F.object({widget:cqQ,data:F.unknown()}),pqQ=F.object({widgets:F.record(lqQ)});ZA();w0();ZA();import{h as wzQ}from"preact";ZA();d4();w0();var yE=F.enum(["draft","queued","published","failed"]),lf=F.object({subject:F.string(),status:yE,entityIds:F.array(F.string()).optional(),scheduledFor:F.string().datetime().optional(),sentAt:F.string().datetime().optional(),buttondownId:F.string().optional(),sourceEntityType:F.string().optional()}),Zv0=lf.pick({subject:!0,status:!0,entityIds:!0,scheduledFor:!0,sentAt:!0,buttondownId:!0,sourceEntityType:!0}),pf=FQ.extend({entityType:F.literal("newsletter"),metadata:Zv0});w0();class Fv0 extends _Q{constructor(){super({entityType:"newsletter",schema:pf,frontmatterSchema:lf})}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 qv0=new Fv0;w0();w0();ZA();var dqQ=UG.extend({status:F.enum(["draft","queued","published","failed"]).optional()}),iqQ=GG.extend({query:dqQ.optional()});function zv0(A){try{let{content:Q}=JQ(A.content,lf);return Q}catch{return A.content}}class uJA extends i9{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=iqQ.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=zv0(A),B={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:$G(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:$}=this.parseQuery(A),w=B.entityService;if($.id)return this.fetchSingleNewsletter($.id,Q,w);let D=$.status,Y=D?{filter:{metadata:{status:D}}}:void 0,{items:X,pagination:I}=await this.fetchList($,w,Y);return Q.parse(this.buildListResult(X,I,$))}async fetchSingleNewsletter(A,Q,B){let $=await B.getEntity(this.config.entityType,A);if(!$)throw Error(`Newsletter not found: ${A}`);let w=await this.resolveNavigation($,B),D=[];if($.metadata.entityIds?.length){let I=$.metadata.sourceEntityType??"post";D=(await Promise.all($.metadata.entityIds.map(async(G)=>{let W=await B.getEntity(I,G);if(W){let Z=W.metadata;return{id:G,title:Z.title??G,url:`/${I}s/${Z.slug??G}`}}return null}))).filter((G)=>G!==null)}let Y=zv0($),X={id:$.id,subject:$.metadata.subject,status:$.metadata.status,content:Y,created:$.created,updated:$.updated,sentAt:$.metadata.sentAt,scheduledFor:$.metadata.scheduledFor,newsletter:$,prevNewsletter:w.prev?{id:w.prev.id,subject:w.prev.subject,url:w.prev.url}:null,nextNewsletter:w.next?{id:w.next.id,subject:w.next.subject,url:w.next.url}:null,sourceEntities:D.length>0?D:void 0};return Q.parse(X)}}w0();ZA();var rqQ=F.object({prompt:F.string().optional().describe("AI generation prompt"),sourceEntityIds:F.array(F.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:F.enum(["post"]).optional().describe("Type of source entities"),content:F.string().optional().describe("Direct content (skip AI)"),subject:F.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:F.boolean().optional().describe("Create as queued (true) or draft (false)")});class cJA extends a5{constructor(A,Q){super(A,Q,{schema:rqQ,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let B=A.addToQueue??!1,{prompt:$,sourceEntityIds:w,sourceEntityType:D}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(w&&w.length>0){let Z=D??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${w.length} source entities`});let N=(await Promise.all(w.map((P)=>this.context.entityService.getEntity(Z,P)))).filter((P)=>P!=null);if(N.length===0)this.failEarly(`No source entities found for IDs: ${w.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${N.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
3505
3505
 
3506
3506
  ${N.map((P)=>`## ${P.metadata.title}
3507
3507
 
@@ -3570,16 +3570,16 @@ Newsletter-specific guidelines:
3570
3570
  - "Reply and let me know..."
3571
3571
  - "Until next time..."
3572
3572
 
3573
- The goal is to build a relationship with readers through valuable, authentic content.`});ZA();w0();import{jsxDEV as Y7,Fragment as tqQ}from"preact/jsx-dev-runtime";var oqQ=F.object({id:F.string(),subject:F.string(),status:yE,excerpt:F.string(),created:F.string(),sentAt:F.string().optional(),url:F.string()}),sqQ=F.object({newsletters:F.array(oqQ),totalCount:F.number(),pagination:j7.nullable()}),aqQ=({newsletters:A,totalCount:Q,pageTitle:B,pagination:$,baseUrl:w="/newsletters"})=>{let D=B??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return Y7(tqQ,{children:[Y7(iQ,{title:D,description:Y},void 0,!1,void 0,this),Y7("div",{className:"newsletter-list bg-theme",children:Y7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[Y7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:D},void 0,!1,void 0,this),A.length===0?Y7("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):Y7("div",{className:"space-y-4",children:A.map((X)=>Y7(V2,{href:X.url,children:[Y7(K$,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),Y7(Q7,{children:Y7("div",{className:"flex items-center gap-3",children:[Y7(l7,{status:X.status},void 0,!1,void 0,this),Y7("span",{className:"text-sm text-theme-muted",children:g8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&Y7("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&Y7(MY,{currentPage:$.currentPage,totalPages:$.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)},Nv0=E1({name:"newsletter-list",description:"Newsletter list page template",schema:sqQ,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:aqQ}});ZA();w0();import{jsxDEV as Q8,Fragment as BzQ}from"preact/jsx-dev-runtime";var eqQ=F.object({id:F.string(),title:F.string(),url:F.string()}),Lv0=F.object({id:F.string(),subject:F.string(),url:F.string()}),AzQ=F.object({id:F.string(),subject:F.string(),status:yE,content:F.string(),created:F.string(),updated:F.string(),sentAt:F.string().optional(),scheduledFor:F.string().optional(),sourceEntities:F.array(eqQ).optional(),prevNewsletter:Lv0.nullable().optional(),nextNewsletter:Lv0.nullable().optional()}),QzQ=({subject:A,status:Q,content:B,created:$,sentAt:w,scheduledFor:D,sourceEntities:Y,prevNewsletter:X,nextNewsletter:I})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],G=w??$,W=w?"Sent":"Created";return Q8(BzQ,{children:[Q8(iQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),Q8("section",{className:"newsletter-detail-section",children:Q8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:Q8("div",{className:"max-w-3xl mx-auto",children:[Q8(oD,{items:K},void 0,!1,void 0,this),Q8("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),Q8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[Q8(l7,{status:Q},void 0,!1,void 0,this),Q8("span",{children:[W,": ",g8(G,{style:"long"})]},void 0,!0,void 0,this),D&&Q==="queued"&&Q8("span",{children:["Scheduled for: ",g8(D,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&Q8(V2,{variant:"compact",className:"mb-8",children:[Q8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),Q8("ul",{className:"space-y-1",children:Y.map((Z)=>Q8("li",{children:Q8("a",{href:Z.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:Z.title},void 0,!1,void 0,this)},Z.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q8(EY,{markdown:B},void 0,!1,void 0,this),(X??I)&&Q8("nav",{className:"mt-12 pt-8 border-t border-theme",children:Q8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?Q8(V2,{href:X.url,variant:"compact",children:[Q8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),Q8("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):Q8("div",{},void 0,!1,void 0,this),I&&Q8(V2,{href:I.url,variant:"compact",className:"md:text-right",children:[Q8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),Q8("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)]},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)},Ev0=E1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:AzQ,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:QzQ}});var Mv0={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.31",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 DzQ=F.object({});class lJA extends z2{entityType="newsletter";schema=pf;adapter=qv0;constructor(A={}){super("newsletter",Mv0,A,DzQ)}createGenerationHandler(A){return new cJA(this.logger,A)}getTemplates(){return{generation:Vv0,"newsletter-list":Nv0,"newsletter-detail":Ev0}}getDataSources(){return[new uJA(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:()=>wzQ(MKA,{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:$}=Q.payload;if(B!=="newsletter")return{success:!0};try{let w=await A.entityService.getEntity("newsletter",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Newsletter not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=await A.messaging.send("buttondown:send",{entityId:$,subject:w.metadata.subject,content:w.content}),Y=new Date().toISOString(),X=!("noop"in D)&&D.data?D.data.emailId:void 0;return await A.entityService.updateEntity({...w,metadata:{...w.metadata,status:"published",sentAt:Y,buttondownId:X}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:$,sentAt:Y}),this.logger.info(`Published newsletter: ${$}`),{success:!0}}catch(w){let D=L0(w);return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,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(($)=>$.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=F.object({prompt:F.string().optional(),content:F.string().optional()});A.eval.registerHandler("generation",async(B)=>{let $=Q.parse(B),w=$.content?`Create an engaging newsletter based on this content:
3573
+ The goal is to build a relationship with readers through valuable, authentic content.`});ZA();w0();import{jsxDEV as Y7,Fragment as tqQ}from"preact/jsx-dev-runtime";var oqQ=F.object({id:F.string(),subject:F.string(),status:yE,excerpt:F.string(),created:F.string(),sentAt:F.string().optional(),url:F.string()}),sqQ=F.object({newsletters:F.array(oqQ),totalCount:F.number(),pagination:j7.nullable()}),aqQ=({newsletters:A,totalCount:Q,pageTitle:B,pagination:$,baseUrl:w="/newsletters"})=>{let D=B??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return Y7(tqQ,{children:[Y7(iQ,{title:D,description:Y},void 0,!1,void 0,this),Y7("div",{className:"newsletter-list bg-theme",children:Y7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[Y7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:D},void 0,!1,void 0,this),A.length===0?Y7("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):Y7("div",{className:"space-y-4",children:A.map((X)=>Y7(V2,{href:X.url,children:[Y7(K$,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),Y7(Q7,{children:Y7("div",{className:"flex items-center gap-3",children:[Y7(l7,{status:X.status},void 0,!1,void 0,this),Y7("span",{className:"text-sm text-theme-muted",children:g8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&Y7("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&Y7(MY,{currentPage:$.currentPage,totalPages:$.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)},Nv0=E1({name:"newsletter-list",description:"Newsletter list page template",schema:sqQ,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:aqQ}});ZA();w0();import{jsxDEV as Q8,Fragment as BzQ}from"preact/jsx-dev-runtime";var eqQ=F.object({id:F.string(),title:F.string(),url:F.string()}),Lv0=F.object({id:F.string(),subject:F.string(),url:F.string()}),AzQ=F.object({id:F.string(),subject:F.string(),status:yE,content:F.string(),created:F.string(),updated:F.string(),sentAt:F.string().optional(),scheduledFor:F.string().optional(),sourceEntities:F.array(eqQ).optional(),prevNewsletter:Lv0.nullable().optional(),nextNewsletter:Lv0.nullable().optional()}),QzQ=({subject:A,status:Q,content:B,created:$,sentAt:w,scheduledFor:D,sourceEntities:Y,prevNewsletter:X,nextNewsletter:I})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],G=w??$,W=w?"Sent":"Created";return Q8(BzQ,{children:[Q8(iQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),Q8("section",{className:"newsletter-detail-section",children:Q8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:Q8("div",{className:"max-w-3xl mx-auto",children:[Q8(oD,{items:K},void 0,!1,void 0,this),Q8("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),Q8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[Q8(l7,{status:Q},void 0,!1,void 0,this),Q8("span",{children:[W,": ",g8(G,{style:"long"})]},void 0,!0,void 0,this),D&&Q==="queued"&&Q8("span",{children:["Scheduled for: ",g8(D,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&Q8(V2,{variant:"compact",className:"mb-8",children:[Q8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),Q8("ul",{className:"space-y-1",children:Y.map((Z)=>Q8("li",{children:Q8("a",{href:Z.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:Z.title},void 0,!1,void 0,this)},Z.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q8(EY,{markdown:B},void 0,!1,void 0,this),(X??I)&&Q8("nav",{className:"mt-12 pt-8 border-t border-theme",children:Q8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?Q8(V2,{href:X.url,variant:"compact",children:[Q8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),Q8("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):Q8("div",{},void 0,!1,void 0,this),I&&Q8(V2,{href:I.url,variant:"compact",className:"md:text-right",children:[Q8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),Q8("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)]},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)},Ev0=E1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:AzQ,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:QzQ}});var Mv0={name:"@brains/newsletter-entity",private:!0,version:"0.2.0-alpha.32",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 DzQ=F.object({});class lJA extends z2{entityType="newsletter";schema=pf;adapter=qv0;constructor(A={}){super("newsletter",Mv0,A,DzQ)}createGenerationHandler(A){return new cJA(this.logger,A)}getTemplates(){return{generation:Vv0,"newsletter-list":Nv0,"newsletter-detail":Ev0}}getDataSources(){return[new uJA(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:()=>wzQ(MKA,{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:$}=Q.payload;if(B!=="newsletter")return{success:!0};try{let w=await A.entityService.getEntity("newsletter",$);if(!w)return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,error:`Newsletter not found: ${$}`}),{success:!0};if(w.metadata.status==="published")return{success:!0};let D=await A.messaging.send("buttondown:send",{entityId:$,subject:w.metadata.subject,content:w.content}),Y=new Date().toISOString(),X=!("noop"in D)&&D.data?D.data.emailId:void 0;return await A.entityService.updateEntity({...w,metadata:{...w.metadata,status:"published",sentAt:Y,buttondownId:X}}),await A.messaging.send("publish:report:success",{entityType:B,entityId:$,sentAt:Y}),this.logger.info(`Published newsletter: ${$}`),{success:!0}}catch(w){let D=L0(w);return await A.messaging.send("publish:report:failure",{entityType:B,entityId:$,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(($)=>$.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=F.object({prompt:F.string().optional(),content:F.string().optional()});A.eval.registerHandler("generation",async(B)=>{let $=Q.parse(B),w=$.content?`Create an engaging newsletter based on this content:
3574
3574
 
3575
- ${$.content}`:$.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:w,templateName:"newsletter:generation"})})}}function pJA(A={}){return new lJA(A)}w0();ZA();class mE{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 $=await fetch(B,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!$.ok){let w=await $.json().catch(()=>({})),D=w.detail??w.message??`HTTP ${$.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:$.status,error:D}),Error(`Buttondown API error: ${D}`)}return $.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 $=B.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:$?.[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(),$=B?`/subscribers?${B}`:"/subscribers";return this.request($)}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}}}w0();ZA();var YzQ=F.object({email:F.string().email().describe("Email address to subscribe"),name:F.string().optional().describe("Subscriber name (optional)"),tags:F.array(F.string()).optional().describe("Tags to apply to subscriber (optional)")}),XzQ=F.object({email:F.string().email().describe("Email address to unsubscribe")}),IzQ=F.object({type:F.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:F.number().optional().describe("Maximum number of results")});function Cv0(A,Q,B){let $=new mE(Q,B);return[g2(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",YzQ,async(w)=>{try{let D=await $.createSubscriber({email:w.email,...w.name&&{name:w.name},...w.tags&&{tags:w.tags}}),Y=D.subscriber_type==="already_subscribed";return E9({subscriberId:D.id,email:D.email,status:D.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${w.email} is already subscribed`:`Subscribed ${w.email} successfully`)}catch(D){return z5(L0(D))}}),g2(A,"unsubscribe","Unsubscribe an email address from the newsletter.",XzQ,async(w)=>{try{return await $.unsubscribe(w.email),E9({email:w.email},`Unsubscribed ${w.email} successfully`)}catch(D){return z5(L0(D))}}),g2(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",IzQ,async(w)=>{try{let D=await $.listSubscribers({...w.type&&{type:w.type},...w.limit&&{limit:w.limit}});return E9({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 z5(L0(D))}})]}ZA();async function Ov0(A,Q,B,$){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let w=await B.getEntity("post",A.entityId);if(!w)return{success:!1,error:`Post ${A.entityId} not found`};$.info("Auto-sending newsletter for published post",{postId:w.id,title:w.metadata.title});try{let D=await Q.createEmail({subject:w.metadata.title,body:w.content,status:"about_to_send"});return $.info("Newsletter sent for post",{postId:w.id,emailId:D.id}),{success:!0,emailId:D.id}}catch(D){let Y=L0(D);return $.error("Failed to send newsletter for post",{postId:w.id,error:Y}),{success:!1,error:Y}}}var jv0={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.31",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 HzQ=F.object({apiKey:F.string().optional().describe("Buttondown API key"),doubleOptIn:F.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:F.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class dJA extends f8{constructor(A={}){super("buttondown",jv0,A,HzQ)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new mE({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($){return this.logger.error("Buttondown send failed",{error:L0($)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(B)=>{return await Ov0(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 Cv0(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 iJA(A={}){return new dJA(A)}var UzQ=F.object({apiKey:F.string().optional().describe("Buttondown API key"),doubleOptIn:F.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:F.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function Rv0(A={}){let Q=UzQ.parse(A);return[pJA({}),iJA({...Q.apiKey!==void 0&&{apiKey:Q.apiKey},...Q.doubleOptIn!==void 0&&{doubleOptIn:Q.doubleOptIn},...Q.autoSendOnPublish!==void 0&&{autoSendOnPublish:Q.autoSendOnPublish}})]}w0();ZA();import{existsSync as MzQ,mkdirSync as CzQ,writeFileSync as OzQ}from"fs";import{join as pH}from"path";ZA();var rJA=F.object({baseFolder:F.string().default("_obsidian")});ZA();function GzQ(A){let Q=A,B=!0,$=void 0,w=!1,D=!0;while(D){if(D=!1,Q instanceof F.ZodOptional)B=!1,Q=Q._def.innerType,D=!0;if(Q instanceof F.ZodDefault)B=!1,w=!0,$=Q._def.defaultValue(),Q=Q._def.innerType,D=!0;if(Q instanceof F.ZodNullable)B=!1,Q=Q._def.innerType,D=!0}let Y={inner:Q,required:B};if(w)Y.defaultValue=$;return Y}function JzQ(A){if(A instanceof F.ZodEnum)return{type:"enum",enumValues:A._def.values};if(A instanceof F.ZodLiteral)return{type:"string",defaultValue:A._def.value};if(A instanceof F.ZodString)return{type:"string"};if(A instanceof F.ZodNumber)return{type:"number"};if(A instanceof F.ZodBoolean)return{type:"boolean"};if(A instanceof F.ZodArray)return{type:"array"};if(A instanceof F.ZodDate)return{type:"date"};if(A instanceof F.ZodPipeline){if(A._def.out instanceof F.ZodDate)return{type:"date"}}return{type:"unknown"}}function Pv0(A){let Q=A.shape,B=[];for(let[$,w]of Object.entries(Q)){let{inner:D,required:Y,defaultValue:X}=GzQ(w),I=JzQ(D),K={name:$,type:I.type,required:Y},G=X!==void 0?X:I.defaultValue;if(G!==void 0)K.defaultValue=G;if(I.enumValues)K.enumValues=I.enumValues;B.push(K)}return B}function WzQ(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 _v0(A,Q,B=""){let $=["---"];for(let w of Q){let D=WzQ(w,A);if(D==="")$.push(`${w.name}:`);else $.push(`${w.name}: ${D}`)}if($.push("---"),$.push(""),B)$.push(B);else $.push("<!-- Write your content here -->"),$.push("");return $.join(`
3575
+ ${$.content}`:$.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:w,templateName:"newsletter:generation"})})}}function pJA(A={}){return new lJA(A)}w0();ZA();class mE{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 $=await fetch(B,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!$.ok){let w=await $.json().catch(()=>({})),D=w.detail??w.message??`HTTP ${$.status}`;throw this.logger.error("Buttondown API error",{endpoint:A,status:$.status,error:D}),Error(`Buttondown API error: ${D}`)}return $.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 $=B.message.match(/id=([a-f0-9-]+)/);return this.logger.info("Subscriber already exists",{email:A.email}),{id:$?.[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(),$=B?`/subscribers?${B}`:"/subscribers";return this.request($)}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}}}w0();ZA();var YzQ=F.object({email:F.string().email().describe("Email address to subscribe"),name:F.string().optional().describe("Subscriber name (optional)"),tags:F.array(F.string()).optional().describe("Tags to apply to subscriber (optional)")}),XzQ=F.object({email:F.string().email().describe("Email address to unsubscribe")}),IzQ=F.object({type:F.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:F.number().optional().describe("Maximum number of results")});function Cv0(A,Q,B){let $=new mE(Q,B);return[g2(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",YzQ,async(w)=>{try{let D=await $.createSubscriber({email:w.email,...w.name&&{name:w.name},...w.tags&&{tags:w.tags}}),Y=D.subscriber_type==="already_subscribed";return E9({subscriberId:D.id,email:D.email,status:D.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${w.email} is already subscribed`:`Subscribed ${w.email} successfully`)}catch(D){return z5(L0(D))}}),g2(A,"unsubscribe","Unsubscribe an email address from the newsletter.",XzQ,async(w)=>{try{return await $.unsubscribe(w.email),E9({email:w.email},`Unsubscribed ${w.email} successfully`)}catch(D){return z5(L0(D))}}),g2(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",IzQ,async(w)=>{try{let D=await $.listSubscribers({...w.type&&{type:w.type},...w.limit&&{limit:w.limit}});return E9({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 z5(L0(D))}})]}ZA();async function Ov0(A,Q,B,$){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let w=await B.getEntity("post",A.entityId);if(!w)return{success:!1,error:`Post ${A.entityId} not found`};$.info("Auto-sending newsletter for published post",{postId:w.id,title:w.metadata.title});try{let D=await Q.createEmail({subject:w.metadata.title,body:w.content,status:"about_to_send"});return $.info("Newsletter sent for post",{postId:w.id,emailId:D.id}),{success:!0,emailId:D.id}}catch(D){let Y=L0(D);return $.error("Failed to send newsletter for post",{postId:w.id,error:Y}),{success:!1,error:Y}}}var jv0={name:"@brains/buttondown",private:!0,version:"0.2.0-alpha.32",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 HzQ=F.object({apiKey:F.string().optional().describe("Buttondown API key"),doubleOptIn:F.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:F.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class dJA extends f8{constructor(A={}){super("buttondown",jv0,A,HzQ)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new mE({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($){return this.logger.error("Buttondown send failed",{error:L0($)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(B)=>{return await Ov0(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 Cv0(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 iJA(A={}){return new dJA(A)}var UzQ=F.object({apiKey:F.string().optional().describe("Buttondown API key"),doubleOptIn:F.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:F.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function Rv0(A={}){let Q=UzQ.parse(A);return[pJA({}),iJA({...Q.apiKey!==void 0&&{apiKey:Q.apiKey},...Q.doubleOptIn!==void 0&&{doubleOptIn:Q.doubleOptIn},...Q.autoSendOnPublish!==void 0&&{autoSendOnPublish:Q.autoSendOnPublish}})]}w0();ZA();import{existsSync as MzQ,mkdirSync as CzQ,writeFileSync as OzQ}from"fs";import{join as pH}from"path";ZA();var rJA=F.object({baseFolder:F.string().default("_obsidian")});ZA();function GzQ(A){let Q=A,B=!0,$=void 0,w=!1,D=!0;while(D){if(D=!1,Q instanceof F.ZodOptional)B=!1,Q=Q._def.innerType,D=!0;if(Q instanceof F.ZodDefault)B=!1,w=!0,$=Q._def.defaultValue(),Q=Q._def.innerType,D=!0;if(Q instanceof F.ZodNullable)B=!1,Q=Q._def.innerType,D=!0}let Y={inner:Q,required:B};if(w)Y.defaultValue=$;return Y}function JzQ(A){if(A instanceof F.ZodEnum)return{type:"enum",enumValues:A._def.values};if(A instanceof F.ZodLiteral)return{type:"string",defaultValue:A._def.value};if(A instanceof F.ZodString)return{type:"string"};if(A instanceof F.ZodNumber)return{type:"number"};if(A instanceof F.ZodBoolean)return{type:"boolean"};if(A instanceof F.ZodArray)return{type:"array"};if(A instanceof F.ZodDate)return{type:"date"};if(A instanceof F.ZodPipeline){if(A._def.out instanceof F.ZodDate)return{type:"date"}}return{type:"unknown"}}function Pv0(A){let Q=A.shape,B=[];for(let[$,w]of Object.entries(Q)){let{inner:D,required:Y,defaultValue:X}=GzQ(w),I=JzQ(D),K={name:$,type:I.type,required:Y},G=X!==void 0?X:I.defaultValue;if(G!==void 0)K.defaultValue=G;if(I.enumValues)K.enumValues=I.enumValues;B.push(K)}return B}function WzQ(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 _v0(A,Q,B=""){let $=["---"];for(let w of Q){let D=WzQ(w,A);if(D==="")$.push(`${w.name}:`);else $.push(`${w.name}: ${D}`)}if($.push("---"),$.push(""),B)$.push(B);else $.push("<!-- Write your content here -->"),$.push("");return $.join(`
3576
3576
  `)}ZA();var ZzQ={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function FzQ(A){let Q={name:A.name,id:A.name,type:ZzQ[A.type]};if(A.type==="enum"&&A.enumValues){let B={};A.enumValues.forEach(($,w)=>{B[String(w)]=$}),Q.options=B}return Q}function kv0(A,Q){let B={filesPaths:A,fields:Q.map(FzQ)};return`---
3577
3577
  ${ND(B)}---
3578
- `}ZA();var qzQ=new Set(["entityType"]),zzQ={base:"Notes"},VzQ=new Set(["base"]);function NzQ(A){let Q=["file.name"];for(let B of A)if(!qzQ.has(B.name))Q.push(B.name);return Q}function LzQ(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function fv0(A,Q){let B=zzQ[A]??mx(A),$=LzQ(Q),w=NzQ(Q),D=[{type:"table",name:`All ${B}`,order:w}];if($)D.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:w});let X={filters:{and:[VzQ.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:D};return{filename:`${B}.base`,content:ND(X),hasStatus:$}}function bv0(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$}")`),B={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return ND(B)}function Tv0(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$.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 ND(B)}var xv0={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.31",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 jzQ={mkdir:CzQ,writeFile:OzQ,existsFile:MzQ},RzQ=F.object({entityTypes:F.array(F.string()).optional().describe("Entity types to generate templates for (default: all)")});class nJA extends f8{deps;constructor(A={},Q={}){super("obsidian-vault",xv0,A,rJA);this.deps={...jzQ,...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[g2(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",RzQ,async(Q)=>{return this.sync(A,Q.entityTypes)})]}async sync(A,Q){try{let B=A.entityService.getEntityTypes(),$=Q?B.filter((L)=>Q.includes(L)):B,w=pH(A.dataDir,this.config.baseFolder),D=pH(w,"templates"),Y=pH(w,"fileClasses"),X=pH(w,"bases");this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(X,{recursive:!0});let I=[],K=[],G=[],W=[],Z=[],q=[];for(let L of $){let _=A.entities.getEffectiveFrontmatterSchema(L);if(!_){this.logger.debug(`Skipping ${L}: no frontmatter schema`),K.push(L);continue}let T=Pv0(_),P=A.entities.getAdapter(L),r=P?.isSingleton===!0,n=kv0(L,T);if(this.deps.writeFile(pH(Y,`${L}.md`),n),G.push(L),r){Z.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let g=P?.getBodyTemplate()??"",x=_v0(L,T,g);this.deps.writeFile(pH(D,`${L}.md`),x),I.push(L);let S=fv0(L,T),h=pH(X,S.filename);if(!this.deps.existsFile(h))this.deps.writeFile(h,S.content),W.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)q.push({entityType:L,fields:T});this.logger.debug(`Generated template + fileClass: ${L}`)}let N=bv0(Z);if(N){let L=pH(X,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,N),W.push("Settings"),this.logger.debug("Generated Settings.base")}let M=Tv0(q);if(M){let L=pH(X,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,M),W.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${I.length} templates, ${G.length} fileClasses, ${W.length} bases (${K.length} skipped)`),E9({generated:I,skipped:K,fileClasses:G,bases:W})}catch(B){return this.logger.error("Failed to sync",{error:B}),z5(B instanceof Error?B.message:"Unknown error")}}}function oJA(A,Q){return new nJA(A,Q)}w0();ZA();w0();var sJA=F.enum(["new","planned","in-progress","done","declined"]),aJA=F.enum(["low","medium","high","critical"]),df=F.object({title:F.string(),status:sJA,priority:aJA.default("medium"),requested:F.number().int().default(1),tags:F.array(F.string()).default([]),declinedReason:F.string().optional()}),vv0=F.object({title:F.string(),status:sJA,priority:aJA,requested:F.number().int(),slug:F.string()}),rf=FQ.extend({entityType:F.literal("wish"),metadata:vv0}),tJA=F.object({});w0();ZA();class nf extends _Q{constructor(){super({entityType:"wish",schema:rf,frontmatterSchema:df})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,df);return{frontmatter:df.parse(Q),description:this.extractBody(A).trim()}}toMarkdown(A){return A.content}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),B=a1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:B}}}}var eJA=new nf;ZA();ZA();async function Sv0(A,Q){let B=`${Q.title}: ${Q.description}`,w=(await A.search(B,{types:["wish"],limit:1}))[0];if(w&&w.score>=A.similarityThreshold)return w.entity;let D=a1(Q.title);return A.getEntity("wish",D)}class ji{logger;context;adapter=new nf;constructor(A,Q){this.logger=A;this.context=Q}async process(A,Q,B){let $=A.title??A.prompt??"Untitled wish",w=A.content??A.prompt??"",D=await Sv0({search:(K,G)=>this.context.entityService.search(K,G),getEntity:(K,G)=>this.context.entityService.getEntity(K,G),similarityThreshold:0.85},{title:$,description:w});if(D){let{frontmatter:K,description:G}=this.adapter.parseWishContent(D.content),W=K.requested+1,Z=this.adapter.createWishContent({...K,requested:W},G);return await this.context.entityService.updateEntity({...D,content:Z,metadata:{...D.metadata,requested:W}}),this.logger.info("Incremented wish request count",{id:D.id,requested:W}),{success:!0,entityId:D.id,existed:!0,requested:W}}let Y=a1($),X=A.options?.priority??"medium",I=this.adapter.createWishContent({title:$,status:"new",priority:X,requested:1,tags:A.options?.tags??[]},w);return await this.context.entityService.createEntity({id:Y,entityType:"wish",content:I,metadata:{title:$,status:"new",priority:X,requested:1,slug:Y}}),this.logger.info("Created new wish",{id:Y,title:$}),{success:!0,entityId:Y,existed:!1,requested:1}}}var hv0={critical:0,high:1,medium:2,low:3};function gv0(A){A.sort((Q,B)=>{let $=B.metadata.requested-Q.metadata.requested;if($!==0)return $;return hv0[Q.metadata.priority]-hv0[B.metadata.priority]})}var yv0={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.31",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 mv0 extends z2{entityType=eJA.entityType;schema=rf;adapter=eJA;constructor(A={}){super("wishlist",yv0,A,tJA)}async interceptCreate(A,Q,B){let $=await new ji(this.logger,B).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!$.success)return{kind:"handled",result:{success:!1,error:$.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...$.entityId?{entityId:$.entityId}:{},status:$.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 gv0(B),{items:B.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}),{success:!0}});let Q=new ji(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."}}function _zQ(A={}){return new mv0(A)}var Ri=_zQ;w0();ZA();w0();var of=F.object({title:F.string(),target:F.string()}),uv0=F.object({title:F.string(),target:F.string(),slug:F.string().optional()}),sf=FQ.extend({entityType:F.literal("prompt"),metadata:uv0});w0();ZA();class AWA extends _Q{constructor(){super({entityType:"prompt",schema:sf,frontmatterSchema:of})}toMarkdown(A){let Q=this.extractBody(A.content),B=this.parseFrontMatter(A.content,of);return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,of),B=a1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:B}}}}var Pi=new AWA;var cv0={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.31",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 QWA extends z2{entityType=Pi.entityType;schema=sf;adapter=Pi;constructor(){super("prompt",cv0,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function a3(){return new QWA}w0();ZA();class _i{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 $=await this.fetchFn(B.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!$.ok)throw Error(`Unsplash API error: ${$.status} ${$.statusText}`);let w=await $.json();return{photos:w.results.map(fzQ),total:w.total,totalPages:w.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function fzQ(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}}ZA();var lv0={query:F.string().describe("Search terms for stock photos"),perPage:F.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:F.number().min(1).default(1).describe("Page number")},pv0={photoId:F.string().describe("Photo ID from search results"),downloadLocation:F.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:F.string().describe("Photographer name for attribution"),photographerUrl:F.string().url().describe("Photographer profile URL for attribution"),sourceUrl:F.string().url().describe("Photo page URL on provider"),imageUrl:F.string().url().describe("Image URL to download"),title:F.string().optional().describe("Image entity title"),alt:F.string().optional().describe("Alt text for the image"),targetEntityType:F.string().optional().describe("Entity type to set cover image on"),targetEntityId:F.string().optional().describe("Entity ID to set cover image on")};function iv0(A,Q){return[bzQ(A,Q),TzQ(A,Q)]}function bzQ(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:lv0,handler:async(B)=>{let $=F.object(lv0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos($.data.query,{page:$.data.page,perPage:$.data.perPage})}}catch(w){return{success:!1,error:w instanceof Error?w.message:"Search failed"}}}}}function TzQ(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:pv0,handler:async(B)=>{let $=F.object(pv0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:w,downloadLocation:D,photographerName:Y,photographerUrl:X,sourceUrl:I,imageUrl:K,title:G,alt:W,targetEntityType:Z,targetEntityId:q}=$.data,N={photographerName:Y,photographerUrl:X,sourceUrl:I},M=await Q.entityService.listEntities("image",{limit:1,filter:{metadata:{sourceUrl:K}}});if(M[0]){let g={imageEntityId:M[0].id,alreadyExisted:!0,attribution:N};if(Z&&q)await dv0(Q.entityService,Z,q,M[0].id),g.coverSet=!0;return{success:!0,data:g}}Q.provider.triggerDownload(D).catch(()=>{});let L;try{L=await Q.fetchImage(K)}catch(g){return{success:!1,error:g instanceof Error?g.message:"Image download failed"}}let _=G??`Stock photo ${w}`,T=yG.createImageEntity({dataUrl:L,title:_,alt:W??_}),P={id:w,...T,metadata:{...T.metadata,sourceUrl:K}},{entityId:r}=await Q.entityService.createEntity(P),n={imageEntityId:r,alreadyExisted:!1,attribution:N};if(Z&&q)await dv0(Q.entityService,Z,q,r),n.coverSet=!0;return{success:!0,data:n}}}}async function dv0(A,Q,B,$){let w=await A.getEntity(Q,B);if(!w)return;await A.updateEntity({...w,metadata:{...w.metadata,coverImageId:$}})}ZA();var rv0={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.31",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 vzQ=F.object({provider:F.enum(["unsplash"]).default("unsplash"),apiKey:F.string().optional().describe("Stock photo provider API key")});class BWA extends f8{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",rv0,A,vzQ);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=new _i(this.config.apiKey,this.deps.fetch??globalThis.fetch);return this.cachedTools=iv0(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??E7}),this.cachedTools}}function $WA(A={},Q={}){return new BWA(A,Q)}ZA();w0();ZA();w0();var nv0=F.object({name:F.string(),description:F.string(),tags:F.array(F.string())}),eJ=n4.pick({name:!0,kind:!0,organization:!0}).extend({brainName:F.string().optional().describe("Name of the brain"),url:F.string().url().describe("Brain endpoint URL"),did:F.string().optional().describe("Decentralized identifier (public)"),status:F.enum(["active","archived"]).describe("Active or archived"),discoveredAt:F.string().datetime().describe("When this agent was first discovered"),discoveredVia:F.enum(["atproto","manual"]).describe("How this agent was discovered")}),ov0=eJ.pick({name:!0,url:!0,status:!0}).extend({slug:F.string()}),uE=FQ.extend({entityType:F.literal("agent"),metadata:ov0}),af=uE.extend({frontmatter:eJ,about:F.string(),skills:F.array(nv0),notes:F.string()}),cE=af.extend({url:F.string().optional(),typeLabel:F.string().optional()}),SzQ=af.extend({url:F.string(),typeLabel:F.string()});w0();ZA();var hzQ=F.object({about:F.string(),skills:F.array(F.object({name:F.string(),description:F.string(),tags:F.array(F.string())})),notes:F.string()});function gzQ(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((B)=>{let $=B.tags.length>0?` [${B.tags.join(", ")}]`:"";return`- ${B.name}: ${B.description}${$}`}).join(`
3578
+ `}ZA();var qzQ=new Set(["entityType"]),zzQ={base:"Notes"},VzQ=new Set(["base"]);function NzQ(A){let Q=["file.name"];for(let B of A)if(!qzQ.has(B.name))Q.push(B.name);return Q}function LzQ(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function fv0(A,Q){let B=zzQ[A]??mx(A),$=LzQ(Q),w=NzQ(Q),D=[{type:"table",name:`All ${B}`,order:w}];if($)D.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:w});let X={filters:{and:[VzQ.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:D};return{filename:`${B}.base`,content:ND(X),hasStatus:$}}function bv0(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$}")`),B={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return ND(B)}function Tv0(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$.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 ND(B)}var xv0={name:"@brains/obsidian-vault",private:!0,version:"0.2.0-alpha.32",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 jzQ={mkdir:CzQ,writeFile:OzQ,existsFile:MzQ},RzQ=F.object({entityTypes:F.array(F.string()).optional().describe("Entity types to generate templates for (default: all)")});class nJA extends f8{deps;constructor(A={},Q={}){super("obsidian-vault",xv0,A,rJA);this.deps={...jzQ,...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[g2(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",RzQ,async(Q)=>{return this.sync(A,Q.entityTypes)})]}async sync(A,Q){try{let B=A.entityService.getEntityTypes(),$=Q?B.filter((L)=>Q.includes(L)):B,w=pH(A.dataDir,this.config.baseFolder),D=pH(w,"templates"),Y=pH(w,"fileClasses"),X=pH(w,"bases");this.deps.mkdir(D,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(X,{recursive:!0});let I=[],K=[],G=[],W=[],Z=[],q=[];for(let L of $){let _=A.entities.getEffectiveFrontmatterSchema(L);if(!_){this.logger.debug(`Skipping ${L}: no frontmatter schema`),K.push(L);continue}let T=Pv0(_),P=A.entities.getAdapter(L),r=P?.isSingleton===!0,n=kv0(L,T);if(this.deps.writeFile(pH(Y,`${L}.md`),n),G.push(L),r){Z.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let g=P?.getBodyTemplate()??"",x=_v0(L,T,g);this.deps.writeFile(pH(D,`${L}.md`),x),I.push(L);let S=fv0(L,T),h=pH(X,S.filename);if(!this.deps.existsFile(h))this.deps.writeFile(h,S.content),W.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)q.push({entityType:L,fields:T});this.logger.debug(`Generated template + fileClass: ${L}`)}let N=bv0(Z);if(N){let L=pH(X,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,N),W.push("Settings"),this.logger.debug("Generated Settings.base")}let M=Tv0(q);if(M){let L=pH(X,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,M),W.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${I.length} templates, ${G.length} fileClasses, ${W.length} bases (${K.length} skipped)`),E9({generated:I,skipped:K,fileClasses:G,bases:W})}catch(B){return this.logger.error("Failed to sync",{error:B}),z5(B instanceof Error?B.message:"Unknown error")}}}function oJA(A,Q){return new nJA(A,Q)}w0();ZA();w0();var sJA=F.enum(["new","planned","in-progress","done","declined"]),aJA=F.enum(["low","medium","high","critical"]),df=F.object({title:F.string(),status:sJA,priority:aJA.default("medium"),requested:F.number().int().default(1),tags:F.array(F.string()).default([]),declinedReason:F.string().optional()}),vv0=F.object({title:F.string(),status:sJA,priority:aJA,requested:F.number().int(),slug:F.string()}),rf=FQ.extend({entityType:F.literal("wish"),metadata:vv0}),tJA=F.object({});w0();ZA();class nf extends _Q{constructor(){super({entityType:"wish",schema:rf,frontmatterSchema:df})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,df);return{frontmatter:df.parse(Q),description:this.extractBody(A).trim()}}toMarkdown(A){return A.content}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),B=a1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:B}}}}var eJA=new nf;ZA();ZA();async function Sv0(A,Q){let B=`${Q.title}: ${Q.description}`,w=(await A.search(B,{types:["wish"],limit:1}))[0];if(w&&w.score>=A.similarityThreshold)return w.entity;let D=a1(Q.title);return A.getEntity("wish",D)}class ji{logger;context;adapter=new nf;constructor(A,Q){this.logger=A;this.context=Q}async process(A,Q,B){let $=A.title??A.prompt??"Untitled wish",w=A.content??A.prompt??"",D=await Sv0({search:(K,G)=>this.context.entityService.search(K,G),getEntity:(K,G)=>this.context.entityService.getEntity(K,G),similarityThreshold:0.85},{title:$,description:w});if(D){let{frontmatter:K,description:G}=this.adapter.parseWishContent(D.content),W=K.requested+1,Z=this.adapter.createWishContent({...K,requested:W},G);return await this.context.entityService.updateEntity({...D,content:Z,metadata:{...D.metadata,requested:W}}),this.logger.info("Incremented wish request count",{id:D.id,requested:W}),{success:!0,entityId:D.id,existed:!0,requested:W}}let Y=a1($),X=A.options?.priority??"medium",I=this.adapter.createWishContent({title:$,status:"new",priority:X,requested:1,tags:A.options?.tags??[]},w);return await this.context.entityService.createEntity({id:Y,entityType:"wish",content:I,metadata:{title:$,status:"new",priority:X,requested:1,slug:Y}}),this.logger.info("Created new wish",{id:Y,title:$}),{success:!0,entityId:Y,existed:!1,requested:1}}}var hv0={critical:0,high:1,medium:2,low:3};function gv0(A){A.sort((Q,B)=>{let $=B.metadata.requested-Q.metadata.requested;if($!==0)return $;return hv0[Q.metadata.priority]-hv0[B.metadata.priority]})}var yv0={name:"@brains/wishlist",private:!0,version:"0.2.0-alpha.32",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 mv0 extends z2{entityType=eJA.entityType;schema=rf;adapter=eJA;constructor(A={}){super("wishlist",yv0,A,tJA)}async interceptCreate(A,Q,B){let $=await new ji(this.logger,B).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!$.success)return{kind:"handled",result:{success:!1,error:$.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...$.entityId?{entityId:$.entityId}:{},status:$.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 gv0(B),{items:B.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}),{success:!0}});let Q=new ji(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."}}function _zQ(A={}){return new mv0(A)}var Ri=_zQ;w0();ZA();w0();var of=F.object({title:F.string(),target:F.string()}),uv0=F.object({title:F.string(),target:F.string(),slug:F.string().optional()}),sf=FQ.extend({entityType:F.literal("prompt"),metadata:uv0});w0();ZA();class AWA extends _Q{constructor(){super({entityType:"prompt",schema:sf,frontmatterSchema:of})}toMarkdown(A){let Q=this.extractBody(A.content),B=this.parseFrontMatter(A.content,of);return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,of),B=a1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:B}}}}var Pi=new AWA;var cv0={name:"@brains/prompt",private:!0,version:"0.2.0-alpha.32",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 QWA extends z2{entityType=Pi.entityType;schema=sf;adapter=Pi;constructor(){super("prompt",cv0,{},void 0)}getEntityTypeConfig(){return{embeddable:!1}}}function a3(){return new QWA}w0();ZA();class _i{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 $=await this.fetchFn(B.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!$.ok)throw Error(`Unsplash API error: ${$.status} ${$.statusText}`);let w=await $.json();return{photos:w.results.map(fzQ),total:w.total,totalPages:w.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}function fzQ(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}}ZA();var lv0={query:F.string().describe("Search terms for stock photos"),perPage:F.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:F.number().min(1).default(1).describe("Page number")},pv0={photoId:F.string().describe("Photo ID from search results"),downloadLocation:F.string().url().describe("Download tracking URL (required by provider ToS)"),photographerName:F.string().describe("Photographer name for attribution"),photographerUrl:F.string().url().describe("Photographer profile URL for attribution"),sourceUrl:F.string().url().describe("Photo page URL on provider"),imageUrl:F.string().url().describe("Image URL to download"),title:F.string().optional().describe("Image entity title"),alt:F.string().optional().describe("Alt text for the image"),targetEntityType:F.string().optional().describe("Entity type to set cover image on"),targetEntityId:F.string().optional().describe("Entity ID to set cover image on")};function iv0(A,Q){return[bzQ(A,Q),TzQ(A,Q)]}function bzQ(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:lv0,handler:async(B)=>{let $=F.object(lv0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos($.data.query,{page:$.data.page,perPage:$.data.perPage})}}catch(w){return{success:!1,error:w instanceof Error?w.message:"Search failed"}}}}}function TzQ(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:pv0,handler:async(B)=>{let $=F.object(pv0).safeParse(B);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:w,downloadLocation:D,photographerName:Y,photographerUrl:X,sourceUrl:I,imageUrl:K,title:G,alt:W,targetEntityType:Z,targetEntityId:q}=$.data,N={photographerName:Y,photographerUrl:X,sourceUrl:I},M=await Q.entityService.listEntities("image",{limit:1,filter:{metadata:{sourceUrl:K}}});if(M[0]){let g={imageEntityId:M[0].id,alreadyExisted:!0,attribution:N};if(Z&&q)await dv0(Q.entityService,Z,q,M[0].id),g.coverSet=!0;return{success:!0,data:g}}Q.provider.triggerDownload(D).catch(()=>{});let L;try{L=await Q.fetchImage(K)}catch(g){return{success:!1,error:g instanceof Error?g.message:"Image download failed"}}let _=G??`Stock photo ${w}`,T=yG.createImageEntity({dataUrl:L,title:_,alt:W??_}),P={id:w,...T,metadata:{...T.metadata,sourceUrl:K}},{entityId:r}=await Q.entityService.createEntity(P),n={imageEntityId:r,alreadyExisted:!1,attribution:N};if(Z&&q)await dv0(Q.entityService,Z,q,r),n.coverSet=!0;return{success:!0,data:n}}}}async function dv0(A,Q,B,$){let w=await A.getEntity(Q,B);if(!w)return;await A.updateEntity({...w,metadata:{...w.metadata,coverImageId:$}})}ZA();var rv0={name:"@brains/stock-photo",private:!0,version:"0.2.0-alpha.32",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 vzQ=F.object({provider:F.enum(["unsplash"]).default("unsplash"),apiKey:F.string().optional().describe("Stock photo provider API key")});class BWA extends f8{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",rv0,A,vzQ);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=new _i(this.config.apiKey,this.deps.fetch??globalThis.fetch);return this.cachedTools=iv0(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??E7}),this.cachedTools}}function $WA(A={},Q={}){return new BWA(A,Q)}ZA();w0();ZA();w0();var nv0=F.object({name:F.string(),description:F.string(),tags:F.array(F.string())}),eJ=n4.pick({name:!0,kind:!0,organization:!0}).extend({brainName:F.string().optional().describe("Name of the brain"),url:F.string().url().describe("Brain endpoint URL"),did:F.string().optional().describe("Decentralized identifier (public)"),status:F.enum(["active","archived"]).describe("Active or archived"),discoveredAt:F.string().datetime().describe("When this agent was first discovered"),discoveredVia:F.enum(["atproto","manual"]).describe("How this agent was discovered")}),ov0=eJ.pick({name:!0,url:!0,status:!0}).extend({slug:F.string()}),uE=FQ.extend({entityType:F.literal("agent"),metadata:ov0}),af=uE.extend({frontmatter:eJ,about:F.string(),skills:F.array(nv0),notes:F.string()}),cE=af.extend({url:F.string().optional(),typeLabel:F.string().optional()}),SzQ=af.extend({url:F.string(),typeLabel:F.string()});w0();ZA();var hzQ=F.object({about:F.string(),skills:F.array(F.object({name:F.string(),description:F.string(),tags:F.array(F.string())})),notes:F.string()});function gzQ(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((B)=>{let $=B.tags.length>0?` [${B.tags.join(", ")}]`:"";return`- ${B.name}: ${B.description}${$}`}).join(`
3579
3579
  `)}function yzQ(A){if(!A.trim())return[];let Q=[];for(let B of A.split(`
3580
3580
  `)){let $=B.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if($){let w=$[1]??"",D=$[2]??"",Y=$[3],X=Y?Y.split(",").map((I)=>I.trim()).filter(Boolean):[];Q.push({name:w,description:D,tags:X})}}return Q}var sv0=new W8(hzQ,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:gzQ,parser:yzQ},{key:"notes",label:"Notes",type:"string"}]});class AW extends _Q{constructor(){super({entityType:"agent",schema:uE,frontmatterSchema:eJ})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,eJ),B=gz(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},...A.brainName&&{brainName:A.brainName},url:A.url,...A.did&&{did:A.did},status:A.status,discoveredAt:A.discoveredAt,discoveredVia:A.discoveredVia},B=sv0.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(B,Q)}parseAgentContent(A){let Q=this.stripFrontmatter(A);if(!Q.trim())return{about:"",skills:[],notes:""};try{let B=sv0.parse(Q);return{about:B.about,skills:B.skills,notes:B.notes}}catch{return{about:"",skills:[],notes:""}}}stripFrontmatter(A){let Q=A.match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);return Q?Q[1]??"":A}}w0();var mzQ=new AW;function uzQ(A){let Q=JQ(A.content,eJ),B=mzQ.parseAgentContent(A.content);return af.parse({...A,frontmatter:Q.metadata,about:B.about,skills:B.skills,notes:B.notes})}class ki extends i9{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 uzQ(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}buildListResult(A,Q,B){return{agents:A,pagination:Q,baseUrl:B.baseUrl}}}w0();ZA();w0();async function fi(A,Q){let $=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let w=await Q($);if(!w.ok)return null;let D=await w.json();return OO(D)}catch{return null}}function av0(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""}ZA();var czQ=new AW;function bi(A){let Q=A.anchor?.name??A.brainName,B=A.anchor?.kind??"professional",$=[];if(A.anchor?.description)$.push(A.anchor.description);if(A.description)$.push(A.description);return{content:czQ.createAgentContent({name:Q,kind:B,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:"active",discoveredAt:new Date().toISOString(),discoveredVia:"manual",about:$.join(`
3581
3581
 
3582
- `),skills:A.skills.map((D)=>({name:D.name,description:D.description,tags:D.tags})),notes:""}),metadata:{name:Q,url:A.url,status:"active",slug:gz(A.url)},anchorName:Q}}var lzQ=F.object({prompt:F.string().optional(),url:F.string().optional(),content:F.string().optional(),skipAi:F.boolean().optional()}),g7B=M7.extend({name:F.string().optional(),domain:F.string().optional()});class wWA extends a5{constructor(A,Q){super(A,Q,{schema:lzQ,jobTypeName:"agent-generation",entityType:"agent"})}async generate(A,Q){let B=A.url??A.prompt??"",$=av0(B);if(!$)throw Error("No URL or domain provided. Use: system_create agent with a domain like yeehaa.io");let w=await fi($,globalThis.fetch);if(!w)throw Error(`Could not fetch Agent Card from ${$}. Make sure the agent is running and accessible.`);let{content:D,metadata:Y,anchorName:X}=bi(w);return{id:$,content:D,metadata:Y,title:X}}}w0();o8();ZA();import{jsxDEV as tv0}from"preact/jsx-dev-runtime";function Ti(A){try{return new URL(A).hostname}catch{return A}}var xi=({name:A,className:Q=""})=>{let B=A.charAt(0).toUpperCase(),$=0;for(let D=0;D<A.length;D++)$=A.charCodeAt(D)+(($<<5)-$);let w=Math.abs($)%360;return tv0("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${w}, 55%, 45%)`},children:B},void 0,!1,void 0,this)},vi=({kind:A,size:Q="md"})=>{let $={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 tv0("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]"} ${$}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as B8,Fragment as rzQ}from"preact/jsx-dev-runtime";var pzQ=({skills:A})=>{if(A.length===0)return null;return B8("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>B8("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 dzQ(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var izQ=({agent:A})=>{let{frontmatter:Q,about:B,skills:$,url:w}=A,D=Q.status==="archived";return B8("a",{href:w,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${D?"opacity-40":""}`,children:[B8(xi,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),B8("div",{className:"flex-1 min-w-0",children:[B8("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[B8("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),B8(vi,{kind:D?"archived":Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&B8("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),B&&B8("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:B},void 0,!1,void 0,this),!D&&B8(pzQ,{skills:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B8("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[B8("span",{className:"text-xs text-theme-muted",children:Ti(Q.url)},void 0,!1,void 0,this),B8("span",{className:"text-[11px] text-theme-muted opacity-60",children:D?"Archived":`Discovered ${dzQ(Q.discoveredAt)}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},ev0=({agents:A,pageTitle:Q,pagination:B,baseUrl:$="/agents"})=>{let w=Q??"Agent Directory",D=B?.totalItems??A.length,Y=`Your network of ${D} ${D===1?"brain":"brains"} and their anchors`;return B8(rzQ,{children:[B8(iQ,{title:w,description:Y},void 0,!1,void 0,this),B8("div",{className:"agent-list bg-theme",children:B8("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[B8("div",{className:"mb-8 pb-6 border-b border-theme",children:[B8("h1",{className:"text-4xl font-bold text-heading mb-2",children:w},void 0,!1,void 0,this),B8("p",{className:"text-theme-muted",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B8("div",{className:"flex flex-col gap-4",children:A.map((X)=>B8(izQ,{agent:X},X.id,!1,void 0,this))},void 0,!1,void 0,this),A.length===0&&B8("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&&B8("div",{className:"mt-12",children:B8(MY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},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 wQ,Fragment as szQ}from"preact/jsx-dev-runtime";function nzQ(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var tf=({children:A})=>wQ("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),ozQ=({skill:A})=>wQ("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[wQ("div",{className:"flex-1",children:[wQ("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),wQ("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&&wQ("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>wQ("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),AS0=({label:A,value:Q,valueClassName:B})=>wQ("div",{className:"flex justify-between text-[13px]",children:[wQ("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),wQ("span",{className:B??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),QS0=({agent:A})=>{let{frontmatter:Q,about:B,skills:$,notes:w}=A,D=Ti(Q.url);return wQ(szQ,{children:[wQ(iQ,{title:Q.name,description:B||`Agent profile for ${Q.name}`},void 0,!1,void 0,this),wQ("article",{className:"agent-detail",children:wQ("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[wQ("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),wQ("div",{className:"flex items-start gap-6 mb-8",children:[wQ(xi,{name:Q.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),wQ("div",{children:[wQ("div",{className:"flex items-center gap-3 mb-1",children:[wQ("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:Q.name},void 0,!1,void 0,this),wQ(vi,{kind:Q.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),wQ("div",{className:"flex items-center gap-3 text-theme-muted",children:[Q.organization&&wQ("span",{className:"text-[15px]",children:Q.organization},void 0,!1,void 0,this),Q.organization&&wQ("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),wQ("span",{className:"text-sm",children:["Discovered ",nzQ(Q.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),wQ("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col md:flex-row gap-12",children:[wQ("div",{className:"flex-[2] min-w-0",children:[B&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"About"},void 0,!1,void 0,this),wQ("p",{className:"text-[15px] text-theme leading-relaxed",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.length>0&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Skills"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col gap-2.5",children:$.map((Y)=>wQ(ozQ,{skill:Y},Y.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Notes"},void 0,!1,void 0,this),wQ("p",{className:"text-[15px] text-theme leading-relaxed",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Brain"},void 0,!1,void 0,this),wQ("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[wQ("div",{className:"text-[15px] font-semibold text-heading mb-1",children:Q.brainName??`${Q.name}'s Brain`},void 0,!1,void 0,this),Q.did&&wQ("div",{className:"text-xs text-theme-muted font-mono",children:Q.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Connection"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col gap-3",children:[wQ("div",{children:[wQ("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),wQ("div",{className:"text-xs text-heading font-mono",children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),wQ(AS0,{label:"Status",value:Q.status==="active"?"Active":"Archived",valueClassName:Q.status==="active"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this),wQ(AS0,{label:"Discovered via",value:Q.discoveredVia==="atproto"?"AT Protocol":"Manual"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("a",{href:Q.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 ",D," \u2197"]},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,!1,void 0,this)]},void 0,!0,void 0,this)};var azQ=F.object({agents:F.array(cE),pageTitle:F.string().optional(),pagination:j7.nullable(),baseUrl:F.string().optional()});function BS0(){return{"agent-list":E1({name:"agent-list",description:"Agent directory list page template",schema:azQ,dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:ev0}}),"agent-detail":E1({name:"agent-detail",description:"Individual agent profile template",schema:F.object({agent:cE,prevAgent:cE.nullable(),nextAgent:cE.nullable()}),dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:QS0}})}}function $S0(A){A.messaging.subscribe("a2a:call:completed",async(Q)=>{try{let{domain:B}=Q.payload;if(await A.entityService.getEntity("agent",B))return{success:!0};let w=await fi(B,globalThis.fetch);if(!w)return{success:!0};let{content:D,metadata:Y}=bi(w);await A.entityService.createEntity({id:B,entityType:"agent",content:D,metadata:Y})}catch{}return{success:!0}})}var Si={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.31",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","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ezQ=new AW;class DWA extends z2{entityType="agent";schema=uE;adapter=ezQ;constructor(){super("agent-discovery",Si)}createGenerationHandler(A){return new wWA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return BS0()}getDataSources(){return[new ki(this.logger.child("AgentDataSource"))]}async onRegister(A){$S0(A)}}function YWA(){return new DWA}w0();ZA();ZA();w0();var lE=wV,wS0=wV,ef=FQ.extend({entityType:F.literal("skill"),metadata:wS0});w0();class pE extends _Q{constructor(){super({entityType:"skill",schema:ef,frontmatterSchema:lE})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,lE);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}ZA();function AVQ(A){let Q=[];if(A.topicTitles.length>0)Q.push(`The brain's knowledge domains (from content analysis):
3582
+ `),skills:A.skills.map((D)=>({name:D.name,description:D.description,tags:D.tags})),notes:""}),metadata:{name:Q,url:A.url,status:"active",slug:gz(A.url)},anchorName:Q}}var lzQ=F.object({prompt:F.string().optional(),url:F.string().optional(),content:F.string().optional(),skipAi:F.boolean().optional()}),g7B=M7.extend({name:F.string().optional(),domain:F.string().optional()});class wWA extends a5{constructor(A,Q){super(A,Q,{schema:lzQ,jobTypeName:"agent-generation",entityType:"agent"})}async generate(A,Q){let B=A.url??A.prompt??"",$=av0(B);if(!$)throw Error("No URL or domain provided. Use: system_create agent with a domain like yeehaa.io");let w=await fi($,globalThis.fetch);if(!w)throw Error(`Could not fetch Agent Card from ${$}. Make sure the agent is running and accessible.`);let{content:D,metadata:Y,anchorName:X}=bi(w);return{id:$,content:D,metadata:Y,title:X}}}w0();o8();ZA();import{jsxDEV as tv0}from"preact/jsx-dev-runtime";function Ti(A){try{return new URL(A).hostname}catch{return A}}var xi=({name:A,className:Q=""})=>{let B=A.charAt(0).toUpperCase(),$=0;for(let D=0;D<A.length;D++)$=A.charCodeAt(D)+(($<<5)-$);let w=Math.abs($)%360;return tv0("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${w}, 55%, 45%)`},children:B},void 0,!1,void 0,this)},vi=({kind:A,size:Q="md"})=>{let $={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 tv0("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]"} ${$}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as B8,Fragment as rzQ}from"preact/jsx-dev-runtime";var pzQ=({skills:A})=>{if(A.length===0)return null;return B8("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>B8("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 dzQ(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}var izQ=({agent:A})=>{let{frontmatter:Q,about:B,skills:$,url:w}=A,D=Q.status==="archived";return B8("a",{href:w,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${D?"opacity-40":""}`,children:[B8(xi,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),B8("div",{className:"flex-1 min-w-0",children:[B8("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[B8("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),B8(vi,{kind:D?"archived":Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&B8("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),B&&B8("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:B},void 0,!1,void 0,this),!D&&B8(pzQ,{skills:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B8("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[B8("span",{className:"text-xs text-theme-muted",children:Ti(Q.url)},void 0,!1,void 0,this),B8("span",{className:"text-[11px] text-theme-muted opacity-60",children:D?"Archived":`Discovered ${dzQ(Q.discoveredAt)}`},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},ev0=({agents:A,pageTitle:Q,pagination:B,baseUrl:$="/agents"})=>{let w=Q??"Agent Directory",D=B?.totalItems??A.length,Y=`Your network of ${D} ${D===1?"brain":"brains"} and their anchors`;return B8(rzQ,{children:[B8(iQ,{title:w,description:Y},void 0,!1,void 0,this),B8("div",{className:"agent-list bg-theme",children:B8("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[B8("div",{className:"mb-8 pb-6 border-b border-theme",children:[B8("h1",{className:"text-4xl font-bold text-heading mb-2",children:w},void 0,!1,void 0,this),B8("p",{className:"text-theme-muted",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B8("div",{className:"flex flex-col gap-4",children:A.map((X)=>B8(izQ,{agent:X},X.id,!1,void 0,this))},void 0,!1,void 0,this),A.length===0&&B8("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&&B8("div",{className:"mt-12",children:B8(MY,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},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 wQ,Fragment as szQ}from"preact/jsx-dev-runtime";function nzQ(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var tf=({children:A})=>wQ("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),ozQ=({skill:A})=>wQ("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[wQ("div",{className:"flex-1",children:[wQ("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),wQ("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&&wQ("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>wQ("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),AS0=({label:A,value:Q,valueClassName:B})=>wQ("div",{className:"flex justify-between text-[13px]",children:[wQ("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),wQ("span",{className:B??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),QS0=({agent:A})=>{let{frontmatter:Q,about:B,skills:$,notes:w}=A,D=Ti(Q.url);return wQ(szQ,{children:[wQ(iQ,{title:Q.name,description:B||`Agent profile for ${Q.name}`},void 0,!1,void 0,this),wQ("article",{className:"agent-detail",children:wQ("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[wQ("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),wQ("div",{className:"flex items-start gap-6 mb-8",children:[wQ(xi,{name:Q.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),wQ("div",{children:[wQ("div",{className:"flex items-center gap-3 mb-1",children:[wQ("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:Q.name},void 0,!1,void 0,this),wQ(vi,{kind:Q.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),wQ("div",{className:"flex items-center gap-3 text-theme-muted",children:[Q.organization&&wQ("span",{className:"text-[15px]",children:Q.organization},void 0,!1,void 0,this),Q.organization&&wQ("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),wQ("span",{className:"text-sm",children:["Discovered ",nzQ(Q.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),wQ("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col md:flex-row gap-12",children:[wQ("div",{className:"flex-[2] min-w-0",children:[B&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"About"},void 0,!1,void 0,this),wQ("p",{className:"text-[15px] text-theme leading-relaxed",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.length>0&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Skills"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col gap-2.5",children:$.map((Y)=>wQ(ozQ,{skill:Y},Y.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w&&wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Notes"},void 0,!1,void 0,this),wQ("p",{className:"text-[15px] text-theme leading-relaxed",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Brain"},void 0,!1,void 0,this),wQ("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[wQ("div",{className:"text-[15px] font-semibold text-heading mb-1",children:Q.brainName??`${Q.name}'s Brain`},void 0,!1,void 0,this),Q.did&&wQ("div",{className:"text-xs text-theme-muted font-mono",children:Q.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("section",{className:"mb-8",children:[wQ(tf,{children:"Connection"},void 0,!1,void 0,this),wQ("div",{className:"flex flex-col gap-3",children:[wQ("div",{children:[wQ("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),wQ("div",{className:"text-xs text-heading font-mono",children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),wQ(AS0,{label:"Status",value:Q.status==="active"?"Active":"Archived",valueClassName:Q.status==="active"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this),wQ(AS0,{label:"Discovered via",value:Q.discoveredVia==="atproto"?"AT Protocol":"Manual"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),wQ("a",{href:Q.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 ",D," \u2197"]},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,!1,void 0,this)]},void 0,!0,void 0,this)};var azQ=F.object({agents:F.array(cE),pageTitle:F.string().optional(),pagination:j7.nullable(),baseUrl:F.string().optional()});function BS0(){return{"agent-list":E1({name:"agent-list",description:"Agent directory list page template",schema:azQ,dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:ev0}}),"agent-detail":E1({name:"agent-detail",description:"Individual agent profile template",schema:F.object({agent:cE,prevAgent:cE.nullable(),nextAgent:cE.nullable()}),dataSourceId:"agent-discovery:entities",requiredPermission:"public",layout:{component:QS0}})}}function $S0(A){A.messaging.subscribe("a2a:call:completed",async(Q)=>{try{let{domain:B}=Q.payload;if(await A.entityService.getEntity("agent",B))return{success:!0};let w=await fi(B,globalThis.fetch);if(!w)return{success:!0};let{content:D,metadata:Y}=bi(w);await A.entityService.createEntity({id:B,entityType:"agent",content:D,metadata:Y})}catch{}return{success:!0}})}var Si={name:"@brains/agent-discovery",private:!0,version:"0.2.0-alpha.32",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","lint:fix":"eslint . --ext .ts --fix"},dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"latest","bun-types":"latest",eslint:"^8.56.0",typescript:"^5.3.3"}};var ezQ=new AW;class DWA extends z2{entityType="agent";schema=uE;adapter=ezQ;constructor(){super("agent-discovery",Si)}createGenerationHandler(A){return new wWA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return BS0()}getDataSources(){return[new ki(this.logger.child("AgentDataSource"))]}async onRegister(A){$S0(A)}}function YWA(){return new DWA}w0();ZA();ZA();w0();var lE=wV,wS0=wV,ef=FQ.extend({entityType:F.literal("skill"),metadata:wS0});w0();class pE extends _Q{constructor(){super({entityType:"skill",schema:ef,frontmatterSchema:lE})}toMarkdown(A){return A.content}fromMarkdown(A){let Q=this.parseFrontMatter(A,lE);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}ZA();function AVQ(A){let Q=[];if(A.topicTitles.length>0)Q.push(`The brain's knowledge domains (from content analysis):
3583
3583
  ${A.topicTitles.map((B)=>`- ${B}`).join(`
3584
3584
  `)}`);if(A.toolDescriptions.length>0)Q.push(`The brain has these capabilities:
3585
3585
  ${A.toolDescriptions.map((B)=>`- ${B}`).join(`
@@ -3621,7 +3621,7 @@ Return 2-5 skills as a JSON object with a "skills" array.`,requiredPermission:"p
3621
3621
  title: ${Y}
3622
3622
  keywords: []
3623
3623
  ---
3624
- ${Y}`;try{await A.entityService.createEntity({id:X,entityType:"topic",content:I,metadata:{}})}catch{}}let w=await hi(A,this.logger),D=await A.entityService.listEntities("skill");return{...w,skills:D.map((Y)=>Y.metadata)}})}async deriveAll(A){this.logger.info("Deriving skills from topics (replace-all)");let Q=await hi(A,this.logger,{replaceAll:!0});this.logger.info("Skill derivation complete",Q)}hasRunInitialDerivation(){return this.initialDerivationDone}}function IWA(){return new XWA}var $VQ=F.object({}).strict();function gi(A={}){return $VQ.parse(A),[YWA(),IWA()]}w0();ZA();o8();ZA();w0();var yi=yv.extend({expertise:F.array(F.string()).optional().describe("Skills, domains, areas of focus"),currentFocus:F.string().optional().describe("What you're currently working on"),availability:F.string().optional().describe("What you're open to (consulting, speaking, etc.)")}),QW=n4.extend(yi.shape);w0();JG();ZA();var wVQ=new TX;class mi{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 $=B.entityService,[w,D,Y,X]=await Promise.all([$V($),$.listEntities("post",{limit:20}),$.listEntities("deck",{limit:20}),vH($)]),I=wVQ.parseProfileBody(w,QW),K=D.sort(pC).slice(0,3).map(Of),G=Y.sort(pC).slice(0,3).map(_f);if(!X.cta)throw Error("CTA not configured in site-info");let W={profile:I,posts:K,decks:G,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:X.cta};return Q.parse(W)}}w0();JG();var DVQ=new TX;class ui{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,B){let $=await $V(B.entityService),D={profile:DVQ.parseProfileBody($,QW)};return Q.parse(D)}}import{jsxDEV as m6,Fragment as YS0}from"preact/jsx-dev-runtime";var KWA=({profile:A,posts:Q,decks:B,postsListUrl:$,decksListUrl:w,cta:D})=>{let Y=A.tagline||A.description,X=Q.map((W)=>({id:W.id,url:W.url,title:W.metadata.title,date:W.metadata.publishedAt||W.created,description:W.frontmatter.excerpt,series:W.frontmatter.seriesName&&W.frontmatter.seriesIndex?{name:W.frontmatter.seriesName,index:W.frontmatter.seriesIndex}:void 0})),I=B.map((W)=>({id:W.id,url:W.url,title:W.frontmatter.title||W.id,date:W.frontmatter.publishedAt??W.created,description:W.frontmatter.description})),K=A.name||"Home",G=A.intro||A.description||Y||"Professional site";return m6(YS0,{children:[m6(iQ,{title:K,description:G,ogType:"website"},void 0,!1,void 0,this),m6("div",{className:"homepage-list bg-theme",children:[m6("header",{className:"hero-bg-pattern relative w-full min-h-[70vh] flex items-end px-6 md:px-12 bg-theme overflow-hidden",children:m6("div",{className:"relative z-10 max-w-6xl mx-auto w-full pb-16 md:pb-24",children:[Y&&m6("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&&m6(YS0,{children:[m6("div",{className:"w-12 border-t border-theme mt-8 mb-6 md:mt-10 md:mb-8"},void 0,!1,void 0,this),m6("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),m6("div",{className:"section-divider"},void 0,!1,void 0,this),m6("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"Essays",items:X,viewAllUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),I.length>0&&m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"Presentations",items:I,viewAllUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),(A.description||A.expertise&&A.expertise.length>0)&&m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"About",viewAllUrl:"/about",variant:"stacked",children:m6("div",{className:"space-y-6",children:[A.description&&m6("p",{className:"text-lg text-theme leading-relaxed",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&m6(H$,{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),m6(DKA,{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 WB,Fragment as YVQ}from"preact/jsx-dev-runtime";var HWA=({profile:A})=>{let Q=`About ${A.name||"Me"}`,B=A.description||A.intro||"About page",$=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return WB(YVQ,{children:[WB(iQ,{title:Q,description:B,ogType:"profile"},void 0,!1,void 0,this),WB("div",{className:"about-page bg-theme",children:[WB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:WB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[WB("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&&WB("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),WB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&WB("section",{className:"content-section-reveal mb-20 md:mb-28",children:WB(EY,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&WB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),WB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((w,D)=>WB("li",{className:Xk({variant:"accent",size:"lg"}),children:w},D,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),WB("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&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),WB("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)&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),WB("div",{className:"space-y-4",children:[A.email&&WB("p",{className:"text-lg",children:WB("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&&WB("p",{className:"text-lg",children:WB("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&&WB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((w,D)=>WB(G9,{href:w.url,external:!0,variant:"secondary",size:"md",children:w.label||w.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 q$,Fragment as XS0}from"preact/jsx-dev-runtime";var UWA=()=>{return q$(XS0,{children:[q$(iQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),q$("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:q$("div",{className:"text-center max-w-md",children:[q$("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),q$("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),q$("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),q$(G9,{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)},GWA=()=>{return q$(XS0,{children:[q$(iQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),q$("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:q$("div",{className:"text-center max-w-md",children:[q$("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),q$("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),q$("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),q$(G9,{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)};ZA();var IS0=F.object({label:F.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:F.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),KS0=F.object({entityDisplay:F.object({post:IS0,deck:IS0}).describe("Display metadata for post and deck entity types (required for homepage)")});var HS0={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.31",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 JWA extends f8{dependencies=["blog","decks"];constructor(A){super("professional-site",HS0,A,KS0)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",yi);let Q=this.config.entityDisplay.post,B=this.config.entityDisplay.deck,$=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,w=`/${B.pluralName??B.label.toLowerCase()+"s"}`,D=new mi($,w);A.entities.registerDataSource(D);let Y=new ui;A.entities.registerDataSource(Y);let X=F.object({profile:QW,posts:F.array(mH),decks:F.array(Rf),postsListUrl:F.string(),decksListUrl:F.string(),cta:Gf}),I=F.object({profile:QW}),K=F.object({});A.templates.register({"homepage-list":E1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:KWA}}),about:E1({name:"about",description:"About page with full profile information",schema:I,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:HWA}}),"subscribe-thanks":E1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:UWA}}),"subscribe-error":E1({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:GWA}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function US0(A){return new JWA(A??{})}var GS0=[{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 dE}from"preact/jsx-dev-runtime";function JS0({sections:A,siteInfo:Q,slots:B}){return dE("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[dE(KKA,{title:Q.title,navigation:Q.navigation.primary,...Q.logo!==void 0?{logo:Q.logo}:{}},void 0,!1,void 0,this),dE("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),dE("div",{className:"section-divider"},void 0,!1,void 0,this),dE(XKA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,children:dE(EGA,{name:"footer-top",slots:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var IVQ={layouts:{default:JS0},routes:GS0,plugin:US0,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"}}}},dH=IVQ;var WS0=`/* Default font imports */
3624
+ ${Y}`;try{await A.entityService.createEntity({id:X,entityType:"topic",content:I,metadata:{}})}catch{}}let w=await hi(A,this.logger),D=await A.entityService.listEntities("skill");return{...w,skills:D.map((Y)=>Y.metadata)}})}async deriveAll(A){this.logger.info("Deriving skills from topics (replace-all)");let Q=await hi(A,this.logger,{replaceAll:!0});this.logger.info("Skill derivation complete",Q)}hasRunInitialDerivation(){return this.initialDerivationDone}}function IWA(){return new XWA}var $VQ=F.object({}).strict();function gi(A={}){return $VQ.parse(A),[YWA(),IWA()]}w0();ZA();o8();ZA();w0();var yi=yv.extend({expertise:F.array(F.string()).optional().describe("Skills, domains, areas of focus"),currentFocus:F.string().optional().describe("What you're currently working on"),availability:F.string().optional().describe("What you're open to (consulting, speaking, etc.)")}),QW=n4.extend(yi.shape);w0();JG();ZA();var wVQ=new TX;class mi{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 $=B.entityService,[w,D,Y,X]=await Promise.all([$V($),$.listEntities("post",{limit:20}),$.listEntities("deck",{limit:20}),vH($)]),I=wVQ.parseProfileBody(w,QW),K=D.sort(pC).slice(0,3).map(Of),G=Y.sort(pC).slice(0,3).map(_f);if(!X.cta)throw Error("CTA not configured in site-info");let W={profile:I,posts:K,decks:G,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:X.cta};return Q.parse(W)}}w0();JG();var DVQ=new TX;class ui{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,B){let $=await $V(B.entityService),D={profile:DVQ.parseProfileBody($,QW)};return Q.parse(D)}}import{jsxDEV as m6,Fragment as YS0}from"preact/jsx-dev-runtime";var KWA=({profile:A,posts:Q,decks:B,postsListUrl:$,decksListUrl:w,cta:D})=>{let Y=A.tagline||A.description,X=Q.map((W)=>({id:W.id,url:W.url,title:W.metadata.title,date:W.metadata.publishedAt||W.created,description:W.frontmatter.excerpt,series:W.frontmatter.seriesName&&W.frontmatter.seriesIndex?{name:W.frontmatter.seriesName,index:W.frontmatter.seriesIndex}:void 0})),I=B.map((W)=>({id:W.id,url:W.url,title:W.frontmatter.title||W.id,date:W.frontmatter.publishedAt??W.created,description:W.frontmatter.description})),K=A.name||"Home",G=A.intro||A.description||Y||"Professional site";return m6(YS0,{children:[m6(iQ,{title:K,description:G,ogType:"website"},void 0,!1,void 0,this),m6("div",{className:"homepage-list bg-theme",children:[m6("header",{className:"hero-bg-pattern relative w-full min-h-[70vh] flex items-end px-6 md:px-12 bg-theme overflow-hidden",children:m6("div",{className:"relative z-10 max-w-6xl mx-auto w-full pb-16 md:pb-24",children:[Y&&m6("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&&m6(YS0,{children:[m6("div",{className:"w-12 border-t border-theme mt-8 mb-6 md:mt-10 md:mb-8"},void 0,!1,void 0,this),m6("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),m6("div",{className:"section-divider"},void 0,!1,void 0,this),m6("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"Essays",items:X,viewAllUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),I.length>0&&m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"Presentations",items:I,viewAllUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this),(A.description||A.expertise&&A.expertise.length>0)&&m6("div",{className:"content-section-reveal mb-20 md:mb-32",children:m6(LH,{title:"About",viewAllUrl:"/about",variant:"stacked",children:m6("div",{className:"space-y-6",children:[A.description&&m6("p",{className:"text-lg text-theme leading-relaxed",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&m6(H$,{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),m6(DKA,{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 WB,Fragment as YVQ}from"preact/jsx-dev-runtime";var HWA=({profile:A})=>{let Q=`About ${A.name||"Me"}`,B=A.description||A.intro||"About page",$=A.expertise&&A.expertise.length>0||A.currentFocus||A.availability||A.email||A.website||A.socialLinks&&A.socialLinks.length>0;return WB(YVQ,{children:[WB(iQ,{title:Q,description:B,ogType:"profile"},void 0,!1,void 0,this),WB("div",{className:"about-page bg-theme",children:[WB("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:WB("div",{className:"relative z-10 max-w-4xl mx-auto",children:[WB("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&&WB("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),WB("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&WB("section",{className:"content-section-reveal mb-20 md:mb-28",children:WB(EY,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&WB("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),WB("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((w,D)=>WB("li",{className:Xk({variant:"accent",size:"lg"}),children:w},D,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),WB("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&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),WB("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)&&WB("section",{children:[WB("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),WB("div",{className:"space-y-4",children:[A.email&&WB("p",{className:"text-lg",children:WB("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&&WB("p",{className:"text-lg",children:WB("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&&WB("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((w,D)=>WB(G9,{href:w.url,external:!0,variant:"secondary",size:"md",children:w.label||w.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 q$,Fragment as XS0}from"preact/jsx-dev-runtime";var UWA=()=>{return q$(XS0,{children:[q$(iQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),q$("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:q$("div",{className:"text-center max-w-md",children:[q$("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),q$("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),q$("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),q$(G9,{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)},GWA=()=>{return q$(XS0,{children:[q$(iQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),q$("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:q$("div",{className:"text-center max-w-md",children:[q$("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),q$("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),q$("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),q$(G9,{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)};ZA();var IS0=F.object({label:F.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:F.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),KS0=F.object({entityDisplay:F.object({post:IS0,deck:IS0}).describe("Display metadata for post and deck entity types (required for homepage)")});var HS0={name:"@brains/site-professional",private:!0,version:"0.2.0-alpha.32",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 JWA extends f8{dependencies=["blog","decks"];constructor(A){super("professional-site",HS0,A,KS0)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",yi);let Q=this.config.entityDisplay.post,B=this.config.entityDisplay.deck,$=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,w=`/${B.pluralName??B.label.toLowerCase()+"s"}`,D=new mi($,w);A.entities.registerDataSource(D);let Y=new ui;A.entities.registerDataSource(Y);let X=F.object({profile:QW,posts:F.array(mH),decks:F.array(Rf),postsListUrl:F.string(),decksListUrl:F.string(),cta:Gf}),I=F.object({profile:QW}),K=F.object({});A.templates.register({"homepage-list":E1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:KWA}}),about:E1({name:"about",description:"About page with full profile information",schema:I,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:HWA}}),"subscribe-thanks":E1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:UWA}}),"subscribe-error":E1({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:GWA}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function US0(A){return new JWA(A??{})}var GS0=[{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 dE}from"preact/jsx-dev-runtime";function JS0({sections:A,siteInfo:Q,slots:B}){return dE("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[dE(KKA,{title:Q.title,navigation:Q.navigation.primary,...Q.logo!==void 0?{logo:Q.logo}:{}},void 0,!1,void 0,this),dE("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),dE("div",{className:"section-divider"},void 0,!1,void 0,this),dE(XKA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,children:dE(EGA,{name:"footer-top",slots:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var IVQ={layouts:{default:JS0},routes:GS0,plugin:US0,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"}}}},dH=IVQ;var WS0=`/* Default font imports */
3625
3625
  @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap');
3626
3626
  @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap');
3627
3627
 
@@ -3925,7 +3925,7 @@ ${Y}`;try{await A.entityService.createEntity({id:X,entityType:"topic",content:I,
3925
3925
  .btn-primary:hover { background-color: var(--color-brand-dark); }
3926
3926
  .btn-primary:disabled { opacity: 0.5; }
3927
3927
  }
3928
- `;var ci=WS0;import{join as UVQ}from"path";var ZS0={name:"@brains/rover",version:"0.2.0-alpha.31",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"start:core":"cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","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 FS0=["prompt","note","link","wishlist","topics","directory-sync","agents","admin","dashboard","mcp","webserver","discord","a2a"],qS0=[...FS0,"image","dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],GVQ=[...qS0,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],zS0=fG({name:"rover",version:ZS0.version,model:"gpt-5.4-mini",site:dH,theme:ci,presets:{core:FS0,default:qS0,full:GVQ},evalDisable:["discord","webserver","mcp","analytics","dashboard"],capabilities:[["prompt",a3,void 0],["image",lR,void 0],["admin",tJ,{}],["dashboard",s3,void 0],["blog",_GA,{}],["series",xGA,void 0],["decks",kf,void 0],["note",i3,{}],["link",n3,{}],["portfolio",UJA,{}],["topics",Hi,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",vJA,{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",yf,{autoGenerateOnBlogPublish:!0}],["newsletter",Rv0,{doubleOptIn:!0}],["obsidian-vault",oJA,{autoSync:!0}],["wishlist",Ri,{}],["stock-photo",$WA,{}],["agents",gi,void 0],["directory-sync",H3,{seedContent:!0,seedContentPath:UVQ(import.meta.dir,"..","seed-content"),initialSync:!0}],["analytics",Li,{}],["site-info",h3,void 0],["site-builder",l3,{cms:{}}]],interfaces:[["mcp",mG,()=>({})],["discord",LJ,()=>({})],["webserver",EJ,()=>({})],["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"}}});SG();w0();ZA();ZA();w0();var li=F.object({routeId:F.string(),sectionId:F.string()}),Ab=FQ.extend({entityType:F.literal("site-content"),template:F.string().optional(),content:F.string(),metadata:li});w0();class VS0 extends _Q{constructor(){super({entityType:"site-content",schema:Ab,frontmatterSchema:li})}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 WWA=new VS0;ZA();var pi=F.object({routeId:F.string().optional().describe("Optional: specific route filter"),sectionId:F.string().optional().describe("Optional: specific section filter"),dryRun:F.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:F.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),l4B=F.object({jobs:F.array(F.object({jobId:F.string(),routeId:F.string(),sectionId:F.string()})),totalSections:F.number(),queuedSections:F.number(),skippedSections:F.number().optional(),batchId:F.string().optional()});class ZWA{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 $=this.context.logger.child("SiteContentOperations"),w=await this.fetchRoutes(),D=w;if(A.routeId){if(D=w.filter((G)=>G.id===A.routeId),D.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let G of D)for(let W of G.sections){if(A.sectionId&&W.id!==A.sectionId)continue;if(W.content){$.debug("Section has static content, skipping",{routeId:G.id,sectionId:W.id});continue}if(W.template){let Z=this.context.templates.getCapabilities(W.template);if(!Z){$.warn("Template not found, skipping section",{routeId:G.id,sectionId:W.id,templateName:W.template});continue}if(!Z.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:G.id,sectionId:W.id,templateName:W.template,capabilities:Z});continue}}else{$.debug("Section has no template, skipping",{routeId:G.id,sectionId:W.id});continue}if(!A.force&&!A.dryRun){let Z=`${G.id}:${W.id}`;if(await this.context.entityService.getEntity("site-content",Z)){$.debug("Content already exists, skipping",{routeId:G.id,sectionId:W.id});continue}}Y.push({route:G,section:W})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let I=[],K=[];for(let{route:G,section:W}of Y){let Z=`${G.id}:${W.id}`,q=W.template,N={routeId:G.id,sectionId:W.id,entityId:Z,entityType:"site-content",templateName:q,context:{prompt:typeof W.content==="string"?W.content:void 0,data:{routeId:G.id,sectionId:W.id,routeTitle:G.title||Q?.title||"",routeDescription:G.description||Q?.description||"",sectionContent:W.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:N})}if(K.length>0){let G=this.createJobOptions(B,"site:content-generation"),W=await this.context.jobs.enqueueBatch(K,G);for(let Z=0;Z<Y.length;Z++){let q=Y[Z];if(q)I.push({jobId:`${W}-${Z}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:I,totalSections:X,queuedSections:I.length,batchId:W}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class FWA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new ZWA(A)}async generateContent(A,Q){let B=pi.parse(A);return this.operations.generate(B,this.siteConfig,Q)}}w0();function NS0(A,Q){return[g2(Q,"generate","Generate content for all routes, a specific route, or a specific section",pi,async(B,$)=>{let w=A();if(!w)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:$.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:$.interfaceType,channelId:$.channelId},Y=await w.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 LS0={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.31",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 qWA extends f8{siteContentService;constructor(){super("site-content",LS0,{},F.object({}))}async onRegister(A){A.entities.register("site-content",Ab,WWA),this.siteContentService=new FWA(A)}async getTools(){return NS0(()=>this.siteContentService,this.id)}}function Qb(){return new qWA}w0();ZA();o8();ZA();w0();var ES0=F.enum(["available","early access","coming soon","planned"]),MS0=F.object({title:F.string(),description:F.string()}),iH=F.object({name:F.string(),availability:ES0,order:F.number()}),di=F.object({tagline:F.string(),promise:F.string(),role:F.string(),purpose:F.string(),audience:F.string(),values:F.array(F.string()).min(1),features:F.array(MS0).min(1).max(6),story:F.string()}),WVQ=iH.pick({name:!0,availability:!0,order:!0}).extend({slug:F.string()}),iE=FQ.extend({entityType:F.literal("product"),metadata:WVQ}),ii=iE.extend({frontmatter:iH,body:di,labels:F.record(F.string(),F.string())}),ri=ii.extend({url:F.string().optional(),typeLabel:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional()});w0();ZA();ZA();class rE extends W8{constructor(){super(di,{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 zWA extends _Q{constructor(){super({entityType:"product",schema:iE,frontmatterSchema:iH,bodyFormatter:new rE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,iH);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,iH),B=a1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:B,availability:Q.availability,order:Q.order}}}}var ni=new zWA;ZA();w0();var CS0=F.object({title:F.string(),description:F.string()}),OS0=F.object({title:F.string(),description:F.string()}),ZVQ=F.object({title:F.string(),description:F.string()}),jS0=F.object({heading:F.string(),buttonText:F.string(),link:F.string()}),rH=F.object({headline:F.string(),tagline:F.string()}),FVQ=F.object({title:F.string(),description:F.string()}),oi=F.object({vision:F.string(),pillars:F.array(CS0).min(1).max(6),approach:F.array(FVQ).min(1).max(6),productsIntro:F.string(),technologies:F.array(ZVQ).min(1).max(6),benefits:F.array(OS0).min(1).max(6),cta:jS0}),RS0=rH.pick({headline:!0}).extend({slug:F.string()}),nE=FQ.extend({entityType:F.literal("products-overview"),metadata:RS0}),Bb=nE.extend({frontmatter:rH,body:oi,labels:F.record(F.string(),F.string())});w0();ZA();ZA();class oE extends W8{constructor(){super(oi,{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 VWA extends _Q{constructor(){super({entityType:"products-overview",schema:nE,frontmatterSchema:rH,bodyFormatter:new oE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,rH);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,rH),B=a1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:B}}}}var NWA=new VWA;w0();ZA();var qVQ=F.object({entityType:F.string(),query:F.object({id:F.string().optional()}).optional()});function PS0(A,Q){let B=JQ(A.content,iH),$=Q.parse(B.content),w=Q.getLabels();return ii.parse({...A,frontmatter:B.metadata,body:$,labels:w})}function _S0(A,Q){let B=JQ(A.content,rH),$=Q.parse(B.content),w=Q.getLabels();return Bb.parse({...A,frontmatter:B.metadata,body:$,labels:w})}class si{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new oE;productFormatter=new rE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,B){let $=qVQ.parse(A),w=B.entityService;if($.entityType==="products-overview"){let K=(await w.listEntities("products-overview",{limit:1}))[0];if(!K)throw Error("Products overview entity not found");let G=_S0(K,this.overviewFormatter);return Q.parse(G)}if($.query?.id){let K=(await w.listEntities("product",{filter:{metadata:{slug:$.query.id}},limit:1}))[0];if(!K)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:PS0(K,this.productFormatter)})}let[D,Y]=await Promise.all([w.listEntities("products-overview",{limit:1}),w.listEntities("product",{sortFields:[{field:"order",direction:"asc"}]})]),X=D[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:_S0(X,this.overviewFormatter),products:Y.map((I)=>PS0(I,this.productFormatter))})}}import{jsxDEV as l0,Fragment as NVQ}from"preact/jsx-dev-runtime";var kS0=({overview:A,products:Q})=>{let{frontmatter:B,body:$,labels:w}=A;return l0(NVQ,{children:[l0(iQ,{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:`
3928
+ `;var ci=WS0;import{join as UVQ}from"path";var ZS0={name:"@brains/rover",version:"0.2.0-alpha.32",type:"module",private:!0,main:"./src/index.ts",files:["src","brain.eval.yaml","env.schema.template"],scripts:{"start:core":"cd test-apps/core && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","start:default":"cd test-apps/default && INIT_CWD=$PWD bun run --filter @rizom/brain dev:start","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 FS0=["prompt","note","link","wishlist","topics","directory-sync","agents","admin","dashboard","mcp","webserver","discord","a2a"],qS0=[...FS0,"image","dashboard","blog","series","decks","analytics","obsidian-vault","site-info","site-builder"],GVQ=[...qS0,"portfolio","topics","content-pipeline","social-media","newsletter","stock-photo"],zS0=fG({name:"rover",version:ZS0.version,model:"gpt-5.4-mini",site:dH,theme:ci,presets:{core:FS0,default:qS0,full:GVQ},evalDisable:["discord","webserver","mcp","analytics","dashboard"],capabilities:[["prompt",a3,void 0],["image",lR,void 0],["admin",tJ,{}],["dashboard",s3,void 0],["blog",_GA,{}],["series",xGA,void 0],["decks",kf,void 0],["note",i3,{}],["link",n3,{}],["portfolio",UJA,{}],["topics",Hi,{includeEntityTypes:["post","deck","project","link","anchor-profile"]}],["content-pipeline",vJA,{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",yf,{autoGenerateOnBlogPublish:!0}],["newsletter",Rv0,{doubleOptIn:!0}],["obsidian-vault",oJA,{autoSync:!0}],["wishlist",Ri,{}],["stock-photo",$WA,{}],["agents",gi,void 0],["directory-sync",H3,{seedContent:!0,seedContentPath:UVQ(import.meta.dir,"..","seed-content"),initialSync:!0}],["analytics",Li,{}],["site-info",h3,void 0],["site-builder",l3,{cms:{}}]],interfaces:[["mcp",mG,()=>({})],["discord",LJ,()=>({})],["webserver",EJ,()=>({})],["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"}}});SG();w0();ZA();ZA();w0();var li=F.object({routeId:F.string(),sectionId:F.string()}),Ab=FQ.extend({entityType:F.literal("site-content"),template:F.string().optional(),content:F.string(),metadata:li});w0();class VS0 extends _Q{constructor(){super({entityType:"site-content",schema:Ab,frontmatterSchema:li})}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 WWA=new VS0;ZA();var pi=F.object({routeId:F.string().optional().describe("Optional: specific route filter"),sectionId:F.string().optional().describe("Optional: specific section filter"),dryRun:F.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:F.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),l4B=F.object({jobs:F.array(F.object({jobId:F.string(),routeId:F.string(),sectionId:F.string()})),totalSections:F.number(),queuedSections:F.number(),skippedSections:F.number().optional(),batchId:F.string().optional()});class ZWA{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 $=this.context.logger.child("SiteContentOperations"),w=await this.fetchRoutes(),D=w;if(A.routeId){if(D=w.filter((G)=>G.id===A.routeId),D.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let G of D)for(let W of G.sections){if(A.sectionId&&W.id!==A.sectionId)continue;if(W.content){$.debug("Section has static content, skipping",{routeId:G.id,sectionId:W.id});continue}if(W.template){let Z=this.context.templates.getCapabilities(W.template);if(!Z){$.warn("Template not found, skipping section",{routeId:G.id,sectionId:W.id,templateName:W.template});continue}if(!Z.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:G.id,sectionId:W.id,templateName:W.template,capabilities:Z});continue}}else{$.debug("Section has no template, skipping",{routeId:G.id,sectionId:W.id});continue}if(!A.force&&!A.dryRun){let Z=`${G.id}:${W.id}`;if(await this.context.entityService.getEntity("site-content",Z)){$.debug("Content already exists, skipping",{routeId:G.id,sectionId:W.id});continue}}Y.push({route:G,section:W})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let I=[],K=[];for(let{route:G,section:W}of Y){let Z=`${G.id}:${W.id}`,q=W.template,N={routeId:G.id,sectionId:W.id,entityId:Z,entityType:"site-content",templateName:q,context:{prompt:typeof W.content==="string"?W.content:void 0,data:{routeId:G.id,sectionId:W.id,routeTitle:G.title||Q?.title||"",routeDescription:G.description||Q?.description||"",sectionContent:W.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:N})}if(K.length>0){let G=this.createJobOptions(B,"site:content-generation"),W=await this.context.jobs.enqueueBatch(K,G);for(let Z=0;Z<Y.length;Z++){let q=Y[Z];if(q)I.push({jobId:`${W}-${Z}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:I,totalSections:X,queuedSections:I.length,batchId:W}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class FWA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q;this.operations=new ZWA(A)}async generateContent(A,Q){let B=pi.parse(A);return this.operations.generate(B,this.siteConfig,Q)}}w0();function NS0(A,Q){return[g2(Q,"generate","Generate content for all routes, a specific route, or a specific section",pi,async(B,$)=>{let w=A();if(!w)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:$.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:$.interfaceType,channelId:$.channelId},Y=await w.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 LS0={name:"@brains/site-content",private:!0,version:"0.2.0-alpha.32",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 qWA extends f8{siteContentService;constructor(){super("site-content",LS0,{},F.object({}))}async onRegister(A){A.entities.register("site-content",Ab,WWA),this.siteContentService=new FWA(A)}async getTools(){return NS0(()=>this.siteContentService,this.id)}}function Qb(){return new qWA}w0();ZA();o8();ZA();w0();var ES0=F.enum(["available","early access","coming soon","planned"]),MS0=F.object({title:F.string(),description:F.string()}),iH=F.object({name:F.string(),availability:ES0,order:F.number()}),di=F.object({tagline:F.string(),promise:F.string(),role:F.string(),purpose:F.string(),audience:F.string(),values:F.array(F.string()).min(1),features:F.array(MS0).min(1).max(6),story:F.string()}),WVQ=iH.pick({name:!0,availability:!0,order:!0}).extend({slug:F.string()}),iE=FQ.extend({entityType:F.literal("product"),metadata:WVQ}),ii=iE.extend({frontmatter:iH,body:di,labels:F.record(F.string(),F.string())}),ri=ii.extend({url:F.string().optional(),typeLabel:F.string().optional(),listUrl:F.string().optional(),listLabel:F.string().optional()});w0();ZA();ZA();class rE extends W8{constructor(){super(di,{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 zWA extends _Q{constructor(){super({entityType:"product",schema:iE,frontmatterSchema:iH,bodyFormatter:new rE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,iH);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,iH),B=a1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:B,availability:Q.availability,order:Q.order}}}}var ni=new zWA;ZA();w0();var CS0=F.object({title:F.string(),description:F.string()}),OS0=F.object({title:F.string(),description:F.string()}),ZVQ=F.object({title:F.string(),description:F.string()}),jS0=F.object({heading:F.string(),buttonText:F.string(),link:F.string()}),rH=F.object({headline:F.string(),tagline:F.string()}),FVQ=F.object({title:F.string(),description:F.string()}),oi=F.object({vision:F.string(),pillars:F.array(CS0).min(1).max(6),approach:F.array(FVQ).min(1).max(6),productsIntro:F.string(),technologies:F.array(ZVQ).min(1).max(6),benefits:F.array(OS0).min(1).max(6),cta:jS0}),RS0=rH.pick({headline:!0}).extend({slug:F.string()}),nE=FQ.extend({entityType:F.literal("products-overview"),metadata:RS0}),Bb=nE.extend({frontmatter:rH,body:oi,labels:F.record(F.string(),F.string())});w0();ZA();ZA();class oE extends W8{constructor(){super(oi,{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 VWA extends _Q{constructor(){super({entityType:"products-overview",schema:nE,frontmatterSchema:rH,bodyFormatter:new oE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let B=this.parseFrontMatter(A.content,rH);return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,rH),B=a1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:B}}}}var NWA=new VWA;w0();ZA();var qVQ=F.object({entityType:F.string(),query:F.object({id:F.string().optional()}).optional()});function PS0(A,Q){let B=JQ(A.content,iH),$=Q.parse(B.content),w=Q.getLabels();return ii.parse({...A,frontmatter:B.metadata,body:$,labels:w})}function _S0(A,Q){let B=JQ(A.content,rH),$=Q.parse(B.content),w=Q.getLabels();return Bb.parse({...A,frontmatter:B.metadata,body:$,labels:w})}class si{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new oE;productFormatter=new rE;constructor(A){this.logger=A;this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,B){let $=qVQ.parse(A),w=B.entityService;if($.entityType==="products-overview"){let K=(await w.listEntities("products-overview",{limit:1}))[0];if(!K)throw Error("Products overview entity not found");let G=_S0(K,this.overviewFormatter);return Q.parse(G)}if($.query?.id){let K=(await w.listEntities("product",{filter:{metadata:{slug:$.query.id}},limit:1}))[0];if(!K)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:PS0(K,this.productFormatter)})}let[D,Y]=await Promise.all([w.listEntities("products-overview",{limit:1}),w.listEntities("product",{sortFields:[{field:"order",direction:"asc"}]})]),X=D[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:_S0(X,this.overviewFormatter),products:Y.map((I)=>PS0(I,this.productFormatter))})}}import{jsxDEV as l0,Fragment as NVQ}from"preact/jsx-dev-runtime";var kS0=({overview:A,products:Q})=>{let{frontmatter:B,body:$,labels:w}=A;return l0(NVQ,{children:[l0(iQ,{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:`
3929
3929
  @keyframes wave-drift {
3930
3930
  from { transform: translateX(0); }
3931
3931
  to { transform: translateX(-50%); }
@@ -3953,7 +3953,7 @@ ${Y}`;try{await A.entityService.createEntity({id:X,entityType:"topic",content:I,
3953
3953
  @media (prefers-reduced-motion: reduce) {
3954
3954
  .detail-wave { animation: none; }
3955
3955
  }
3956
- `},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:w,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(l7,{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:$.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:$.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:$.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:$.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:$.values},void 0,!1,void 0,this),b1(H$,{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:$.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((X,I)=>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(I+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:X.title},void 0,!1,void 0,this),b1("p",{className:"text-white/70 leading-relaxed",children:X.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},X.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:$.story},void 0,!1,void 0,this),b1("div",{className:"space-y-6",children:Y.map((X,I)=>b1("p",{className:I===0?"text-2xl md:text-3xl leading-relaxed text-heading font-light":"text-lg leading-relaxed text-theme-muted",children:X},I,!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(G9,{href:w,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)};ZA();var LWA=F.object({route:F.string().default("/products")});var bS0={name:"@brains/products",private:!0,version:"0.2.0-alpha.31",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 MVQ=F.object({overview:Bb,products:F.array(ri)}),CVQ=F.object({product:ri});class EWA extends z2{entityType=ni.entityType;schema=iE;adapter=ni;constructor(A={}){super("products",bS0,A,LWA)}getTemplates(){return{"product-list":E1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:MVQ,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:kS0}}),"product-detail":E1({name:"product-detail",description:"Individual product detail page",schema:CVQ,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:fS0}})}}getDataSources(){return[new si(this.logger.child("ProductsDataSource"))]}async onRegister(A){A.entities.register("products-overview",nE,NWA)}}function MWA(A={}){return new EWA(A)}import{join as jVQ}from"path";var TS0=`/*
3956
+ `},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:w,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(l7,{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:$.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:$.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:$.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:$.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:$.values},void 0,!1,void 0,this),b1(H$,{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:$.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((X,I)=>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(I+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:X.title},void 0,!1,void 0,this),b1("p",{className:"text-white/70 leading-relaxed",children:X.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},X.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:$.story},void 0,!1,void 0,this),b1("div",{className:"space-y-6",children:Y.map((X,I)=>b1("p",{className:I===0?"text-2xl md:text-3xl leading-relaxed text-heading font-light":"text-lg leading-relaxed text-theme-muted",children:X},I,!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(G9,{href:w,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)};ZA();var LWA=F.object({route:F.string().default("/products")});var bS0={name:"@brains/products",private:!0,version:"0.2.0-alpha.32",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 MVQ=F.object({overview:Bb,products:F.array(ri)}),CVQ=F.object({product:ri});class EWA extends z2{entityType=ni.entityType;schema=iE;adapter=ni;constructor(A={}){super("products",bS0,A,LWA)}getTemplates(){return{"product-list":E1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:MVQ,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:kS0}}),"product-detail":E1({name:"product-detail",description:"Individual product detail page",schema:CVQ,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:fS0}})}}getDataSources(){return[new si(this.logger.child("ProductsDataSource"))]}async onRegister(A){A.entities.register("products-overview",nE,NWA)}}function MWA(A={}){return new EWA(A)}import{join as jVQ}from"path";var TS0=`/*
3957
3957
  * Rizom brand theme \u2014 amber + purple bioluminescent palette.
3958
3958
  *
3959
3959
  * Shared by rizom.ai (variant: ai), rizom.foundation (variant: foundation),
@@ -4728,7 +4728,7 @@ Your task is to:
4728
4728
  2. Generate a clear, natural summary that captures key points, decisions, and action items
4729
4729
  3. Return structured data in the required JSON format
4730
4730
 
4731
- Be concise but comprehensive, focusing on the most important information.`});w0();ZA();var bVQ=F.object({entityType:F.literal("summary"),query:F.object({id:F.string().optional(),conversationId:F.string().optional(),limit:F.number().optional()}).optional()});class PWA{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 kI,this.logger.debug("SummaryDataSource initialized")}async fetch(A,Q,B){let $=bVQ.parse(A),w=B.entityService,D=$.query?.conversationId??$.query?.id;if(D){let K=await w.getEntity($.query?.conversationId?"summary":$.entityType,D);if(!K)throw Error(`Summary not found: ${D}`);let G;try{let Z=JQ(K.content,F.record(F.string(),F.unknown()));G=this.adapter.parseEntriesFromContent(Z.content)}catch{G=this.adapter.parseEntriesFromContent(K.content)}let W={conversationId:K.metadata.conversationId,channelName:K.metadata.channelName,entries:G,totalMessages:K.metadata.totalMessages,entryCount:G.length,updated:K.updated};return Q.parse(W)}let X=(await w.listEntities($.entityType,{limit:$.query?.limit??100})).map((K)=>{let G;try{let Z=JQ(K.content,F.record(F.string(),F.unknown()));G=this.adapter.parseEntriesFromContent(Z.content)}catch{G=this.adapter.parseEntriesFromContent(K.content)}let W=G[0];return{id:K.id,conversationId:K.metadata.conversationId,channelName:K.metadata.channelName,entryCount:G.length,totalMessages:K.metadata.totalMessages,latestEntry:W?.title??"No entries",updated:K.updated,created:K.created}}),I={summaries:X,totalCount:X.length};return this.logger.debug("Creating list data",{summaryCount:X.length,firstSummary:X[0]?.id}),Q.parse(I)}}var gS0={name:"@brains/summary",private:!0,version:"0.2.0-alpha.31",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 xVQ=new kI;class _WA extends z2{entityType="summary";schema=$b;adapter=xVQ;digestHandler=null;constructor(A){super("summary",gS0,A??{},OWA)}getConfig(){return this.config}getTemplates(){return{"summary-list":vS0,"summary-detail":SS0,"ai-response":hS0}}getDataSources(){return[new PWA(this.logger)]}async onRegister(A){if(this.digestHandler=oH.getInstance(A,this.logger),this.config.enableAutoSummary)A.messaging.subscribe("conversation:digest",async(Q)=>{let B=Sv.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 kWA(A){return new _WA(A)}var yS0=["prompt","directory-sync","note","link","topics","agents","admin","dashboard","mcp","webserver","discord","a2a"],SVQ=[...yS0,"image","site-info","site-content","site-builder"],mS0=fG({name:"relay",version:"0.1.0",model:"gpt-5.4-mini",site:dH,theme:sE,presets:{core:yS0,default:SVQ},evalDisable:["webserver","discord"],capabilities:[["prompt",a3,void 0],["note",i3,{}],["link",n3,{}],["image",lR,void 0],["topics",Hi,{}],["summary",kWA,{}],["decks",kf,void 0],["agents",gi,void 0],["admin",tJ,{}],["dashboard",s3,void 0],["directory-sync",H3,{seedContent:!0,seedContentPath:vVQ(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Qb,void 0],["site-info",h3,void 0],["site-builder",l3,{}]],interfaces:[["mcp",mG,()=>({})],["discord",LJ,()=>({captureUrls:!0})],["a2a",TL,()=>({})],["webserver",EJ,()=>({})]],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 tEQ}from"fs";import{join as eEQ}from"path";import{execSync as AMQ}from"child_process";import{parseArgs as yVQ}from"util";var mVQ={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 sH(A,Q){let B=A[Q];return typeof B==="string"?B:void 0}function aE(A,Q){let B=A[Q];return typeof B==="boolean"?B:void 0}function uS0(A){let{values:Q,positionals:B}=yVQ({args:A,options:mVQ,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:sH(Q,"model"),domain:sH(Q,"domain"),"content-repo":sH(Q,"content-repo"),backend:sH(Q,"backend"),"push-to":sH(Q,"push-to"),"ai-api-key":sH(Q,"ai-api-key"),"no-interactive":aE(Q,"no-interactive"),preview:aE(Q,"preview"),deploy:aE(Q,"deploy"),regen:aE(Q,"regen"),all:aE(Q,"all"),only:sH(Q,"only"),"dry-run":aE(Q,"dry-run"),remote:sH(Q,"remote"),token:sH(Q,"token")}}}Yb();import{mkdirSync as uEQ}from"fs";import{join as cEQ}from"path";import{execSync as lEQ}from"child_process";var Qr={name:"@rizom/brain",version:"0.2.0-alpha.31",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 dS0,writeFileSync as Ib,chmodSync as Kb,existsSync as $r,readFileSync as tE,unlinkSync as XNQ}from"fs";import{basename as xWA,dirname as vWA,join as mB,resolve as INQ}from"path";import{fileURLToPath as KNQ}from"url";Xb();import{existsSync as cS0,readFileSync as rVQ}from"fs";import{dirname as nVQ,join as lS0}from"path";var Br={rover:`# This env file uses @env-spec - see https://varlock.dev/env-spec for more info
4731
+ Be concise but comprehensive, focusing on the most important information.`});w0();ZA();var bVQ=F.object({entityType:F.literal("summary"),query:F.object({id:F.string().optional(),conversationId:F.string().optional(),limit:F.number().optional()}).optional()});class PWA{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 kI,this.logger.debug("SummaryDataSource initialized")}async fetch(A,Q,B){let $=bVQ.parse(A),w=B.entityService,D=$.query?.conversationId??$.query?.id;if(D){let K=await w.getEntity($.query?.conversationId?"summary":$.entityType,D);if(!K)throw Error(`Summary not found: ${D}`);let G;try{let Z=JQ(K.content,F.record(F.string(),F.unknown()));G=this.adapter.parseEntriesFromContent(Z.content)}catch{G=this.adapter.parseEntriesFromContent(K.content)}let W={conversationId:K.metadata.conversationId,channelName:K.metadata.channelName,entries:G,totalMessages:K.metadata.totalMessages,entryCount:G.length,updated:K.updated};return Q.parse(W)}let X=(await w.listEntities($.entityType,{limit:$.query?.limit??100})).map((K)=>{let G;try{let Z=JQ(K.content,F.record(F.string(),F.unknown()));G=this.adapter.parseEntriesFromContent(Z.content)}catch{G=this.adapter.parseEntriesFromContent(K.content)}let W=G[0];return{id:K.id,conversationId:K.metadata.conversationId,channelName:K.metadata.channelName,entryCount:G.length,totalMessages:K.metadata.totalMessages,latestEntry:W?.title??"No entries",updated:K.updated,created:K.created}}),I={summaries:X,totalCount:X.length};return this.logger.debug("Creating list data",{summaryCount:X.length,firstSummary:X[0]?.id}),Q.parse(I)}}var gS0={name:"@brains/summary",private:!0,version:"0.2.0-alpha.32",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 xVQ=new kI;class _WA extends z2{entityType="summary";schema=$b;adapter=xVQ;digestHandler=null;constructor(A){super("summary",gS0,A??{},OWA)}getConfig(){return this.config}getTemplates(){return{"summary-list":vS0,"summary-detail":SS0,"ai-response":hS0}}getDataSources(){return[new PWA(this.logger)]}async onRegister(A){if(this.digestHandler=oH.getInstance(A,this.logger),this.config.enableAutoSummary)A.messaging.subscribe("conversation:digest",async(Q)=>{let B=Sv.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 kWA(A){return new _WA(A)}var yS0=["prompt","directory-sync","note","link","topics","agents","admin","dashboard","mcp","webserver","discord","a2a"],SVQ=[...yS0,"image","site-info","site-content","site-builder"],mS0=fG({name:"relay",version:"0.1.0",model:"gpt-5.4-mini",site:dH,theme:sE,presets:{core:yS0,default:SVQ},evalDisable:["webserver","discord"],capabilities:[["prompt",a3,void 0],["note",i3,{}],["link",n3,{}],["image",lR,void 0],["topics",Hi,{}],["summary",kWA,{}],["decks",kf,void 0],["agents",gi,void 0],["admin",tJ,{}],["dashboard",s3,void 0],["directory-sync",H3,{seedContent:!0,seedContentPath:vVQ(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Qb,void 0],["site-info",h3,void 0],["site-builder",l3,{}]],interfaces:[["mcp",mG,()=>({})],["discord",LJ,()=>({captureUrls:!0})],["a2a",TL,()=>({})],["webserver",EJ,()=>({})]],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 tEQ}from"fs";import{join as eEQ}from"path";import{execSync as AMQ}from"child_process";import{parseArgs as yVQ}from"util";var mVQ={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 sH(A,Q){let B=A[Q];return typeof B==="string"?B:void 0}function aE(A,Q){let B=A[Q];return typeof B==="boolean"?B:void 0}function uS0(A){let{values:Q,positionals:B}=yVQ({args:A,options:mVQ,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:sH(Q,"model"),domain:sH(Q,"domain"),"content-repo":sH(Q,"content-repo"),backend:sH(Q,"backend"),"push-to":sH(Q,"push-to"),"ai-api-key":sH(Q,"ai-api-key"),"no-interactive":aE(Q,"no-interactive"),preview:aE(Q,"preview"),deploy:aE(Q,"deploy"),regen:aE(Q,"regen"),all:aE(Q,"all"),only:sH(Q,"only"),"dry-run":aE(Q,"dry-run"),remote:sH(Q,"remote"),token:sH(Q,"token")}}}Yb();import{mkdirSync as uEQ}from"fs";import{join as cEQ}from"path";import{execSync as lEQ}from"child_process";var Qr={name:"@rizom/brain",version:"0.2.0-alpha.32",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 dS0,writeFileSync as Ib,chmodSync as Kb,existsSync as $r,readFileSync as tE,unlinkSync as XNQ}from"fs";import{basename as xWA,dirname as vWA,join as mB,resolve as INQ}from"path";import{fileURLToPath as KNQ}from"url";Xb();import{existsSync as cS0,readFileSync as rVQ}from"fs";import{dirname as nVQ,join as lS0}from"path";var Br={rover:`# This env file uses @env-spec - see https://varlock.dev/env-spec for more info
4732
4732
  #
4733
4733
  # @defaultRequired=false @defaultSensitive=false
4734
4734
  # ----------