@rizom/brain 0.2.0-alpha.195 → 0.2.0-alpha.196

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
@@ -460,7 +460,7 @@ ${X}`:"")}function i0A(A,Q,$,w){return async(B,X)=>{if(w){let Y={toolName:A,args
460
460
  hash text NOT NULL,
461
461
  created_at numeric
462
462
  )
463
- `;await A.session.run(B);let Y=(await A.values(BA`SELECT id, hash, created_at FROM ${BA.identifier(w)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let H of $)if(!Y||Number(Y[2])<H.folderMillis){for(let K of H.sql)Z.push(A.run(BA.raw(K)));Z.push(A.run(BA`INSERT INTO ${BA.identifier(w)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(Z)}var F20=c(()=>{HD1();x4()});async function KD1(A,Q){let $=Q?.child("entity-migrate")??H6.getInstance().child("entity-migrate"),{db:w,client:B,url:X}=JD0(A);$.debug("Running entity database migrations...");try{await FD0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),await LD0(B),$.debug("Entity database migrations completed successfully")}catch(Y){throw $.error("Entity database migration failed:",Y),Y}finally{B.close()}}var UD1=c(()=>{F20();Vo0();_X()});async function GD1(A,Q){let $=Q?.child("job-queue-migrate")??H6.getInstance().child("job-queue-migrate"),{db:w,client:B,url:X}=iW0(A);$.debug("Running job queue migrations...");try{await dW0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Job queue migrations completed successfully")}catch(Y){throw $.error("Job queue migration failed:",Y),Y}finally{B.close()}}var DD1=c(()=>{F20();xc0();_X()});async function qD1(A,Q){let $=Q?.child("conversation-migrate")??H6.getInstance().child("conversation-migrate"),{db:w,client:B,url:X}=zC(A);$.debug("Running conversation database migrations...");try{if(X.startsWith("file:"))await B.execute("PRAGMA journal_mode = WAL");let Z=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Conversation database migrations completed successfully")}catch(Y){throw $.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var zD1=c(()=>{F20();DD0();_X()});async function VD1(A,Q){let $=Q?.child("runtime-state-migrate")??H6.getInstance().child("runtime-state-migrate"),{db:w,client:B,url:X}=mz0(A);$.debug("Running runtime state migrations...");try{await uz0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Runtime state migrations completed successfully")}catch(Y){throw $.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var JD1=c(()=>{F20();_X();KAA()});import{mkdir as mAA}from"fs/promises";function $30(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function w30(A=process.env){return Dk($30(A))}async function B30(A=process.env){let Q=$30(A);try{await mAA(Q.dataDir,{recursive:!0}),await mAA(Q.cacheDir,{recursive:!0}),await mAA(Q.distDir,{recursive:!0})}catch($){let w=$ instanceof Error&&$.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${Q.dataDir}`:`Cannot create data directories: ${$ instanceof Error?$.message:String($)}`;throw Error(w,{cause:$})}return Dk(Q)}var X30=c(()=>{A30()});class L20{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>B30(),migrateEntities:KD1,migrateJobQueue:GD1,migrateConversations:qD1,migrateRuntimeState:VD1}}async runAllMigrations(A){this.logger.debug("Running database migrations...");let Q=await this.migrations.getStandardConfigWithDirectories();if(A?.database)Q.database.url=A.database;if(A?.jobQueueDatabase)Q.jobQueueDatabase.url=A.jobQueueDatabase;if(A?.conversationDatabase)Q.conversationDatabase.url=A.conversationDatabase;if(A?.runtimeStateDatabase)Q.runtimeStateDatabase.url=A.runtimeStateDatabase;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(Q),await this.migrateRuntimeStateDatabase(Q),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(A){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:A.database.url,...A.database.authToken&&{authToken:A.database.authToken}},this.logger)}async migrateJobQueueDatabase(A){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:A.jobQueueDatabase.url,...A.jobQueueDatabase.authToken&&{authToken:A.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(A){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:A.conversationDatabase.url,...A.conversationDatabase.authToken&&{authToken:A.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(A){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:A.runtimeStateDatabase.url,...A.runtimeStateDatabase.authToken&&{authToken:A.runtimeStateDatabase.authToken}},this.logger)}}var uAA=c(()=>{UD1();DD1();zD1();JD1();X30()});function k56(){return process.env[M56]}function FD1(){return k56()!=="production"}var M56="NODE_ENV";var Y30;var cAA=c(()=>{h0();Y30=W.object({theme:W.object({primaryColor:W.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:W.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var ID1;var LD1=c(()=>{ID1={name:"@brains/chat-repl",version:"0.2.0-alpha.195",dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^7.0.6","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^18.0.5",react:"^19.2.7"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{dev:"tsc --watch",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"}});var n6=x((f56,Z30)=>{(function(){function A(e,z0){Object.defineProperty(w.prototype,e,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",z0[0],z0[1])}})}function Q(e){if(e===null||typeof e!=="object")return null;return e=k0&&e[k0]||e["@@iterator"],typeof e==="function"?e:null}function $(e,z0){e=(e=e.constructor)&&(e.displayName||e.name)||"ReactClass";var I0=e+"."+z0;O0[I0]||(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.",z0,e),O0[I0]=!0)}function w(e,z0,I0){this.props=e,this.context=z0,this.refs=o0,this.updater=I0||f0}function B(){}function X(e,z0,I0){this.props=e,this.context=z0,this.refs=o0,this.updater=I0||f0}function Y(){}function Z(e){return""+e}function H(e){try{Z(e);var z0=!1}catch(_0){z0=!0}if(z0){z0=console;var I0=z0.error,M0=typeof Symbol==="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return I0.call(z0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",M0),Z(e)}}function K(e){if(e==null)return null;if(typeof e==="function")return e.$$typeof===HA?null:e.displayName||e.name||null;if(typeof e==="string")return e;switch(e){case q0:return"Fragment";case Y0:return"Profiler";case g:return"StrictMode";case i0:return"Suspense";case N0:return"SuspenseList";case S0:return"Activity"}if(typeof e==="object")switch(typeof e.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case t:return"Portal";case d:return e.displayName||"Context";case F0:return(e._context.displayName||"Context")+".Consumer";case c0:var z0=e.render;return e=e.displayName,e||(e=z0.displayName||z0.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case b0:return z0=e.displayName||null,z0!==null?z0:K(e.type)||"Memo";case v0:z0=e._payload,e=e._init;try{return K(e(z0))}catch(I0){}}return null}function U(e){if(e===q0)return"<>";if(typeof e==="object"&&e!==null&&e.$$typeof===v0)return"<...>";try{var z0=K(e);return z0?"<"+z0+">":"<...>"}catch(I0){return"<...>"}}function G(){var e=e0.A;return e===null?null:e.getOwner()}function D(){return Error("react-stack-top-frame")}function q(e){if(u0.call(e,"key")){var z0=Object.getOwnPropertyDescriptor(e,"key").get;if(z0&&z0.isReactWarning)return!1}return e.key!==void 0}function J(e,z0){function I0(){qA||(qA=!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)",z0))}I0.isReactWarning=!0,Object.defineProperty(e,"key",{get:I0,configurable:!0})}function F(){var e=K(this.type);return xA[e]||(xA[e]=!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.")),e=this.props.ref,e!==void 0?e:null}function L(e,z0,I0,M0,_0,a0){var d0=I0.ref;return e={$$typeof:o,type:e,key:z0,props:I0,_owner:M0},(d0!==void 0?d0:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:F}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:_0}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:a0}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function _(e,z0){return z0=L(e.type,z0,e.props,e._owner,e._debugStack,e._debugTask),e._store&&(z0._store.validated=e._store.validated),z0}function j(e){b(e)?e._store&&(e._store.validated=1):typeof e==="object"&&e!==null&&e.$$typeof===v0&&(e._payload.status==="fulfilled"?b(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function b(e){return typeof e==="object"&&e!==null&&e.$$typeof===o}function f(e){var z0={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,function(I0){return z0[I0]})}function v(e,z0){return typeof e==="object"&&e!==null&&e.key!=null?(H(e.key),f(""+e.key)):z0.toString(36)}function R(e){switch(e.status){case"fulfilled":return e.value;case"rejected":throw e.reason;default:switch(typeof e.status==="string"?e.then(Y,Y):(e.status="pending",e.then(function(z0){e.status==="pending"&&(e.status="fulfilled",e.value=z0)},function(z0){e.status==="pending"&&(e.status="rejected",e.reason=z0)})),e.status){case"fulfilled":return e.value;case"rejected":throw e.reason}}throw e}function O(e,z0,I0,M0,_0){var a0=typeof e;if(a0==="undefined"||a0==="boolean")e=null;var d0=!1;if(e===null)d0=!0;else switch(a0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch(e.$$typeof){case o:case t:d0=!0;break;case v0:return d0=e._init,O(d0(e._payload),z0,I0,M0,_0)}}if(d0){d0=e,_0=_0(d0);var UA=M0===""?"."+v(d0,0):M0;return YA(_0)?(I0="",UA!=null&&(I0=UA.replace(x0,"$&/")+"/"),O(_0,z0,I0,"",function(cA){return cA})):_0!=null&&(b(_0)&&(_0.key!=null&&(d0&&d0.key===_0.key||H(_0.key)),I0=_(_0,I0+(_0.key==null||d0&&d0.key===_0.key?"":(""+_0.key).replace(x0,"$&/")+"/")+UA),M0!==""&&d0!=null&&b(d0)&&d0.key==null&&d0._store&&!d0._store.validated&&(I0._store.validated=2),_0=I0),z0.push(_0)),1}if(d0=0,UA=M0===""?".":M0+":",YA(e))for(var VA=0;VA<e.length;VA++)M0=e[VA],a0=UA+v(M0,VA),d0+=O(M0,z0,I0,a0,_0);else if(VA=Q(e),typeof VA==="function")for(VA===e.entries&&(T0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),T0=!0),e=VA.call(e),VA=0;!(M0=e.next()).done;)M0=M0.value,a0=UA+v(M0,VA++),d0+=O(M0,z0,I0,a0,_0);else if(a0==="object"){if(typeof e.then==="function")return O(R(e),z0,I0,M0,_0);throw z0=String(e),Error("Objects are not valid as a React child (found: "+(z0==="[object Object]"?"object with keys {"+Object.keys(e).join(", ")+"}":z0)+"). If you meant to render a collection of children, use an array instead.")}return d0}function S(e,z0,I0){if(e==null)return e;var M0=[],_0=0;return O(e,M0,"","",function(a0){return z0.call(I0,a0,_0++)}),M0}function u(e){if(e._status===-1){var z0=e._ioInfo;z0!=null&&(z0.start=z0.end=performance.now()),z0=e._result;var I0=z0();if(I0.then(function(_0){if(e._status===0||e._status===-1){e._status=1,e._result=_0;var a0=e._ioInfo;a0!=null&&(a0.end=performance.now()),I0.status===void 0&&(I0.status="fulfilled",I0.value=_0)}},function(_0){if(e._status===0||e._status===-1){e._status=2,e._result=_0;var a0=e._ioInfo;a0!=null&&(a0.end=performance.now()),I0.status===void 0&&(I0.status="rejected",I0.reason=_0)}}),z0=e._ioInfo,z0!=null){z0.value=I0;var M0=I0.displayName;typeof M0==="string"&&(z0.name=M0)}e._status===-1&&(e._status=0,e._result=I0)}if(e._status===1)return z0=e._result,z0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
463
+ `;await A.session.run(B);let Y=(await A.values(BA`SELECT id, hash, created_at FROM ${BA.identifier(w)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let H of $)if(!Y||Number(Y[2])<H.folderMillis){for(let K of H.sql)Z.push(A.run(BA.raw(K)));Z.push(A.run(BA`INSERT INTO ${BA.identifier(w)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(Z)}var F20=c(()=>{HD1();x4()});async function KD1(A,Q){let $=Q?.child("entity-migrate")??H6.getInstance().child("entity-migrate"),{db:w,client:B,url:X}=JD0(A);$.debug("Running entity database migrations...");try{await FD0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),await LD0(B),$.debug("Entity database migrations completed successfully")}catch(Y){throw $.error("Entity database migration failed:",Y),Y}finally{B.close()}}var UD1=c(()=>{F20();Vo0();_X()});async function GD1(A,Q){let $=Q?.child("job-queue-migrate")??H6.getInstance().child("job-queue-migrate"),{db:w,client:B,url:X}=iW0(A);$.debug("Running job queue migrations...");try{await dW0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Job queue migrations completed successfully")}catch(Y){throw $.error("Job queue migration failed:",Y),Y}finally{B.close()}}var DD1=c(()=>{F20();xc0();_X()});async function qD1(A,Q){let $=Q?.child("conversation-migrate")??H6.getInstance().child("conversation-migrate"),{db:w,client:B,url:X}=zC(A);$.debug("Running conversation database migrations...");try{if(X.startsWith("file:"))await B.execute("PRAGMA journal_mode = WAL");let Z=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Conversation database migrations completed successfully")}catch(Y){throw $.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var zD1=c(()=>{F20();DD0();_X()});async function VD1(A,Q){let $=Q?.child("runtime-state-migrate")??H6.getInstance().child("runtime-state-migrate"),{db:w,client:B,url:X}=mz0(A);$.debug("Running runtime state migrations...");try{await uz0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await jk(w,{migrationsFolder:Z}),$.debug("Runtime state migrations completed successfully")}catch(Y){throw $.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var JD1=c(()=>{F20();_X();KAA()});import{mkdir as mAA}from"fs/promises";function $30(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function w30(A=process.env){return Dk($30(A))}async function B30(A=process.env){let Q=$30(A);try{await mAA(Q.dataDir,{recursive:!0}),await mAA(Q.cacheDir,{recursive:!0}),await mAA(Q.distDir,{recursive:!0})}catch($){let w=$ instanceof Error&&$.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${Q.dataDir}`:`Cannot create data directories: ${$ instanceof Error?$.message:String($)}`;throw Error(w,{cause:$})}return Dk(Q)}var X30=c(()=>{A30()});class L20{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>B30(),migrateEntities:KD1,migrateJobQueue:GD1,migrateConversations:qD1,migrateRuntimeState:VD1}}async runAllMigrations(A){this.logger.debug("Running database migrations...");let Q=await this.migrations.getStandardConfigWithDirectories();if(A?.database)Q.database.url=A.database;if(A?.jobQueueDatabase)Q.jobQueueDatabase.url=A.jobQueueDatabase;if(A?.conversationDatabase)Q.conversationDatabase.url=A.conversationDatabase;if(A?.runtimeStateDatabase)Q.runtimeStateDatabase.url=A.runtimeStateDatabase;await this.migrateEntityDatabase(Q),await this.migrateJobQueueDatabase(Q),await this.migrateConversationDatabase(Q),await this.migrateRuntimeStateDatabase(Q),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(A){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:A.database.url,...A.database.authToken&&{authToken:A.database.authToken}},this.logger)}async migrateJobQueueDatabase(A){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:A.jobQueueDatabase.url,...A.jobQueueDatabase.authToken&&{authToken:A.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(A){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:A.conversationDatabase.url,...A.conversationDatabase.authToken&&{authToken:A.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(A){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:A.runtimeStateDatabase.url,...A.runtimeStateDatabase.authToken&&{authToken:A.runtimeStateDatabase.authToken}},this.logger)}}var uAA=c(()=>{UD1();DD1();zD1();JD1();X30()});function k56(){return process.env[M56]}function FD1(){return k56()!=="production"}var M56="NODE_ENV";var Y30;var cAA=c(()=>{h0();Y30=W.object({theme:W.object({primaryColor:W.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:W.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var ID1;var LD1=c(()=>{ID1={name:"@brains/chat-repl",version:"0.2.0-alpha.196",dependencies:{"@brains/plugins":"workspace:*",chalk:"^5.4.1",ink:"^7.0.6","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^18.0.5",react:"^19.2.7"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{dev:"tsc --watch",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"}});var n6=x((f56,Z30)=>{(function(){function A(e,z0){Object.defineProperty(w.prototype,e,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",z0[0],z0[1])}})}function Q(e){if(e===null||typeof e!=="object")return null;return e=k0&&e[k0]||e["@@iterator"],typeof e==="function"?e:null}function $(e,z0){e=(e=e.constructor)&&(e.displayName||e.name)||"ReactClass";var I0=e+"."+z0;O0[I0]||(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.",z0,e),O0[I0]=!0)}function w(e,z0,I0){this.props=e,this.context=z0,this.refs=o0,this.updater=I0||f0}function B(){}function X(e,z0,I0){this.props=e,this.context=z0,this.refs=o0,this.updater=I0||f0}function Y(){}function Z(e){return""+e}function H(e){try{Z(e);var z0=!1}catch(_0){z0=!0}if(z0){z0=console;var I0=z0.error,M0=typeof Symbol==="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return I0.call(z0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",M0),Z(e)}}function K(e){if(e==null)return null;if(typeof e==="function")return e.$$typeof===HA?null:e.displayName||e.name||null;if(typeof e==="string")return e;switch(e){case q0:return"Fragment";case Y0:return"Profiler";case g:return"StrictMode";case i0:return"Suspense";case N0:return"SuspenseList";case S0:return"Activity"}if(typeof e==="object")switch(typeof e.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case t:return"Portal";case d:return e.displayName||"Context";case F0:return(e._context.displayName||"Context")+".Consumer";case c0:var z0=e.render;return e=e.displayName,e||(e=z0.displayName||z0.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case b0:return z0=e.displayName||null,z0!==null?z0:K(e.type)||"Memo";case v0:z0=e._payload,e=e._init;try{return K(e(z0))}catch(I0){}}return null}function U(e){if(e===q0)return"<>";if(typeof e==="object"&&e!==null&&e.$$typeof===v0)return"<...>";try{var z0=K(e);return z0?"<"+z0+">":"<...>"}catch(I0){return"<...>"}}function G(){var e=e0.A;return e===null?null:e.getOwner()}function D(){return Error("react-stack-top-frame")}function q(e){if(u0.call(e,"key")){var z0=Object.getOwnPropertyDescriptor(e,"key").get;if(z0&&z0.isReactWarning)return!1}return e.key!==void 0}function J(e,z0){function I0(){qA||(qA=!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)",z0))}I0.isReactWarning=!0,Object.defineProperty(e,"key",{get:I0,configurable:!0})}function F(){var e=K(this.type);return xA[e]||(xA[e]=!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.")),e=this.props.ref,e!==void 0?e:null}function L(e,z0,I0,M0,_0,a0){var d0=I0.ref;return e={$$typeof:o,type:e,key:z0,props:I0,_owner:M0},(d0!==void 0?d0:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:F}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:_0}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:a0}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function _(e,z0){return z0=L(e.type,z0,e.props,e._owner,e._debugStack,e._debugTask),e._store&&(z0._store.validated=e._store.validated),z0}function j(e){b(e)?e._store&&(e._store.validated=1):typeof e==="object"&&e!==null&&e.$$typeof===v0&&(e._payload.status==="fulfilled"?b(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function b(e){return typeof e==="object"&&e!==null&&e.$$typeof===o}function f(e){var z0={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,function(I0){return z0[I0]})}function v(e,z0){return typeof e==="object"&&e!==null&&e.key!=null?(H(e.key),f(""+e.key)):z0.toString(36)}function R(e){switch(e.status){case"fulfilled":return e.value;case"rejected":throw e.reason;default:switch(typeof e.status==="string"?e.then(Y,Y):(e.status="pending",e.then(function(z0){e.status==="pending"&&(e.status="fulfilled",e.value=z0)},function(z0){e.status==="pending"&&(e.status="rejected",e.reason=z0)})),e.status){case"fulfilled":return e.value;case"rejected":throw e.reason}}throw e}function O(e,z0,I0,M0,_0){var a0=typeof e;if(a0==="undefined"||a0==="boolean")e=null;var d0=!1;if(e===null)d0=!0;else switch(a0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch(e.$$typeof){case o:case t:d0=!0;break;case v0:return d0=e._init,O(d0(e._payload),z0,I0,M0,_0)}}if(d0){d0=e,_0=_0(d0);var UA=M0===""?"."+v(d0,0):M0;return YA(_0)?(I0="",UA!=null&&(I0=UA.replace(x0,"$&/")+"/"),O(_0,z0,I0,"",function(cA){return cA})):_0!=null&&(b(_0)&&(_0.key!=null&&(d0&&d0.key===_0.key||H(_0.key)),I0=_(_0,I0+(_0.key==null||d0&&d0.key===_0.key?"":(""+_0.key).replace(x0,"$&/")+"/")+UA),M0!==""&&d0!=null&&b(d0)&&d0.key==null&&d0._store&&!d0._store.validated&&(I0._store.validated=2),_0=I0),z0.push(_0)),1}if(d0=0,UA=M0===""?".":M0+":",YA(e))for(var VA=0;VA<e.length;VA++)M0=e[VA],a0=UA+v(M0,VA),d0+=O(M0,z0,I0,a0,_0);else if(VA=Q(e),typeof VA==="function")for(VA===e.entries&&(T0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),T0=!0),e=VA.call(e),VA=0;!(M0=e.next()).done;)M0=M0.value,a0=UA+v(M0,VA++),d0+=O(M0,z0,I0,a0,_0);else if(a0==="object"){if(typeof e.then==="function")return O(R(e),z0,I0,M0,_0);throw z0=String(e),Error("Objects are not valid as a React child (found: "+(z0==="[object Object]"?"object with keys {"+Object.keys(e).join(", ")+"}":z0)+"). If you meant to render a collection of children, use an array instead.")}return d0}function S(e,z0,I0){if(e==null)return e;var M0=[],_0=0;return O(e,M0,"","",function(a0){return z0.call(I0,a0,_0++)}),M0}function u(e){if(e._status===-1){var z0=e._ioInfo;z0!=null&&(z0.start=z0.end=performance.now()),z0=e._result;var I0=z0();if(I0.then(function(_0){if(e._status===0||e._status===-1){e._status=1,e._result=_0;var a0=e._ioInfo;a0!=null&&(a0.end=performance.now()),I0.status===void 0&&(I0.status="fulfilled",I0.value=_0)}},function(_0){if(e._status===0||e._status===-1){e._status=2,e._result=_0;var a0=e._ioInfo;a0!=null&&(a0.end=performance.now()),I0.status===void 0&&(I0.status="rejected",I0.reason=_0)}}),z0=e._ioInfo,z0!=null){z0.value=I0;var M0=I0.displayName;typeof M0==="string"&&(z0.name=M0)}e._status===-1&&(e._status=0,e._result=I0)}if(e._status===1)return z0=e._result,z0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
464
464
 
465
465
  Your code should look like:
466
466
  const MyComponent = lazy(() => import('./MyComponent'))
@@ -1772,7 +1772,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
1772
1772
  Title: "${A.entityTitle??Z}"
1773
1773
 
1774
1774
  Content:
1775
- ${U}`,iZ6);K=`${w.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:eA(_)})}}await this.reportProgress($,{progress:g6.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),J=oF1(G,D)+K,F;try{F=await this.context.ai.generateImage(J,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:eA(_)}),o5.failure(_)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let L=ZG.createImageEntity({dataUrl:F.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await BH({entityService:this.context.entityService,entity:{...L,id:H}}),this.logger.debug("Created image entity",{imageId:H}),X&&Y){await this.reportProgress($,{progress:g6.SAVE,message:`Updating ${X} with cover image`});let _=await kC(this.context.entityService,X,Y,this.logger);if(!_)return o5.failure(Error(`Target entity not found: ${X}/${Y}`));let j=Zh(_,H);await this.context.entities.update(j),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:H})}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:H}}catch(K){let U=eA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await NF({entityService:this.context.entityService,entityType:"image",id:H,error:U}),o5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}zA();h0();Uw();cZ();var nZ6=W.object({sourceEntityType:W.string().min(1),sourceEntityId:W.string().min(1),attachmentType:W.string().min(1),imageId:W.string().min(1),dedupKey:W.string().min(1).optional(),replace:W.boolean().optional(),targetEntityType:W.string().min(1).optional(),targetEntityId:W.string().min(1).optional(),targetImageField:W.enum(["coverImageId","ogImageId"]).optional()});class UQA extends H8{context;constructor(A,Q){super(Q,{schema:nZ6,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,$){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress($,{progress:g6.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress($,{progress:g6.PROCESS,message:"Rendering source image"});let w=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!w)return o5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(w.type!=="image")return o5.failure(Error(`Attachment provider returned ${w.type}; expected image`));await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let B=w.mimeType.split("/")[1]??"png",X=ZG.createImageEntity({dataUrl:RAA(w.data.toString("base64"),B),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await BH({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress($,{progress:g6.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(w){let B=eA(w);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await NF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),o5.failure(w)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let $=await kC(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!$)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let B=(A.targetImageField??"coverImageId")==="ogImageId"?V20($,Q):Zh($,Q);await this.context.entities.update(B)}}zA();h0();Uw();cZ();p2();var Al={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function RV0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function vV0(A){let Q=rZ6(A.title,A.filename),$=O1(Q);if(!$)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:$,title:Q}}function sF1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function rZ6(A,Q){let $=A?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}var oZ6=W.object({uploadId:W.string().min(1),imageId:W.string().min(1).optional(),title:W.string().optional()});class GQA extends H8{context;constructor(A,Q){super(A,{schema:oZ6,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,$){try{await this.reportProgress($,{progress:10,message:"Reading uploaded image"});let w=await this.context.uploads.scoped(Al).read(A.uploadId);if(!RV0(w.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=vV0({filename:w.record.filename,...A.title!==void 0?{title:A.title}:{}}),X=A.imageId??B.id;await this.reportProgress($,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),Z=ZG.createImageEntity({dataUrl:sF1(w.record.mediaType,w.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:w.record.filename,sourceMediaType:w.record.mediaType,attachmentType:"uploaded"}),H=await BH({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress($,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch(w){if(A.imageId)await NF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:eA(w)});return o5.failure(w)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var aF1={name:"@brains/image-plugin",version:"0.2.0-alpha.195",description:"Plugin for AI-powered image generation and management",dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var aZ6="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",tZ6=W.object({defaultAspectRatio:W.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function o3(A){let Q=A?.trim();if(!Q)return;return Q}function eZ6(A){let Q=o3(A.prompt);if(Q)return Q;let $=o3(A.content);if($&&!KQA($))return $;return}function AW6(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return O1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function tF1(A){let Q=o3(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return O1(Q)}async function QW6(A,Q){let $=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,w=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return w?`${$}:${w.contentHash}`:$}function DQA(A,Q="generated"){let $=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${$}`,downloadUrl:`/api/chat/attachments/image?id=${$}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function $W6(A){let Q=encodeURIComponent(A.entityId);return{mediaType:A.mediaType,url:`/api/chat/attachments/image?id=${Q}`,downloadUrl:`/api/chat/attachments/image?id=${Q}&download=1`,filename:A.filename,source:{entityType:"image",entityId:A.entityId,attachmentType:"uploaded"}}}class qQA extends c6{entityType=ZG.entityType;schema=q20;adapter=ZG;constructor(A={}){super("image",aF1,A,tZ6)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,$){if(A.from?.kind===Al.refKind)return this.promoteUpload(A,$);let w=eZ6(A),B=o3(A.targetEntityType),X=o3(A.targetEntityId),Y=B===this.entityType?X:void 0,Z=A.from;if(Z?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Z},$);if(!B||!X||Y){if(!w)return{kind:"continue",input:A};let D=o3(A.title)??Y,q=tF1({prompt:w,...D&&{title:D}});await this.createPendingImage($,{id:q,title:D??w.slice(0,60).trim(),alt:D??w.slice(0,60).trim(),attachmentType:"generated"});let J=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:J,attachment:DQA(q)}}}}let H=await TZ($.entityService,B,X,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!w)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let K=fV0(H.entity.content),U=tF1({prompt:w,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage($,{id:U,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:H.entity.id});let G=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...K&&{entityContent:K}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:DQA(U)}}}}async promoteUpload(A,Q){let $=A.from;if($?.kind!==Al.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w=$.id,B;try{B=await Q.uploads.scoped(Al).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!RV0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=vV0({filename:B.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Z){return{kind:"handled",result:{success:!1,error:Z instanceof Error?Z.message:String(Z)}}}await this.createPendingImage(Q,{id:X.id,title:X.title,alt:X.title,sourceUploadId:w,sourceFilename:B.filename,sourceMediaType:B.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:w,imageId:X.id,title:X.title}});return{kind:"handled",result:{success:!0,data:{entityId:X.id,status:"generating",jobId:Y,attachment:$W6({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let $=o3(A.from.sourceEntityType),w=o3(A.from.sourceEntityId),B=o3(A.from.attachmentType);if(!$||!w||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await TZ(Q.entityService,$,w,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=o3(A.targetEntityType),Z=o3(A.targetEntityId),H;if(Y&&Z){let q=await TZ(Q.entityService,Y,Z,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let K={sourceEntityType:$,sourceEntityId:X.entity.id,attachmentType:B},U=await QW6(Q,K),G=AW6(K);await this.createPendingImage(Q,{id:G,title:G,alt:G,sourceEntityType:K.sourceEntityType,sourceEntityId:K.sourceEntityId,attachmentType:B,dedupKey:U});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...K,imageId:G,dedupKey:U,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:G,status:"generating",jobId:D,attachment:DQA(G,B)}}}}async createPendingImage(A,Q){let $=new Date().toISOString(),w=ZG.createImageEntity({dataUrl:aZ6,title:Q.title,alt:Q.alt,status:"pending",attachmentType:Q.attachmentType,...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceUploadId&&{sourceUploadId:Q.sourceUploadId},...Q.sourceFilename&&{sourceFilename:Q.sourceFilename},...Q.sourceMediaType&&{sourceMediaType:Q.sourceMediaType},...Q.dedupKey&&{dedupKey:Q.dedupKey}});await fC({entityService:A.entityService,entity:{id:Q.id,...w,created:$,updated:$}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new xV0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async($)=>{let w=await this.promoteUpload({entityType:this.entityType,...$.title!==void 0?{title:$.title}:{},from:$.upload},A);return w.kind==="handled"?w.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new xV0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new UQA(A,this.logger)),A.jobs.registerHandler("upload-promote",new GQA(this.logger.child("UploadPromotionJobHandler"),A))}}function FQ0(A={}){return new qQA(A)}zA();import{StdioServerTransport as BW6}from"@modelcontextprotocol/sdk/server/stdio.js";h0();var wW6=W.custom((A)=>typeof A==="object"&&A!==null&&("info"in A)&&typeof A.info==="function"&&("debug"in A)&&typeof A.debug==="function"&&("error"in A)&&typeof A.error==="function"&&("warn"in A)&&typeof A.warn==="function");function eF1(){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 zQA(){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 CV0(A){let Q=wW6.safeParse(A);if(Q.success)return{info:($,...w)=>Q.data.info($,...w),debug:($,...w)=>Q.data.debug($,...w),error:($,...w)=>Q.data.error($,...w),warn:($,...w)=>Q.data.warn($,...w)};return zQA()}class s3{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return s3.instance??=new s3(A),s3.instance}static resetInstance(){if(s3.instance)s3.instance.stop(),s3.instance=null}static createFresh(A){return new s3(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?CV0(this.config.logger):eF1()}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 BW6,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 YW6,timingSafeEqual as ZW6}from"crypto";import{WebStandardStreamableHTTPServerTransport as WW6}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as HW6}from"@modelcontextprotocol/sdk/types.js";c8();function XW6(A){return t0.async((Q)=>{let $=setTimeout(()=>Q(t0.void),A);return $.unref(),t0.sync(()=>clearTimeout($))})}class VQA{scope;fibers;activeSweeps=new Set;closePromise=null;closed=!1;constructor(A,Q,$={}){this.scope=t0.runSync(j2.make()),this.fibers=t0.runSync(j2.extend(RZ.make(),this.scope));let w=t0.flatMap(eW.currentTimeMillis,(Z)=>t0.tryPromise({try:()=>this.trackSweep(()=>Q(Z)),catch:(H)=>H}).pipe(t0.catchAll((H)=>t0.sync(()=>{$.onError?.(H)})))),B=Math.max(1,A),X=($.clock?t0.sleep(B):XW6(B)).pipe(t0.andThen(w),t0.forever),Y=$.clock?t0.withClock(X,$.clock):X;RZ.unsafeAdd(this.fibers,t0.runFork(Y))}close(){return this.closed=!0,this.closePromise??=this.closeSupervisor(),this.closePromise}trackSweep(A){if(this.closed)return Promise.resolve();let Q=A();return this.activeSweeps.add(Q),Q.finally(()=>{this.activeSweeps.delete(Q)})}async closeSupervisor(){let A=await t0.runPromiseExit(j2.close(this.scope,y2.void));if(await Promise.allSettled([...this.activeSweeps]),y2.isFailure(A))throw a$.squash(A.cause)}}h0();var KW6=1800000,UW6=60000,GW6={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id, MCP-Protocol-Version, Last-Event-ID","Access-Control-Allow-Private-Network":"true","X-Content-Type-Options":"nosniff"},DW6=W.looseObject({code:W.string().optional()});function qW6(A){let Q=new URL(A.url),w=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),B=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!B)return Q.origin;return`${w??Q.protocol.replace(":","")}://${B}`}class SF{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;sessionEviction;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?CV0(this.config.logger):zQA(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??KW6,!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.");this.sessionEviction=new VQA(Math.min(this.sessionIdleTtlMs,UW6),(Q)=>this.evictIdleSessions(Q),{onError:(Q)=>{this.logger.error("Error sweeping idle MCP sessions:",Q)}})}static getInstance(A){return SF.instance??=new SF(A),SF.instance}static async resetInstance(){let A=SF.instance;SF.instance=null,await A?.stop()}static createFresh(A){return new SF(A)}withCors(A){let Q=new Headers(A.headers);for(let[$,w]of Object.entries(GW6))Q.set($,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,$){let w=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!$)return w;let B=new Headers(w.headers);return B.set("WWW-Authenticate",$),new Response(w.body,{status:w.status,statusText:w.statusText,headers:B})}getBearerChallenge(A,Q={}){let $={...this.authConfig.token?{}:{resource_metadata:`${qW6(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries($).map(([B,X])=>`${B}="${zW6(X)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let $=A.headers.get("authorization");if(!$?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let w=$.substring(7);if(!VW6(w,this.authConfig.token))return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));return this.logger.debug("Authentication successful"),{token:w,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let w=await this.authConfig.verifyBearerToken?.(A);if(!w)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let B=this.authConfig.requiredScopes??[],X=B.filter((Y)=>!w.scope?.includes(Y));if(X.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${X.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:B.join(" ")}));return this.logger.debug("Authentication successful"),{token:$.substring(7),clientId:w.subject,scopes:w.scope??[],extra:{subject:w.subject}}}catch(w){return this.logger.warn("Authentication failed: Invalid token",w),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}async evictIdleSessions(A){let Q=[];for(let[$,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${$}`),this.sessionLastActivity.delete($);let B=this.transports[$];if(B)delete this.transports[$],Q.push(B.close().catch((X)=>{this.logger.error(`Error closing idle transport for session ${$}:`,X)}))}await Promise.all(Q)}async handleMcpRequest(A,Q){let $=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!$||!this.transports[$])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession($),this.logger.debug(`GET /mcp - SSE stream for session ${$}`),this.withCors(await this.transports[$].handleRequest(A,{authInfo:Q}))}if(A.method==="DELETE"){if(!$||!this.transports[$])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${$}`),this.withCors(await this.transports[$].handleRequest(A,{authInfo:Q}))}if(A.method==="OPTIONS")return this.withCors(new Response(null,{status:204}));if(A.method!=="POST")return this.createTextResponse("Method Not Allowed",405);if(!this.mcpServer)return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Service Unavailable: MCP server not connected"},id:null},503);let w;try{w=await A.json()}catch{return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32700,message:"Parse error: Invalid JSON body"},id:null},400)}this.logger.debug(`POST /mcp - Session: ${$??"new"}`);try{let B;if($&&this.transports[$])B=this.transports[$],this.touchSession($);else if(!$&&HW6(w))B=new WW6({sessionIdGenerator:()=>YW6(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=B,this.touchSession(Y)},onsessionclosed:(Y)=>{this.logger.info(`Session closed: ${Y}`),delete this.transports[Y],this.sessionLastActivity.delete(Y)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:w,authInfo:Q}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let $=await this.authenticate(A);if($ instanceof Response)return $;let w=$??void 0;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A,w);return this.createTextResponse("Not Found",404)}connectMCPServer(A,Q){this.mcpServer=A,this.mcpTransport=Q??null,this.logger.debug("MCP server connected to StreamableHTTP transport")}async start(){if(this.server)throw Error("Server is already running");let A=Number(this.config.port??3333),Q=this.config.host??"0.0.0.0";try{this.server=Bun.serve({port:A,hostname:Q,fetch:($)=>this.handleRequest($)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch($){let w=DW6.safeParse($);if(w.success&&w.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw $}}async stop(){await this.sessionEviction.close(),this.sessionLastActivity.clear();for(let A in this.transports)try{let Q=this.transports[A];if(Q)this.logger.debug(`Closing transport for session ${A}`),await Q.close(),delete this.transports[A]}catch(Q){this.logger.error(`Error closing transport for session ${A}:`,Q)}if(this.server)await this.server.stop(),this.logger.info("StreamableHTTP server stopped"),this.server=null,this.boundPort=null}getPort(){if(this.boundPort===null)throw Error("Server is not running");return this.boundPort}getApp(){return{fetch:(A)=>this.handleRequest(A)}}isRunning(){return this.server!==null}getSessionCount(){return Object.keys(this.transports).length}}function zW6(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function VW6(A,Q){let $=Buffer.from(A),w=Buffer.from(Q);if($.length!==w.length)return!1;return ZW6($,w)}import{randomUUID as PW6}from"crypto";import{chmod as JW6,mkdir as FW6,readFile as LW6,rename as AL1,writeFile as IW6}from"fs/promises";import{dirname as NW6}from"path";class UH{filePath;parse;empty;logError;onCorrupt;writeQueue=Promise.resolve();constructor(A){this.filePath=A.filePath,this.parse=A.parse,this.empty=A.empty,this.onCorrupt=A.onCorrupt??"quarantine",this.logError=A.logError??((Q,$)=>{console.error(Q,$)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await LW6(this.filePath,"utf8")}catch(Q){if(Q.code==="ENOENT")return this.empty();throw Q}try{return this.parse(JSON.parse(A))}catch(Q){if(this.onCorrupt==="throw")throw Error(`Corrupt JSON store at ${this.filePath}; refusing to start empty. Inspect or remove the file to proceed.`,{cause:Q});return await this.quarantineCorruptFile(Q),this.empty()}}async write(A){await FW6(NW6(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await IW6(Q,`${JSON.stringify(A,null,2)}
1775
+ ${U}`,iZ6);K=`${w.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:eA(_)})}}await this.reportProgress($,{progress:g6.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),J=oF1(G,D)+K,F;try{F=await this.context.ai.generateImage(J,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:eA(_)}),o5.failure(_)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let L=ZG.createImageEntity({dataUrl:F.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await BH({entityService:this.context.entityService,entity:{...L,id:H}}),this.logger.debug("Created image entity",{imageId:H}),X&&Y){await this.reportProgress($,{progress:g6.SAVE,message:`Updating ${X} with cover image`});let _=await kC(this.context.entityService,X,Y,this.logger);if(!_)return o5.failure(Error(`Target entity not found: ${X}/${Y}`));let j=Zh(_,H);await this.context.entities.update(j),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:H})}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:H}}catch(K){let U=eA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await NF({entityService:this.context.entityService,entityType:"image",id:H,error:U}),o5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}zA();h0();Uw();cZ();var nZ6=W.object({sourceEntityType:W.string().min(1),sourceEntityId:W.string().min(1),attachmentType:W.string().min(1),imageId:W.string().min(1),dedupKey:W.string().min(1).optional(),replace:W.boolean().optional(),targetEntityType:W.string().min(1).optional(),targetEntityId:W.string().min(1).optional(),targetImageField:W.enum(["coverImageId","ogImageId"]).optional()});class UQA extends H8{context;constructor(A,Q){super(Q,{schema:nZ6,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,$){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress($,{progress:g6.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress($,{progress:g6.PROCESS,message:"Rendering source image"});let w=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!w)return o5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(w.type!=="image")return o5.failure(Error(`Attachment provider returned ${w.type}; expected image`));await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let B=w.mimeType.split("/")[1]??"png",X=ZG.createImageEntity({dataUrl:RAA(w.data.toString("base64"),B),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await BH({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress($,{progress:g6.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(w){let B=eA(w);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await NF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),o5.failure(w)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let $=await kC(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!$)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let B=(A.targetImageField??"coverImageId")==="ogImageId"?V20($,Q):Zh($,Q);await this.context.entities.update(B)}}zA();h0();Uw();cZ();p2();var Al={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function RV0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function vV0(A){let Q=rZ6(A.title,A.filename),$=O1(Q);if(!$)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:$,title:Q}}function sF1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function rZ6(A,Q){let $=A?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}var oZ6=W.object({uploadId:W.string().min(1),imageId:W.string().min(1).optional(),title:W.string().optional()});class GQA extends H8{context;constructor(A,Q){super(A,{schema:oZ6,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,$){try{await this.reportProgress($,{progress:10,message:"Reading uploaded image"});let w=await this.context.uploads.scoped(Al).read(A.uploadId);if(!RV0(w.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=vV0({filename:w.record.filename,...A.title!==void 0?{title:A.title}:{}}),X=A.imageId??B.id;await this.reportProgress($,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),Z=ZG.createImageEntity({dataUrl:sF1(w.record.mediaType,w.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:w.record.filename,sourceMediaType:w.record.mediaType,attachmentType:"uploaded"}),H=await BH({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress($,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch(w){if(A.imageId)await NF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:eA(w)});return o5.failure(w)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var aF1={name:"@brains/image-plugin",version:"0.2.0-alpha.196",description:"Plugin for AI-powered image generation and management",dependencies:{"@brains/contracts":"workspace:*","@brains/entity-service":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var aZ6="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",tZ6=W.object({defaultAspectRatio:W.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function o3(A){let Q=A?.trim();if(!Q)return;return Q}function eZ6(A){let Q=o3(A.prompt);if(Q)return Q;let $=o3(A.content);if($&&!KQA($))return $;return}function AW6(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return O1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function tF1(A){let Q=o3(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return O1(Q)}async function QW6(A,Q){let $=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,w=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return w?`${$}:${w.contentHash}`:$}function DQA(A,Q="generated"){let $=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${$}`,downloadUrl:`/api/chat/attachments/image?id=${$}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function $W6(A){let Q=encodeURIComponent(A.entityId);return{mediaType:A.mediaType,url:`/api/chat/attachments/image?id=${Q}`,downloadUrl:`/api/chat/attachments/image?id=${Q}&download=1`,filename:A.filename,source:{entityType:"image",entityId:A.entityId,attachmentType:"uploaded"}}}class qQA extends c6{entityType=ZG.entityType;schema=q20;adapter=ZG;constructor(A={}){super("image",aF1,A,tZ6)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,$){if(A.from?.kind===Al.refKind)return this.promoteUpload(A,$);let w=eZ6(A),B=o3(A.targetEntityType),X=o3(A.targetEntityId),Y=B===this.entityType?X:void 0,Z=A.from;if(Z?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Z},$);if(!B||!X||Y){if(!w)return{kind:"continue",input:A};let D=o3(A.title)??Y,q=tF1({prompt:w,...D&&{title:D}});await this.createPendingImage($,{id:q,title:D??w.slice(0,60).trim(),alt:D??w.slice(0,60).trim(),attachmentType:"generated"});let J=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:J,attachment:DQA(q)}}}}let H=await TZ($.entityService,B,X,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!w)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let K=fV0(H.entity.content),U=tF1({prompt:w,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage($,{id:U,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:H.entity.id});let G=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...K&&{entityContent:K}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:DQA(U)}}}}async promoteUpload(A,Q){let $=A.from;if($?.kind!==Al.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w=$.id,B;try{B=await Q.uploads.scoped(Al).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!RV0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=vV0({filename:B.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Z){return{kind:"handled",result:{success:!1,error:Z instanceof Error?Z.message:String(Z)}}}await this.createPendingImage(Q,{id:X.id,title:X.title,alt:X.title,sourceUploadId:w,sourceFilename:B.filename,sourceMediaType:B.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:w,imageId:X.id,title:X.title}});return{kind:"handled",result:{success:!0,data:{entityId:X.id,status:"generating",jobId:Y,attachment:$W6({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let $=o3(A.from.sourceEntityType),w=o3(A.from.sourceEntityId),B=o3(A.from.attachmentType);if(!$||!w||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await TZ(Q.entityService,$,w,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=o3(A.targetEntityType),Z=o3(A.targetEntityId),H;if(Y&&Z){let q=await TZ(Q.entityService,Y,Z,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let K={sourceEntityType:$,sourceEntityId:X.entity.id,attachmentType:B},U=await QW6(Q,K),G=AW6(K);await this.createPendingImage(Q,{id:G,title:G,alt:G,sourceEntityType:K.sourceEntityType,sourceEntityId:K.sourceEntityId,attachmentType:B,dedupKey:U});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...K,imageId:G,dedupKey:U,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:G,status:"generating",jobId:D,attachment:DQA(G,B)}}}}async createPendingImage(A,Q){let $=new Date().toISOString(),w=ZG.createImageEntity({dataUrl:aZ6,title:Q.title,alt:Q.alt,status:"pending",attachmentType:Q.attachmentType,...Q.sourceEntityType&&{sourceEntityType:Q.sourceEntityType},...Q.sourceEntityId&&{sourceEntityId:Q.sourceEntityId},...Q.sourceUploadId&&{sourceUploadId:Q.sourceUploadId},...Q.sourceFilename&&{sourceFilename:Q.sourceFilename},...Q.sourceMediaType&&{sourceMediaType:Q.sourceMediaType},...Q.dedupKey&&{dedupKey:Q.dedupKey}});await fC({entityService:A.entityService,entity:{id:Q.id,...w,created:$,updated:$}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new xV0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async($)=>{let w=await this.promoteUpload({entityType:this.entityType,...$.title!==void 0?{title:$.title}:{},from:$.upload},A);return w.kind==="handled"?w.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new xV0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new UQA(A,this.logger)),A.jobs.registerHandler("upload-promote",new GQA(this.logger.child("UploadPromotionJobHandler"),A))}}function FQ0(A={}){return new qQA(A)}zA();import{StdioServerTransport as BW6}from"@modelcontextprotocol/sdk/server/stdio.js";h0();var wW6=W.custom((A)=>typeof A==="object"&&A!==null&&("info"in A)&&typeof A.info==="function"&&("debug"in A)&&typeof A.debug==="function"&&("error"in A)&&typeof A.error==="function"&&("warn"in A)&&typeof A.warn==="function");function eF1(){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 zQA(){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 CV0(A){let Q=wW6.safeParse(A);if(Q.success)return{info:($,...w)=>Q.data.info($,...w),debug:($,...w)=>Q.data.debug($,...w),error:($,...w)=>Q.data.error($,...w),warn:($,...w)=>Q.data.warn($,...w)};return zQA()}class s3{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return s3.instance??=new s3(A),s3.instance}static resetInstance(){if(s3.instance)s3.instance.stop(),s3.instance=null}static createFresh(A){return new s3(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?CV0(this.config.logger):eF1()}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 BW6,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 YW6,timingSafeEqual as ZW6}from"crypto";import{WebStandardStreamableHTTPServerTransport as WW6}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as HW6}from"@modelcontextprotocol/sdk/types.js";c8();function XW6(A){return t0.async((Q)=>{let $=setTimeout(()=>Q(t0.void),A);return $.unref(),t0.sync(()=>clearTimeout($))})}class VQA{scope;fibers;activeSweeps=new Set;closePromise=null;closed=!1;constructor(A,Q,$={}){this.scope=t0.runSync(j2.make()),this.fibers=t0.runSync(j2.extend(RZ.make(),this.scope));let w=t0.flatMap(eW.currentTimeMillis,(Z)=>t0.tryPromise({try:()=>this.trackSweep(()=>Q(Z)),catch:(H)=>H}).pipe(t0.catchAll((H)=>t0.sync(()=>{$.onError?.(H)})))),B=Math.max(1,A),X=($.clock?t0.sleep(B):XW6(B)).pipe(t0.andThen(w),t0.forever),Y=$.clock?t0.withClock(X,$.clock):X;RZ.unsafeAdd(this.fibers,t0.runFork(Y))}close(){return this.closed=!0,this.closePromise??=this.closeSupervisor(),this.closePromise}trackSweep(A){if(this.closed)return Promise.resolve();let Q=A();return this.activeSweeps.add(Q),Q.finally(()=>{this.activeSweeps.delete(Q)})}async closeSupervisor(){let A=await t0.runPromiseExit(j2.close(this.scope,y2.void));if(await Promise.allSettled([...this.activeSweeps]),y2.isFailure(A))throw a$.squash(A.cause)}}h0();var KW6=1800000,UW6=60000,GW6={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, MCP-Session-Id, MCP-Protocol-Version, Last-Event-ID","Access-Control-Allow-Private-Network":"true","X-Content-Type-Options":"nosniff"},DW6=W.looseObject({code:W.string().optional()});function qW6(A){let Q=new URL(A.url),w=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),B=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!B)return Q.origin;return`${w??Q.protocol.replace(":","")}://${B}`}class SF{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;sessionEviction;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?CV0(this.config.logger):zQA(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??KW6,!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.");this.sessionEviction=new VQA(Math.min(this.sessionIdleTtlMs,UW6),(Q)=>this.evictIdleSessions(Q),{onError:(Q)=>{this.logger.error("Error sweeping idle MCP sessions:",Q)}})}static getInstance(A){return SF.instance??=new SF(A),SF.instance}static async resetInstance(){let A=SF.instance;SF.instance=null,await A?.stop()}static createFresh(A){return new SF(A)}withCors(A){let Q=new Headers(A.headers);for(let[$,w]of Object.entries(GW6))Q.set($,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,$){let w=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!$)return w;let B=new Headers(w.headers);return B.set("WWW-Authenticate",$),new Response(w.body,{status:w.status,statusText:w.statusText,headers:B})}getBearerChallenge(A,Q={}){let $={...this.authConfig.token?{}:{resource_metadata:`${qW6(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries($).map(([B,X])=>`${B}="${zW6(X)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let $=A.headers.get("authorization");if(!$?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let w=$.substring(7);if(!VW6(w,this.authConfig.token))return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));return this.logger.debug("Authentication successful"),{token:w,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let w=await this.authConfig.verifyBearerToken?.(A);if(!w)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let B=this.authConfig.requiredScopes??[],X=B.filter((Y)=>!w.scope?.includes(Y));if(X.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${X.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:B.join(" ")}));return this.logger.debug("Authentication successful"),{token:$.substring(7),clientId:w.subject,scopes:w.scope??[],extra:{subject:w.subject}}}catch(w){return this.logger.warn("Authentication failed: Invalid token",w),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}async evictIdleSessions(A){let Q=[];for(let[$,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${$}`),this.sessionLastActivity.delete($);let B=this.transports[$];if(B)delete this.transports[$],Q.push(B.close().catch((X)=>{this.logger.error(`Error closing idle transport for session ${$}:`,X)}))}await Promise.all(Q)}async handleMcpRequest(A,Q){let $=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!$||!this.transports[$])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession($),this.logger.debug(`GET /mcp - SSE stream for session ${$}`),this.withCors(await this.transports[$].handleRequest(A,{authInfo:Q}))}if(A.method==="DELETE"){if(!$||!this.transports[$])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${$}`),this.withCors(await this.transports[$].handleRequest(A,{authInfo:Q}))}if(A.method==="OPTIONS")return this.withCors(new Response(null,{status:204}));if(A.method!=="POST")return this.createTextResponse("Method Not Allowed",405);if(!this.mcpServer)return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Service Unavailable: MCP server not connected"},id:null},503);let w;try{w=await A.json()}catch{return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32700,message:"Parse error: Invalid JSON body"},id:null},400)}this.logger.debug(`POST /mcp - Session: ${$??"new"}`);try{let B;if($&&this.transports[$])B=this.transports[$],this.touchSession($);else if(!$&&HW6(w))B=new WW6({sessionIdGenerator:()=>YW6(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=B,this.touchSession(Y)},onsessionclosed:(Y)=>{this.logger.info(`Session closed: ${Y}`),delete this.transports[Y],this.sessionLastActivity.delete(Y)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:w,authInfo:Q}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let $=await this.authenticate(A);if($ instanceof Response)return $;let w=$??void 0;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A,w);return this.createTextResponse("Not Found",404)}connectMCPServer(A,Q){this.mcpServer=A,this.mcpTransport=Q??null,this.logger.debug("MCP server connected to StreamableHTTP transport")}async start(){if(this.server)throw Error("Server is already running");let A=Number(this.config.port??3333),Q=this.config.host??"0.0.0.0";try{this.server=Bun.serve({port:A,hostname:Q,fetch:($)=>this.handleRequest($)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch($){let w=DW6.safeParse($);if(w.success&&w.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw $}}async stop(){await this.sessionEviction.close(),this.sessionLastActivity.clear();for(let A in this.transports)try{let Q=this.transports[A];if(Q)this.logger.debug(`Closing transport for session ${A}`),await Q.close(),delete this.transports[A]}catch(Q){this.logger.error(`Error closing transport for session ${A}:`,Q)}if(this.server)await this.server.stop(),this.logger.info("StreamableHTTP server stopped"),this.server=null,this.boundPort=null}getPort(){if(this.boundPort===null)throw Error("Server is not running");return this.boundPort}getApp(){return{fetch:(A)=>this.handleRequest(A)}}isRunning(){return this.server!==null}getSessionCount(){return Object.keys(this.transports).length}}function zW6(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function VW6(A,Q){let $=Buffer.from(A),w=Buffer.from(Q);if($.length!==w.length)return!1;return ZW6($,w)}import{randomUUID as PW6}from"crypto";import{chmod as JW6,mkdir as FW6,readFile as LW6,rename as AL1,writeFile as IW6}from"fs/promises";import{dirname as NW6}from"path";class UH{filePath;parse;empty;logError;onCorrupt;writeQueue=Promise.resolve();constructor(A){this.filePath=A.filePath,this.parse=A.parse,this.empty=A.empty,this.onCorrupt=A.onCorrupt??"quarantine",this.logError=A.logError??((Q,$)=>{console.error(Q,$)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await LW6(this.filePath,"utf8")}catch(Q){if(Q.code==="ENOENT")return this.empty();throw Q}try{return this.parse(JSON.parse(A))}catch(Q){if(this.onCorrupt==="throw")throw Error(`Corrupt JSON store at ${this.filePath}; refusing to start empty. Inspect or remove the file to proceed.`,{cause:Q});return await this.quarantineCorruptFile(Q),this.empty()}}async write(A){await FW6(NW6(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await IW6(Q,`${JSON.stringify(A,null,2)}
1776
1776
  `,{mode:384}),await JW6(Q,384),await AL1(Q,this.filePath)}async quarantineCorruptFile(A){let Q=`${this.filePath}.corrupt-${process.pid}`;this.logError(`Corrupt JSON store at ${this.filePath}; moving it to ${Q} and starting from an empty store`,A);try{await AL1(this.filePath,Q)}catch($){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,$)}}}function Ql(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function hV0(){let A=new Date;return A.setDate(A.getDate()-1),A}function QL1(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function d4(){return Math.floor(Date.now()/1000)}h0();import{join as bW6}from"path";function $L1(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function wL1(A){try{return new URL(A)}catch{return}}function JQA(A,Q){if(A===Q)return!0;let $=wL1(A),w=wL1(Q);if(!$||!w)return!1;if(!$L1($.hostname)||!$L1(w.hostname))return!1;return $.protocol===w.protocol&&$.port===w.port&&_W6($.pathname,w.pathname)&&$.search===w.search&&$.hash===w.hash}function _W6(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function FQA(A,Q){return A.some(($)=>JQA($,Q))}var jW6="oauth-auth-codes.json",MW6=600,kW6=W.looseObject({code:W.string(),client_id:W.string(),redirect_uri:W.string(),code_challenge:W.string(),code_challenge_method:W.literal("S256"),scope:W.string().optional(),subject:W.string(),created_at:W.number(),expires_at:W.number(),consumed_at:W.number().optional()}).transform((A)=>({code:A.code,client_id:A.client_id,redirect_uri:A.redirect_uri,code_challenge:A.code_challenge,code_challenge_method:A.code_challenge_method,...A.scope!==void 0?{scope:A.scope}:{},subject:A.subject,created_at:A.created_at,expires_at:A.expires_at,...A.consumed_at!==void 0?{consumed_at:A.consumed_at}:{}})),OW6=W.looseObject({codes:W.array(W.unknown()).optional()});function fW6(A){let Q=OW6.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap(xW6)??[]}}function xW6(A){let Q=kW6.safeParse(A);return Q.success?[Q.data]:[]}async function RW6(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class EV0{store;constructor(A){this.store=new UH({filePath:bW6(A.storageDir,A.storeFile??jW6),parse:fW6,empty:()=>({codes:[]})})}async createCode(A){let Q=d4(),$={code:`ocd_${PW6()}`,client_id:A.clientId,redirect_uri:A.redirectUri,code_challenge:A.codeChallenge,code_challenge_method:"S256",...A.scope?{scope:A.scope}:{},subject:A.subject,created_at:Q,expires_at:Q+MW6};return await this.store.enqueueWrite(async()=>{let w=await this.store.read();w.codes=w.codes.filter((B)=>B.expires_at>Q),w.codes.push($),await this.store.write(w)}),$}async consumeCode(A){let Q=d4(),$;if(await this.store.enqueueWrite(async()=>{let w=await this.store.read(),B=w.codes.findIndex((Z)=>Z.code===A.code),X=B>=0?w.codes[B]:void 0;if(!X)throw new a3("Authorization code not found");if(X.consumed_at!==void 0)throw new a3("Authorization code already consumed");if(X.expires_at<=Q)throw new a3("Authorization code expired");if(X.client_id!==A.clientId)throw new a3("Authorization code client mismatch");if(!JQA(X.redirect_uri,A.redirectUri))throw new a3("Authorization code redirect URI mismatch");let Y=await RW6(A.codeVerifier);if(X.code_challenge!==Y)throw new a3("PKCE verification failed");$={...X,consumed_at:Q},w.codes[B]=$,await this.store.write(w)}),!$)throw new a3("Authorization code not consumed");return $}}class a3 extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as BL1}from"crypto";h0();import{join as vW6}from"path";var CW6="oauth-clients.json",hW6=W.enum(["none","client_secret_basic","client_secret_post"]),EW6=W.object({redirect_uris:W.array(W.url()).min(1),token_endpoint_auth_method:hW6.default("none"),grant_types:W.array(W.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:W.array(W.literal("code")).default(["code"]),scope:W.string().optional(),client_name:W.string().optional(),client_uri:W.url().optional(),logo_uri:W.url().optional(),contacts:W.array(W.string()).optional()}),TW6=W.looseObject({client_id:W.string(),client_id_issued_at:W.number(),redirect_uris:W.array(W.string()),token_endpoint_auth_method:W.string().optional(),grant_types:W.array(W.string()).optional(),response_types:W.array(W.string()).optional(),scope:W.string().optional(),client_name:W.string().optional(),client_uri:W.string().optional(),logo_uri:W.string().optional(),contacts:W.array(W.string()).optional(),client_secret:W.string().optional(),client_secret_expires_at:W.number().optional()}).transform((A)=>({client_id:A.client_id,client_id_issued_at:A.client_id_issued_at,redirect_uris:A.redirect_uris,token_endpoint_auth_method:A.token_endpoint_auth_method??"none",grant_types:A.grant_types??["authorization_code","refresh_token"],response_types:A.response_types??["code"],...A.scope!==void 0?{scope:A.scope}:{},...A.client_name!==void 0?{client_name:A.client_name}:{},...A.client_uri!==void 0?{client_uri:A.client_uri}:{},...A.logo_uri!==void 0?{logo_uri:A.logo_uri}:{},...A.contacts!==void 0?{contacts:A.contacts}:{},...A.client_secret!==void 0?{client_secret:A.client_secret}:{},...A.client_secret_expires_at!==void 0?{client_secret_expires_at:A.client_secret_expires_at}:{}})),yW6=W.looseObject({clients:W.array(W.unknown()).optional()});function gW6(){return`ocs_${BL1().replaceAll("-","")}`}function SW6(A){let Q=yW6.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(mW6)??[]}}function mW6(A){let Q=TW6.safeParse(A);return Q.success?[Q.data]:[]}class TV0{store;constructor(A){this.store=new UH({filePath:vW6(A.storageDir,A.storeFile??CW6),parse:SW6,empty:()=>({clients:[]})})}async registerClient(A){let Q=EW6.safeParse(A);if(!Q.success)throw new LQ0(Q.error.message);let $=Q.data,w=d4(),B=`oc_${BL1()}`,X=$.token_endpoint_auth_method==="none",Y={client_id:B,client_id_issued_at:w,redirect_uris:$.redirect_uris,token_endpoint_auth_method:$.token_endpoint_auth_method,grant_types:$.grant_types,response_types:$.response_types,...$.scope?{scope:$.scope}:{},...$.client_name?{client_name:$.client_name}:{},...$.client_uri?{client_uri:$.client_uri}:{},...$.logo_uri?{logo_uri:$.logo_uri}:{},...$.contacts?{contacts:$.contacts}:{},...!X?{client_secret:gW6(),client_secret_expires_at:0}:{}};return await this.store.enqueueWrite(async()=>{let Z=await this.store.read();Z.clients.push(Y),await this.store.write(Z)}),Y}async getClient(A){return(await this.store.read()).clients.find(($)=>$.client_id===A)}}class LQ0 extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}h0();import{createHash as XL1,generateKeyPairSync as uW6}from"crypto";import{mkdir as cW6,readFile as YL1,writeFile as pW6,chmod as lW6}from"fs/promises";import{dirname as iW6,join as ZL1}from"path";var dW6="oauth-signing-key.jwk",nW6="a2a-signing-key.jwk",WL1=W.object({kty:W.literal("EC"),crv:W.literal("P-256"),x:W.string(),y:W.string(),d:W.string(),kid:W.string().optional()}),HL1=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),d:W.string(),kid:W.string().optional()});function rW6(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return XL1("sha256").update(Q).digest("base64url")}function oW6(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return XL1("sha256").update(Q).digest("base64url")}function sW6(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function aW6(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function tW6(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=WL1.safeParse(await crypto.subtle.exportKey("jwk",A.privateKey));if(!Q.success)throw Error("Generated OAuth signing key is not a P-256 private JWK");return KL1(Q.data)}function eW6(){let{privateKey:A}=uW6("ed25519"),Q=HL1.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return UL1(Q.data)}function KL1(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??rW6(A),use:"sig",alg:"ES256"}}function UL1(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??oW6(A),use:"sig",alg:"EdDSA"}}class yV0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=ZL1(A.storageDir,A.keyFile??dW6)}async getPrivateJwk(){if(this.cachedKey)return this.cachedKey;this.loadPromise??=this.loadOrCreateKey();try{return this.cachedKey=await this.loadPromise,this.cachedKey}catch(A){throw this.loadPromise=void 0,A}}async loadOrCreateKey(){let A=await this.readExistingKey();if(A)return A;let Q=await tW6();return await GL1(this.keyFile,Q),Q}async getPublicJwk(){return sW6(await this.getPrivateJwk())}async readExistingKey(){try{let A=WL1.safeParse(JSON.parse(await YL1(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return KL1(A.data)}catch(A){if(DL1(A))return;throw A}}}class LQA{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=ZL1(A.storageDir,A.keyFile??nW6)}async getPrivateJwk(){if(this.cachedKey)return this.cachedKey;this.loadPromise??=this.loadOrCreateKey();try{return this.cachedKey=await this.loadPromise,this.cachedKey}catch(A){throw this.loadPromise=void 0,A}}async loadOrCreateKey(){let A=await this.readExistingKey();if(A)return A;let Q=eW6();return await GL1(this.keyFile,Q),Q}async getPublicJwk(){return aW6(await this.getPrivateJwk())}async readExistingKey(){try{let A=HL1.safeParse(JSON.parse(await YL1(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return UL1(A.data)}catch(A){if(DL1(A))return;throw A}}}async function GL1(A,Q){await cW6(iW6(A),{recursive:!0,mode:448}),await pW6(A,`${JSON.stringify(Q,null,2)}
1777
1777
  `,{mode:384}),await lW6(A,384)}function DL1(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var q6={};P6(q6,{trimPadding:()=>zL1,toUTF8String:()=>WH6,toBuffer:()=>BH6,toBase64:()=>YH6,isBase64URL:()=>KH6,isBase64:()=>HH6,fromUTF8String:()=>ZH6,fromBuffer:()=>XH6});var qL1=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),$=64;for(let w=0;w<64;w++)Q[A.charCodeAt(w)]=w;return Q},AH6=qL1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),QH6=qL1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),$H6=/^[-A-Za-z0-9\-_]*$/,wH6=/^[-A-Za-z0-9+/]*={0,3}$/,mF={};mF.toArrayBuffer=(A,Q)=>{let $=A.length,w=A.length*0.75,B,X=0,Y,Z,H,K;if(A[A.length-1]==="="){if(w--,A[A.length-2]==="=")w--}let U=new ArrayBuffer(w),G=new Uint8Array(U),D=Q?QH6:AH6;for(B=0;B<$;B+=4)Y=D[A.charCodeAt(B)],Z=D[A.charCodeAt(B+1)],H=D[A.charCodeAt(B+2)],K=D[A.charCodeAt(B+3)],G[X++]=Y<<2|Z>>4,G[X++]=(Z&15)<<4|H>>2,G[X++]=(H&3)<<6|K&63;return U};mF.fromArrayBuffer=(A,Q)=>{let $=new Uint8Array(A),w,B="",X=$.length,Y=Q?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(w=0;w<X;w+=3)B+=Y[$[w]>>2],B+=Y[($[w]&3)<<4|$[w+1]>>4],B+=Y[($[w+1]&15)<<2|$[w+2]>>6],B+=Y[$[w+2]&63];let Z=X%3;if(Z===2)B=B.substring(0,B.length-1)+(Q?"":"=");else if(Z===1)B=B.substring(0,B.length-2)+(Q?"":"==");return B};mF.toString=(A,Q)=>{return new TextDecoder().decode(mF.toArrayBuffer(A,Q))};mF.fromString=(A,Q)=>{return mF.fromArrayBuffer(new TextEncoder().encode(A),Q)};mF.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?$H6.test(A):wH6.test(A)}catch($){return!1}};mF.base64=mF;var AP=mF;function BH6(A,Q="base64url"){let $=AP.toArrayBuffer(A,Q==="base64url");return new Uint8Array($)}function XH6(A,Q="base64url"){let $=new Uint8Array(A);return AP.fromArrayBuffer($.buffer,Q==="base64url")}function YH6(A){let Q=AP.toArrayBuffer(A,!0);return AP.fromArrayBuffer(Q)}function ZH6(A){return AP.fromString(A,!0)}function WH6(A){return AP.toString(A,!0)}function HH6(A){return AP.validate(A,!1)}function KH6(A){return A=zL1(A),AP.validate(A,!0)}function zL1(A){return A.replace(/=/g,"")}var GH={};P6(GH,{encode:()=>RH6,decodeFirst:()=>xH6});function $l(A,Q,$){if(Q<24)return[Q,1];let w=A.byteLength-$-1,B=new DataView(A.buffer,$+1),X,Y=0;switch(Q){case 24:{if(w>0)X=B.getUint8(0),Y=2;break}case 25:{if(w>1)X=B.getUint16(0,!1),Y=3;break}case 26:{if(w>3)X=B.getUint32(0,!1),Y=5;break}case 27:{if(w>7){let Z=B.getBigUint64(0,!1);if(Z>=24n&&Z<=Number.MAX_SAFE_INTEGER)return[Number(Z),9]}break}}if(X&&X>=24)return[X,Y];throw Error("Length not supported or not well formed")}var gV0=0,IQ0=1,IQA=2,NQA=3,_QA=4,PQA=5,bQA=6,VL1=7;function uF(A,Q){let $=A<<5;if(Q<0)throw Error("CBOR Data Item argument must not be negative");let w;if(typeof Q=="number"){if(!Number.isInteger(Q))throw Error("CBOR Data Item argument must be an integer");w=BigInt(Q)}else w=Q;if(A==IQ0){if(w==0n)throw Error("CBOR Data Item argument cannot be zero when negative");w=w-1n}if(w>18446744073709551615n)throw Error("CBOR number out of range");let B=new Uint8Array(8);if(new DataView(B.buffer).setBigUint64(0,w,!1),w<=23)return[$|B[7]];else if(w<=255)return[$|24,B[7]];else if(w<=65535)return[$|25,...B.slice(6)];else if(w<=4294967295)return[$|26,...B.slice(4)];else return[$|27,...B]}class mV0{constructor(A,Q){Object.defineProperty(this,"tagId",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"tagValue",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.tagId=A,this.tagValue=Q}get tag(){return this.tagId}get value(){return this.tagValue}}function JL1(A,Q,$){return $l(A,Q,$)}function UH6(A,Q,$){let[w,B]=JL1(A,Q,$);return[-w-1,B]}function FL1(A,Q,$){let[w,B]=$l(A,Q,$),X=$+B;return[new Uint8Array(A.buffer.slice(X,X+w)),B+w]}var GH6=new TextDecoder;function DH6(A,Q,$){let[w,B]=FL1(A,Q,$);return[GH6.decode(w),B]}function qH6(A,Q,$){if(Q===0)return[[],1];let[w,B]=$l(A,Q,$),X=B,Y=[];for(let Z=0;Z<w;Z++){if(A.byteLength-$-X<=0)throw Error("array is not supported or well formed");let[K,U]=kh(A,$+X);Y.push(K),X+=U}return[Y,X]}var SV0="Map is not supported or well formed";function zH6(A,Q,$){if(Q===0)return[new Map,1];let[w,B]=$l(A,Q,$),X=B,Y=new Map;for(let Z=0;Z<w;Z++){let H=A.byteLength-$-X;if(H<=0)throw Error(SV0);let[K,U]=kh(A,$+X);if(X+=U,H-=U,H<=0)throw Error(SV0);if(typeof K!=="string"&&typeof K!=="number")throw Error(SV0);if(Y.has(K))throw Error(SV0);let[G,D]=kh(A,$+X);X+=D,Y.set(K,G)}return[Y,X]}function VH6(A,Q){if(Q+3>A.byteLength)throw Error("CBOR stream ended before end of Float 16");let $=A.getUint16(Q+1,!1);if($==31744)return[1/0,3];else if($==32256)return[NaN,3];else if($==64512)return[-1/0,3];throw Error("Float16 data is unsupported")}function JH6(A,Q){if(Q+5>A.byteLength)throw Error("CBOR stream ended before end of Float 32");return[A.getFloat32(Q+1,!1),5]}function FH6(A,Q){if(Q+9>A.byteLength)throw Error("CBOR stream ended before end of Float 64");return[A.getFloat64(Q+1,!1),9]}function LH6(A,Q,$){let[w,B]=$l(A,Q,$),[X,Y]=kh(A,$+B);return[new mV0(w,X),B+Y]}function kh(A,Q){if(Q>=A.byteLength)throw Error("CBOR stream ended before tag value");let $=A.getUint8(Q),w=$>>5,B=$&31;switch(w){case gV0:return JL1(A,B,Q);case IQ0:return UH6(A,B,Q);case IQA:return FL1(A,B,Q);case NQA:return DH6(A,B,Q);case _QA:return qH6(A,B,Q);case PQA:return zH6(A,B,Q);case bQA:return LH6(A,B,Q);case VL1:switch(B){case 20:return[!1,1];case 21:return[!0,1];case 22:return[null,1];case 23:return[void 0,1];case 25:return VH6(A,Q);case 26:return JH6(A,Q);case 27:return FH6(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function IH6(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function NH6(A){if(Math.fround(A)==A||!Number.isFinite(A)||Number.isNaN(A)){let Q=new Uint8Array(5);return Q[0]=250,new DataView(Q.buffer).setFloat32(1,A,!1),Q}else{let Q=new Uint8Array(9);return Q[0]=251,new DataView(Q.buffer).setFloat64(1,A,!1),Q}}function _H6(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return uF(IQ0,Math.abs(A));else return uF(gV0,A);return[NH6(A)]}else if(A<0n)return uF(IQ0,A*-1n);else return uF(gV0,A)}var PH6=new TextEncoder;function bH6(A,Q){Q.push(...uF(NQA,A.length)),Q.push(PH6.encode(A))}function jH6(A,Q){Q.push(...uF(IQA,A.length)),Q.push(A)}function MH6(A,Q){Q.push(...uF(_QA,A.length));for(let $ of A)NQ0($,Q)}function kH6(A,Q){Q.push(new Uint8Array(uF(PQA,A.size)));for(let[$,w]of A.entries())NQ0($,Q),NQ0(w,Q)}function OH6(A,Q){Q.push(...uF(bQA,A.tag)),NQ0(A.value,Q)}function NQ0(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(IH6(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(..._H6(A));return}if(typeof A=="string"){bH6(A,Q);return}if(A instanceof Uint8Array){jH6(A,Q);return}if(Array.isArray(A)){MH6(A,Q);return}if(A instanceof Map){kH6(A,Q);return}if(A instanceof mV0){OH6(A,Q);return}throw Error("Not implemented")}function jQA(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return kh(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return kh(new DataView(A),Q);return kh(A,Q)}function MQA(A){let Q=[];NQ0(A,Q);let $=0;for(let X of Q)if(typeof X=="number")$+=1;else $+=X.length;let w=new Uint8Array($),B=0;for(let X of Q)if(typeof X=="number")w[B]=X,B+=1;else w.set(X,B),B+=X.length;return w}function xH6(A){let Q=new Uint8Array(A),$=jQA(Q,0),[w]=$;return w}function RH6(A){return MQA(A)}var pF={};P6(pF,{verify:()=>Ab1,getRandomValues:()=>PL1,digest:()=>_L1});function LL1(A){let Q=A.get(Z6.kty);return kQA(Q)&&Q===HG.OKP}function pk(A){let Q=A.get(Z6.kty);return kQA(Q)&&Q===HG.EC2}function wl(A){let Q=A.get(Z6.kty);return kQA(Q)&&Q===HG.RSA}var Z6;(function(A){A[A.kty=1]="kty",A[A.alg=3]="alg",A[A.crv=-1]="crv",A[A.x=-2]="x",A[A.y=-3]="y",A[A.n=-1]="n",A[A.e=-2]="e"})(Z6||(Z6={}));var HG;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(HG||(HG={}));function kQA(A){return Object.values(HG).indexOf(A)>=0}var iZ;(function(A){A[A.P256=1]="P256",A[A.P384=2]="P384",A[A.P521=3]="P521",A[A.ED25519=6]="ED25519",A[A.SECP256K1=8]="SECP256K1"})(iZ||(iZ={}));function IL1(A){return Object.values(iZ).indexOf(A)>=0}var r6;(function(A){A[A.ES256=-7]="ES256",A[A.EdDSA=-8]="EdDSA",A[A.ES384=-35]="ES384",A[A.ES512=-36]="ES512",A[A.PS256=-37]="PS256",A[A.PS384=-38]="PS384",A[A.PS512=-39]="PS512",A[A.ES256K=-47]="ES256K",A[A.RS256=-257]="RS256",A[A.RS384=-258]="RS384",A[A.RS512=-259]="RS512",A[A.RS1=-65535]="RS1"})(r6||(r6={}));function cF(A){return Object.values(r6).indexOf(A)>=0}function lk(A){if([r6.RS1].indexOf(A)>=0)return"SHA-1";else if([r6.ES256,r6.PS256,r6.RS256].indexOf(A)>=0)return"SHA-256";else if([r6.ES384,r6.PS384,r6.RS384].indexOf(A)>=0)return"SHA-384";else if([r6.ES512,r6.PS512,r6.RS512,r6.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var _Q0=void 0;function gq(){return new Promise((Q,$)=>{if(_Q0)return Q(_Q0);let w=CH6.stubThisGlobalThisCrypto();if(w)return _Q0=w,Q(_Q0);return $(new NL1)})}class NL1 extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var CH6={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{_Q0=A}};async function _L1(A,Q){let $=await gq(),w=lk(Q),B=await $.subtle.digest(w,A);return new Uint8Array(B)}async function PL1(A){return(await gq()).getRandomValues(A),A}async function Bl(A){let Q=await gq(),{keyData:$,algorithm:w}=A;return Q.subtle.importKey("jwk",$,w,!1,["verify"])}async function uV0(A){let{cosePublicKey:Q,signature:$,data:w,shaHashOverride:B}=A,X=await gq(),Y=Q.get(Z6.alg),Z=Q.get(Z6.crv),H=Q.get(Z6.x),K=Q.get(Z6.y);if(!Y)throw Error("Public key was missing alg (EC2)");if(!Z)throw Error("Public key was missing crv (EC2)");if(!H)throw Error("Public key was missing x (EC2)");if(!K)throw Error("Public key was missing y (EC2)");let U;if(Z===iZ.P256)U="P-256";else if(Z===iZ.P384)U="P-384";else if(Z===iZ.P521)U="P-521";else throw Error(`Unexpected COSE crv value of ${Z} (EC2)`);let G={kty:"EC",crv:U,x:q6.fromBuffer(H),y:q6.fromBuffer(K),ext:!1},q=await Bl({keyData:G,algorithm:{name:"ECDSA",namedCurve:U}}),J=lk(Y);if(B)J=lk(B);let F={name:"ECDSA",hash:{name:J}};return X.subtle.verify(F,q,$,w)}function OQA(A){if([r6.EdDSA].indexOf(A)>=0)return"Ed25519";else if([r6.ES256,r6.ES384,r6.ES512,r6.ES256K].indexOf(A)>=0)return"ECDSA";else if([r6.RS256,r6.RS384,r6.RS512,r6.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([r6.PS256,r6.PS384,r6.PS512].indexOf(A)>=0)return"RSA-PSS";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto key alg name`)}async function cV0(A){let{cosePublicKey:Q,signature:$,data:w,shaHashOverride:B}=A,X=await gq(),Y=Q.get(Z6.alg),Z=Q.get(Z6.n),H=Q.get(Z6.e);if(!Y)throw Error("Public key was missing alg (RSA)");if(!cF(Y))throw Error(`Public key had invalid alg ${Y} (RSA)`);if(!Z)throw Error("Public key was missing n (RSA)");if(!H)throw Error("Public key was missing e (RSA)");let K={kty:"RSA",alg:"",n:q6.fromBuffer(Z),e:q6.fromBuffer(H),ext:!1},U={name:OQA(Y),hash:{name:lk(Y)}},G={name:OQA(Y)};if(B)U.hash.name=lk(B);if(U.name==="RSASSA-PKCS1-v1_5"){if(U.hash.name==="SHA-256")K.alg="RS256";else if(U.hash.name==="SHA-384")K.alg="RS384";else if(U.hash.name==="SHA-512")K.alg="RS512";else if(U.hash.name==="SHA-1")K.alg="RS1"}else if(U.name==="RSA-PSS"){let q=0;if(U.hash.name==="SHA-256")K.alg="PS256",q=32;else if(U.hash.name==="SHA-384")K.alg="PS384",q=48;else if(U.hash.name==="SHA-512")K.alg="PS512",q=64;G.saltLength=q}else throw Error(`Unexpected RSA key algorithm ${Y} (${U.name})`);let D=await Bl({keyData:K,algorithm:U});return X.subtle.verify(G,D,$,w)}function pV0(A){let Q=UQ.toHex(A);return[Q.slice(0,8),Q.slice(8,12),Q.slice(12,16),Q.slice(16,20),Q.slice(20,32)].join("-")}function s7(A){let Q;if(typeof A==="string")if(q6.isBase64URL(A))Q=q6.toBase64(A);else if(q6.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=q6.fromBuffer(A,"base64");let $="";for(let w=0;w<Math.ceil(Q.length/64);w+=1){let B=64*w;$+=`${Q.substr(B,64)}
1778
1778
  `}return $=`-----BEGIN CERTIFICATE-----
@@ -2344,14 +2344,14 @@ ${_}`)}if(w!==void 0&&X?.algorithms!==void 0){let L=X.algorithms.map((_)=>_.alg)
2344
2344
  </form>
2345
2345
  </main>
2346
2346
  </body>
2347
- </html>`}function Y$0(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(p8A(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function BL(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as YD6}from"crypto";function Dj1(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function XD6(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let $=2;if(Q[1]&&Q[1]>128)$+=Q[1]-128;if(Q[$]!==2)throw Error("Invalid DER ECDSA signature");let w=Q[$+1];if(w===void 0)throw Error("Invalid DER ECDSA signature");let B=$+2,X=Q.slice(B,B+w);if($=B+w,Q[$]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[$+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let Z=$+2,H=Q.slice(Z,Z+Y);return new Uint8Array([...qj1(X),...qj1(H)])}function qj1(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let $=new Uint8Array(32);return $.set(Q,32-Q.length),$}async function i8A(A,Q){let $={typ:"JWT",alg:"ES256",kid:A.kid},w=`${Dj1($)}.${Dj1(Q)}`,B=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),X=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode(w));return`${w}.${Buffer.from(XD6(X)).toString("base64url")}`}var ZD6=600;class d8A{clientStore;authCodeStore;refreshTokenStore;sessionStore;keyStore;authorizationApprovalTokens=new Map;constructor(A){this.clientStore=A.clientStore,this.authCodeStore=A.authCodeStore,this.refreshTokenStore=A.refreshTokenStore,this.sessionStore=A.sessionStore,this.keyStore=A.keyStore}async handleAuthorizePage(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Y$0(A);let $=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!$.success)return new Response($.error,{status:400});let w=this.createAuthorizationApprovalToken(Q,$.params);return Ni(Gj1($.params,w))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Y$0(A);let $=await A.formData(),w=await this.validateAuthorizationRequest(new URLSearchParams(S8A($)));if(!w.success)return new Response(w.error,{status:400});let B=$.get("approval_token"),X=typeof B==="string"?B:void 0;if(!X||!this.consumeAuthorizationApprovalToken(X,Q,w.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:w.params.clientId,redirectUri:w.params.redirectUri,codeChallenge:w.params.codeChallenge,...w.params.scope?{scope:w.params.scope}:{},subject:Q.subject}),Z=new URL(w.params.redirectUri);if(Z.searchParams.set("code",Y.code),w.params.state)Z.searchParams.set("state",w.params.state);return Response.redirect(Z.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let $=`oat_${YD6()}`;return this.authorizationApprovalTokens.set($,{token:$,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+ZD6}),$}consumeAuthorizationApprovalToken(A,Q,$){this.pruneExpiredAuthorizationApprovalTokens();let w=this.authorizationApprovalTokens.get(A);if(!w)return!1;return this.authorizationApprovalTokens.delete(A),w.sessionId===Q.id&&w.clientId===$.clientId&&w.redirectUri===$.redirectUri&&w.codeChallenge===$.codeChallenge&&w.scope===$.scope&&w.state===$.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,$]of this.authorizationApprovalTokens.entries())if($.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),$=A.get("client_id"),w=A.get("redirect_uri"),B=A.get("code_challenge"),X=A.get("code_challenge_method"),Y=A.get("scope")??void 0,Z=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!$)return{success:!1,error:"Missing client_id"};if(!w)return{success:!1,error:"Missing redirect_uri"};if(!B)return{success:!1,error:"Missing code_challenge"};if(X!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let H=await this.clientStore.getClient($);if(!H)return{success:!1,error:"Unknown client_id"};if(!FQA(H.redirect_uris,w))return{success:!1,error:"Unregistered redirect_uri"};let K=Y??H.scope;return{success:!0,params:{clientId:$,redirectUri:w,codeChallenge:B,...K?{scope:K}:{},...Z?{state:Z}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return Y9("invalid_client_metadata","Request body must be JSON")}try{let $=await this.clientStore.registerClient(Q);return FG($,201)}catch($){if($ instanceof LQ0)return Y9("invalid_client_metadata",$.message);throw $}}async handleTokenRequest(A,Q){let $=await g8A(A),w=$.get("grant_type"),B=u8A(A,$),X=B.clientId??$.get("client_id");if(B.error)return Y9("invalid_client",B.error);if(!X)return Y9("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=m8A(Y,B);if(Z)return Y9("invalid_client",Z);if(w==="authorization_code")return this.handleAuthorizationCodeGrant($,X,Q);if(w==="refresh_token")return this.handleRefreshTokenGrant($,X,Q);return Y9("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,$){let w=A.get("code"),B=A.get("redirect_uri"),X=A.get("code_verifier");if(!w||!B||!X)return Y9("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!FQA(Y.redirect_uris,B))return Y9("invalid_grant","Unregistered redirect_uri");try{let Z=await this.authCodeStore.consumeCode({code:w,clientId:Q,redirectUri:B,codeVerifier:X});return await this.createTokenResponse({issuer:$,clientId:Q,subject:Z.subject,...Z.scope?{scope:Z.scope}:{}})}catch(Z){if(Z instanceof a3)return Y9("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,$){let w=A.get("refresh_token");if(!w)return Y9("invalid_request","refresh_token is required");try{let B=await this.refreshTokenStore.rotateToken(w,Q);return await this.createTokenResponse({issuer:$,clientId:Q,subject:B.consumed.subject,...B.consumed.scope?{scope:B.consumed.scope}:{},refreshToken:B.replacement.token})}catch(B){if(B instanceof PP)return Y9("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),$=900,w=await i8A(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),B=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return FG({access_token:w,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await g8A(A),$=u8A(A,Q),w=$.clientId??Q.get("client_id")??void 0,B=Q.get("token");if($.error)return Y9("invalid_client",$.error);if(!B)return Y9("invalid_request","token is required");if(w){let X=await this.clientStore.getClient(w),Y=m8A(X,$);if(Y)return Y9("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,w),new Response(null,{status:200})}}class n8A{passkeyService;sessionStore;setupFlow;constructor(A){this.passkeyService=A.passkeyService,this.sessionStore=A.sessionStore,this.setupFlow=A.setupFlow}async handleRegistrationOptions(A){if(await this.passkeyService.hasCredentials())return Y9("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return Y9("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(_F0(A));return FG(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return Y9("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return Y9("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),_F0(A));if(!Q.verified)return Y9("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:$$0(A)});return FG({verified:!0},200,{"Set-Cookie":$.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return Y9("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(_F0(A));return FG(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),_F0(A));if(!Q.verified)return Y9("access_denied","Passkey authentication failed");let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:$$0(A)});return FG({verified:!0},200,{"Set-Cookie":$.cookie})}}function _F0(A){let Q=FO(A),$=new URL(Q);return{origin:$.origin,rpID:$.hostname}}import{randomUUID as WD6}from"crypto";var Z$0=86400;class r8A{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??Z$0}async ensureSetupToken(){let A=this.getValidSetupToken();if(A)return A;let Q=await this.setupStateStore.getValidSetupToken(Math.floor(Date.now()/1000));if(Q)return this.setupToken=Q,Q;return this.createSetupToken()}async createSetupToken(){return this.setupToken={token:`setup_${WD6()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let $=new URL(A.url);return($.searchParams.get("setup_token")??$.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return WV(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:WV(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:F8A(Q.token)}}async handleSetupPage(A){if(await this.passkeyService.hasCredentials())return new Response("Setup already completed",{status:404});if(!this.hasValidSetupToken(A))return new Response("Not Found",{status:404});let Q=new URL(A.url).searchParams.get("token")??"";return Ni(Kj1(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupStateStore.recordDelivery(A,Q,$)}}class PF0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=ZV(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>ZV(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??JO(this.issuer),this.keyStore=new yV0({storageDir:A.storageDir}),this.a2aKeyStore=new LQA({storageDir:A.storageDir}),this.clientStore=new TV0({storageDir:A.storageDir}),this.authCodeStore=new EV0({storageDir:A.storageDir}),this.sessionStore=new JF0({storageDir:A.storageDir}),this.peerTrustStore=new DF0({storageDir:A.storageDir}),this.passkeyService=new GF0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new r8A({setupStateStore:new L8A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Z$0}),this.oauthEndpoints=new d8A({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new qF0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new n8A({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await Promise.all([this.keyStore.getPrivateJwk(),this.a2aKeyStore.getPrivateJwk()]),this.logger?.debug("Auth service signing keys loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(JO(this.issuer))this.logger?.warn(`Passkey setup required: ${A}`);else this.logger?.warn("Passkey setup required. Ask through an anchor-visible interface for the setup URL.")}}async hasPasskeyCredentials(){return this.passkeyService.hasCredentials()}async getJwks(){let[A,Q]=await Promise.all([this.keyStore.getPublicJwk(),this.a2aKeyStore.getPublicJwk()]);return{keys:[A,Q]}}async getA2ASigningKey(){let A=await this.a2aKeyStore.getPrivateJwk();return{privateJwk:A,keyId:WV(this.issuer,`/.well-known/jwks.json#${A.kid}`)}}grantA2APeerTrust(A){return this.peerTrustStore.grant(A)}getA2APeerTrust(A){return this.peerTrustStore.get(A)}revokeA2APeerTrust(A){return this.peerTrustStore.revoke(A)}getAuthorizationServerMetadata(A=this.issuer){let Q=ZV(A);return{issuer:Q,authorization_endpoint:WV(Q,"/authorize"),token_endpoint:WV(Q,"/token"),registration_endpoint:WV(Q,"/register"),revocation_endpoint:WV(Q,"/revoke"),jwks_uri:WV(Q,"/.well-known/jwks.json"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none","client_secret_basic","client_secret_post"],scopes_supported:["openid","profile","email","offline_access","mcp"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["ES256"]}}getProtectedResourceMetadata(A,Q=this.issuer){return{resource:A,authorization_servers:[ZV(Q)],bearer_methods_supported:["header"],resource_signing_alg_values_supported:["ES256"],scopes_supported:["mcp"]}}async registerClient(A){return this.clientStore.registerClient(A)}async getRegisteredClient(A){return this.clientStore.getClient(A)}async createOperatorSession(A="single-operator",Q={}){return this.sessionStore.createSession(A,Q)}async getOperatorSession(A){return this.sessionStore.getSessionFromRequest(A)}createOperatorLoginResponse(A){return Y$0(A)}async verifyBearerToken(A,Q={}){let $=y8A(A);if(!$)return;let w=Q.issuer?ZV(Q.issuer):this.resolveRequestIssuer(A);return T8A($,await this.getJwks(),{issuer:w,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,$)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(w){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:w instanceof Error?w.message:String(w)}),new Response("Untrusted OAuth issuer",{status:400})}let $=new URL(A.url).pathname;if(A.method==="OPTIONS"&&Zj1($))return Wj1();if(A.method==="GET"){if($==="/.well-known/oauth-authorization-server")return _O(FG(this.getAuthorizationServerMetadata(Q)));if($==="/.well-known/jwks.json")return _O(FG(await this.getJwks()));if($==="/.well-known/oauth-protected-resource")return _O(FG(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&$==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&$==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&$==="/logout")return this.handleLogout(A);if(A.method==="POST"&&$==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&$==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&$==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&$==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&$==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&$==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&$==="/register")return _O(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&$==="/token")return _O(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&$==="/revoke")return _O(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=FO(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&JO(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=c8A(new URL(A.url).searchParams.get("return_to"));return Ni(p8A(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=c8A(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":N8A($$0(A)),"Cache-Control":"no-store"}})}}Y20();zA();h0();var zj1={name:"@brains/auth-service",version:"0.2.0-alpha.195",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var KD6=W.union([W.string().email(),W.object({to:W.string().email(),subject:W.string().min(1),body:W.string().min(1)}).strict()]),UD6=W.object({issuer:W.string().optional(),trustedIssuers:W.array(W.string()).default([]),allowLocalhostIssuers:W.boolean().optional(),storageDir:W.string().default("./data/auth"),setupTokenTtlSeconds:W.number().int().positive().default(Z$0),setupEmail:KD6.optional()}),bF0;function xY(){return bF0}class o8A extends d6{service;constructor(A={}){super("auth-service",zj1,A,UD6)}async onRegister(A){await super.onRegister(A);let Q=this.config.issuer??(A.preferLocalUrls?A.localSiteUrl??A.siteUrl:A.siteUrl??A.localSiteUrl);this.service=new PF0({storageDir:this.config.storageDir,...Q?{issuer:Q}:{},trustedIssuers:this.config.trustedIssuers,...this.config.allowLocalhostIssuers!==void 0?{allowLocalhostIssuers:this.config.allowLocalhostIssuers}:{},setupTokenTtlSeconds:this.config.setupTokenTtlSeconds,logger:A.logger}),await this.service.initialize(),bF0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(bF0===this.service)bF0=void 0;this.service=void 0}async getTools(){return[{name:`${this.id}_get_passkey_setup_url`,description:"Get the first-passkey setup URL when operator setup is required. Anchor-only.",inputSchema:{},visibility:"anchor",handler:async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return{success:!0,data:{status:"complete"}};let Q=await A.getOperatorSetupRequired();if(Q)return{success:!0,data:{status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt}};return{success:!0,data:{status:"unavailable",reason:"Passkey setup URL is not available."}}},sideEffects:"none"}]}getWebRoutes(){let A=(Q)=>this.getService().handleRequest(Q);return[{path:"/.well-known/oauth-authorization-server",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-authorization-server",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"GET",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"OPTIONS",public:!0,handler:A},{path:"/setup",method:"GET",public:!0,handler:A},{path:"/login",method:"GET",public:!0,handler:A},{path:"/logout",method:"GET",public:!0,handler:A},{path:"/logout",method:"POST",public:!0,handler:A},{path:"/authorize",method:"GET",public:!0,handler:A},{path:"/authorize",method:"POST",public:!0,handler:A},{path:"/register",method:"POST",public:!0,handler:A},{path:"/register",method:"OPTIONS",public:!0,handler:A},{path:"/token",method:"POST",public:!0,handler:A},{path:"/token",method:"OPTIONS",public:!0,handler:A},{path:"/revoke",method:"POST",public:!0,handler:A},{path:"/revoke",method:"OPTIONS",public:!0,handler:A},{path:"/webauthn/register/options",method:"POST",public:!0,handler:A},{path:"/webauthn/register/verify",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/options",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/verify",method:"POST",public:!0,handler:A}]}getService(){if(!this.service)throw Error("AuthServicePlugin has not been registered");return this.service}async requestSetupEmailIfNeeded(A){if(!this.config.setupEmail)return;let Q=this.getService();if(await Q.hasPasskeyCredentials())return;let $=await Q.getOperatorSetupRequired();if(!$)return;let w=GD6(this.config.setupEmail,$);if(await Q.hasSetupEmailDelivery($.setupTokenId,w.to))return;let B=await A.messaging.send({type:$h,payload:{recipient:{type:"email",address:w.to},title:w.subject,body:w.body,sensitivity:"secret"}});if(!("success"in B)||!B.success||!B.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let X=X20.safeParse(B.data);if(!X.success||X.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery($.setupTokenId,w.to,X.data.deliveryId?{deliveryId:X.data.deliveryId}:{})}}function GD6(A,Q){if(typeof A==="string"){let $=new Date(Q.expiresAt*1000).toISOString(),w=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${$}.`,`Dashboard: ${w}/`,`MCP endpoint: ${w}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
2348
- `)}}return{to:A.to,subject:Vj1(A.subject,Q),body:Vj1(A.body,Q)}}function Vj1(A,Q){let $=new Date(Q.expiresAt*1000).toISOString(),w=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",$).replaceAll("{{origin}}",w)}function W$0(A={}){return new o8A(A)}h0();var s8A=W.object({transport:W.enum(["stdio","http"]).default("http"),mode:W.enum(["basic","debug"]).default("basic"),httpPort:W.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:W.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:W.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});h0();import{createHash as VD6,randomUUID as JD6}from"crypto";function DD6(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function H$0(A,Q){let $=A?.[Q];return typeof $==="string"&&$.length>0?$:void 0}function qD6(A){let Q=DD6(A.data)?A.data:void 0,$=A.args,w=H$0(Q,"entityId")??H$0(Q,"id"),B=A.jobId??H$0(Q,"jobId"),X=H$0($,"entityType")??H$0($,"type");if(!w&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...w?{entityId:w}:{},...B?{jobId:B}:{}}}function zD6(A){return A?.map(qD6).filter((Q)=>Q!==void 0)??[]}function a8A(A,Q={}){let $=A.pendingConfirmations?.[0];if($)return{needsConfirmation:!0,toolName:$.toolName,summary:$.summary,...$.completionSummary?{completionSummary:$.completionSummary}:{},...$.preview?{preview:$.preview}:{},args:{approvalId:$.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...$.toolCallId?{toolCallId:$.toolCallId}:{},originalArgs:$.args}};let w=zD6(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...w.length>0?{readYourWrites:w}:{}}}}var Jj1=W.object({message:W.string().min(1),conversationId:W.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),Fj1=W.object({approvalId:W.string().min(1),confirmed:W.boolean(),conversationId:W.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function Lj1(A,Q,$,w){let B=A.conversationId??$??w??`conversation-${JD6()}`,X=VD6("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function Ij1(A){return{userPermissionLevel:A.userPermissionLevel??"public",interfaceType:"mcp",...A.channelId?{channelId:A.channelId}:{},...A.channelName?{channelName:A.channelName}:{},actor:{actorId:A.userId,interfaceType:"mcp",role:"user"}}}function Nj1(A,Q){return[{name:"chat",description:"Talk to the brain to make changes or get reasoned answers. Use this for any create/update/delete request or questions requiring reasoning across content. For simple lookups, use search/get/list directly.",inputSchema:Jj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Jj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=Lj1(B,w.userId,w.conversationId,w.channelId),Z=Ij1(w),H=w.signal?await X.agent.chat(B.message,Y.internalId,Z,w.signal):await X.agent.chat(B.message,Y.internalId,Z);return a8A(H,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:Fj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Fj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=Lj1(B,w.userId,w.conversationId,w.channelId),Z=Ij1(w),H=w.signal?await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z,w.signal):await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z);return a8A(H,{conversationId:Y.handle})}}]}zA();function t8A(A,Q){A.messaging.subscribe("job-progress",async($)=>{let w=eS.safeParse($.payload);if(!w.success)return Q.warn("Received invalid job-progress message",{error:w.error.message}),{success:!1};let B=w.data,X=B.type,Y=B.status,Z=B.id;if(Q.debug(`${X} ${Z} - ${Y}:`,{id:B.id,message:B.message,progress:B.progress,metadata:B.metadata}),B.batchDetails)Q.debug(`Batch details for ${Z}:`,{totalOperations:B.batchDetails.totalOperations,completedOperations:B.batchDetails.completedOperations,failedOperations:B.batchDetails.failedOperations,currentOperation:B.batchDetails.currentOperation,errors:B.batchDetails.errors});if(B.jobDetails)Q.debug(`Job details for ${Z}:`,{jobType:B.jobDetails.jobType,priority:B.jobDetails.priority,retryCount:B.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var _j1={name:"@brains/mcp",version:"0.2.0-alpha.195",dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0",cors:"^2.8.5",express:"^4.18.0","express-async-handler":"^1.2.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/cors":"^2.8.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class PO extends _F{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",_j1,Q,s8A)}async getTools(){return Nj1(this.id,()=>this.context)}async getResources(){return[]}async onRegister(A){if(this.domain=A.domain,this.config.transport==="http"&&!A.plugins.has("webserver"))throw Error("MCP HTTP transport requires the webserver interface. Standalone HTTP listeners have been removed.");if(this.logger.debug(`MCP interface initialized with ${this.config.transport} transport`),this.config.transport==="http")A.endpoints.register({label:"MCP",url:"/mcp",priority:30,visibility:"trusted"}),A.interactions.register({id:"mcp",label:"MCP",description:"Connect a trusted client through the Model Context Protocol.",href:"/mcp",kind:"protocol",priority:30,visibility:"trusted"});t8A(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=xY();return this.httpServer=SF.createFresh({port:this.config.httpPort,logger:this.logger,sessionIdleTtlMs:this.config.sessionIdleTtlMs,auth:this.config.authToken?{token:this.config.authToken}:A?{requiredScopes:["mcp"],verifyBearerToken:async(Q)=>A.verifyBearerToken(Q)}:{disabled:!0}}),this.httpServer}getWebRoutes(){if(this.config.transport!=="http")return[];let A=(Q)=>this.getOrCreateHttpServer().handleRequest(Q);return[{path:"/status",method:"GET",public:!0,handler:A},{path:"/mcp",method:"GET",public:!0,handler:A},{path:"/mcp",method:"POST",public:!0,handler:A},{path:"/mcp",method:"DELETE",public:!0,handler:A},{path:"/mcp",method:"OPTIONS",public:!0,handler:A}]}createDaemon(){return{start:async()=>{await this.startServer()},stop:async()=>{await this.stopServer()},healthCheck:async()=>{let A=this.isServerRunning(),Q="MCP server not running";if(A)if(this.config.transport==="http")Q=`MCP HTTP: ${this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp"}`;else Q="MCP stdio server running";return{status:A?"healthy":"error",message:Q,lastCheck:new Date,details:{transport:this.config.transport,mode:this.config.mode,url:this.config.transport==="http"?this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp":void 0,running:A}}}}}isServerRunning(){if(this.config.transport==="stdio")return this.stdioServer!==void 0&&this.mcpTransport!==void 0;else return this.httpServer!==void 0&&this.mcpTransport!==void 0}async startServer(){if(!this.context)throw Error("Context not initialized");let A=this.context;this.mcpTransport=A.mcpTransport;let Q=this.config.transport==="stdio"?"stdio":"http",$=this.context.permissions.getUserLevel("mcp",Q),w=xY(),B=this.config.transport==="http"&&(this.config.authToken?!0:w!==void 0);if(B)$="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!B)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if($!=="anchor")throw Error("MCP debug mode requires anchor permissions.")}if(this.mcpTransport.setProtocolMode(this.config.mode),this.mcpTransport.setPermissionLevel($),this.logger.debug(`Starting MCP ${this.config.transport} transport in ${this.config.mode} mode with ${$} permissions`),this.config.transport==="stdio"){this.stdioServer=s3.createFresh();let X=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(X),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let X=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(X,this.mcpTransport),this.logger.debug("MCP HTTP transport mounted on shared webserver host")}}async stopServer(){if(this.logger.debug(`Stopping MCP ${this.config.transport} transport`),this.stdioServer)this.stdioServer.stop(),this.stdioServer=void 0;if(this.httpServer)await this.httpServer.stop(),this.httpServer=void 0;this.mcpTransport=void 0}async handleProgressEvent(A,Q){}async onShutdown(){s3.resetInstance(),await SF.resetInstance()}}zA();function K$0(A,Q=2000){if(A.length<=Q)return[A];let $=ND6(A),w=[],B="";for(let X of $){let Y=B?`
2347
+ </html>`}function Y$0(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(p8A(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function BL(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as YD6}from"crypto";function Dj1(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function XD6(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let $=2;if(Q[1]&&Q[1]>128)$+=Q[1]-128;if(Q[$]!==2)throw Error("Invalid DER ECDSA signature");let w=Q[$+1];if(w===void 0)throw Error("Invalid DER ECDSA signature");let B=$+2,X=Q.slice(B,B+w);if($=B+w,Q[$]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[$+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let Z=$+2,H=Q.slice(Z,Z+Y);return new Uint8Array([...qj1(X),...qj1(H)])}function qj1(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let $=new Uint8Array(32);return $.set(Q,32-Q.length),$}async function i8A(A,Q){let $={typ:"JWT",alg:"ES256",kid:A.kid},w=`${Dj1($)}.${Dj1(Q)}`,B=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),X=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode(w));return`${w}.${Buffer.from(XD6(X)).toString("base64url")}`}var ZD6=600;class d8A{clientStore;authCodeStore;refreshTokenStore;sessionStore;keyStore;authorizationApprovalTokens=new Map;constructor(A){this.clientStore=A.clientStore,this.authCodeStore=A.authCodeStore,this.refreshTokenStore=A.refreshTokenStore,this.sessionStore=A.sessionStore,this.keyStore=A.keyStore}async handleAuthorizePage(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Y$0(A);let $=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!$.success)return new Response($.error,{status:400});let w=this.createAuthorizationApprovalToken(Q,$.params);return Ni(Gj1($.params,w))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Y$0(A);let $=await A.formData(),w=await this.validateAuthorizationRequest(new URLSearchParams(S8A($)));if(!w.success)return new Response(w.error,{status:400});let B=$.get("approval_token"),X=typeof B==="string"?B:void 0;if(!X||!this.consumeAuthorizationApprovalToken(X,Q,w.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:w.params.clientId,redirectUri:w.params.redirectUri,codeChallenge:w.params.codeChallenge,...w.params.scope?{scope:w.params.scope}:{},subject:Q.subject}),Z=new URL(w.params.redirectUri);if(Z.searchParams.set("code",Y.code),w.params.state)Z.searchParams.set("state",w.params.state);return Response.redirect(Z.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let $=`oat_${YD6()}`;return this.authorizationApprovalTokens.set($,{token:$,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+ZD6}),$}consumeAuthorizationApprovalToken(A,Q,$){this.pruneExpiredAuthorizationApprovalTokens();let w=this.authorizationApprovalTokens.get(A);if(!w)return!1;return this.authorizationApprovalTokens.delete(A),w.sessionId===Q.id&&w.clientId===$.clientId&&w.redirectUri===$.redirectUri&&w.codeChallenge===$.codeChallenge&&w.scope===$.scope&&w.state===$.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,$]of this.authorizationApprovalTokens.entries())if($.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),$=A.get("client_id"),w=A.get("redirect_uri"),B=A.get("code_challenge"),X=A.get("code_challenge_method"),Y=A.get("scope")??void 0,Z=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!$)return{success:!1,error:"Missing client_id"};if(!w)return{success:!1,error:"Missing redirect_uri"};if(!B)return{success:!1,error:"Missing code_challenge"};if(X!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let H=await this.clientStore.getClient($);if(!H)return{success:!1,error:"Unknown client_id"};if(!FQA(H.redirect_uris,w))return{success:!1,error:"Unregistered redirect_uri"};let K=Y??H.scope;return{success:!0,params:{clientId:$,redirectUri:w,codeChallenge:B,...K?{scope:K}:{},...Z?{state:Z}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return Y9("invalid_client_metadata","Request body must be JSON")}try{let $=await this.clientStore.registerClient(Q);return FG($,201)}catch($){if($ instanceof LQ0)return Y9("invalid_client_metadata",$.message);throw $}}async handleTokenRequest(A,Q){let $=await g8A(A),w=$.get("grant_type"),B=u8A(A,$),X=B.clientId??$.get("client_id");if(B.error)return Y9("invalid_client",B.error);if(!X)return Y9("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=m8A(Y,B);if(Z)return Y9("invalid_client",Z);if(w==="authorization_code")return this.handleAuthorizationCodeGrant($,X,Q);if(w==="refresh_token")return this.handleRefreshTokenGrant($,X,Q);return Y9("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,$){let w=A.get("code"),B=A.get("redirect_uri"),X=A.get("code_verifier");if(!w||!B||!X)return Y9("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!FQA(Y.redirect_uris,B))return Y9("invalid_grant","Unregistered redirect_uri");try{let Z=await this.authCodeStore.consumeCode({code:w,clientId:Q,redirectUri:B,codeVerifier:X});return await this.createTokenResponse({issuer:$,clientId:Q,subject:Z.subject,...Z.scope?{scope:Z.scope}:{}})}catch(Z){if(Z instanceof a3)return Y9("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,$){let w=A.get("refresh_token");if(!w)return Y9("invalid_request","refresh_token is required");try{let B=await this.refreshTokenStore.rotateToken(w,Q);return await this.createTokenResponse({issuer:$,clientId:Q,subject:B.consumed.subject,...B.consumed.scope?{scope:B.consumed.scope}:{},refreshToken:B.replacement.token})}catch(B){if(B instanceof PP)return Y9("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),$=900,w=await i8A(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),B=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return FG({access_token:w,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await g8A(A),$=u8A(A,Q),w=$.clientId??Q.get("client_id")??void 0,B=Q.get("token");if($.error)return Y9("invalid_client",$.error);if(!B)return Y9("invalid_request","token is required");if(w){let X=await this.clientStore.getClient(w),Y=m8A(X,$);if(Y)return Y9("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,w),new Response(null,{status:200})}}class n8A{passkeyService;sessionStore;setupFlow;constructor(A){this.passkeyService=A.passkeyService,this.sessionStore=A.sessionStore,this.setupFlow=A.setupFlow}async handleRegistrationOptions(A){if(await this.passkeyService.hasCredentials())return Y9("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return Y9("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(_F0(A));return FG(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return Y9("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return Y9("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),_F0(A));if(!Q.verified)return Y9("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:$$0(A)});return FG({verified:!0},200,{"Set-Cookie":$.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return Y9("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(_F0(A));return FG(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),_F0(A));if(!Q.verified)return Y9("access_denied","Passkey authentication failed");let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:$$0(A)});return FG({verified:!0},200,{"Set-Cookie":$.cookie})}}function _F0(A){let Q=FO(A),$=new URL(Q);return{origin:$.origin,rpID:$.hostname}}import{randomUUID as WD6}from"crypto";var Z$0=86400;class r8A{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??Z$0}async ensureSetupToken(){let A=this.getValidSetupToken();if(A)return A;let Q=await this.setupStateStore.getValidSetupToken(Math.floor(Date.now()/1000));if(Q)return this.setupToken=Q,Q;return this.createSetupToken()}async createSetupToken(){return this.setupToken={token:`setup_${WD6()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let $=new URL(A.url);return($.searchParams.get("setup_token")??$.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return WV(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:WV(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:F8A(Q.token)}}async handleSetupPage(A){if(await this.passkeyService.hasCredentials())return new Response("Setup already completed",{status:404});if(!this.hasValidSetupToken(A))return new Response("Not Found",{status:404});let Q=new URL(A.url).searchParams.get("token")??"";return Ni(Kj1(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupStateStore.recordDelivery(A,Q,$)}}class PF0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=ZV(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>ZV(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??JO(this.issuer),this.keyStore=new yV0({storageDir:A.storageDir}),this.a2aKeyStore=new LQA({storageDir:A.storageDir}),this.clientStore=new TV0({storageDir:A.storageDir}),this.authCodeStore=new EV0({storageDir:A.storageDir}),this.sessionStore=new JF0({storageDir:A.storageDir}),this.peerTrustStore=new DF0({storageDir:A.storageDir}),this.passkeyService=new GF0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new r8A({setupStateStore:new L8A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Z$0}),this.oauthEndpoints=new d8A({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new qF0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new n8A({passkeyService:this.passkeyService,sessionStore:this.sessionStore,setupFlow:this.setupFlow}),this.logger=A.logger}getIssuer(){return this.issuer}async initialize(){if(await Promise.all([this.keyStore.getPrivateJwk(),this.a2aKeyStore.getPrivateJwk()]),this.logger?.debug("Auth service signing keys loaded"),!await this.hasPasskeyCredentials()){await this.setupFlow.ensureSetupToken();let A=this.getSetupUrl();if(A)if(JO(this.issuer))this.logger?.warn(`Passkey setup required: ${A}`);else this.logger?.warn("Passkey setup required. Ask through an anchor-visible interface for the setup URL.")}}async hasPasskeyCredentials(){return this.passkeyService.hasCredentials()}async getJwks(){let[A,Q]=await Promise.all([this.keyStore.getPublicJwk(),this.a2aKeyStore.getPublicJwk()]);return{keys:[A,Q]}}async getA2ASigningKey(){let A=await this.a2aKeyStore.getPrivateJwk();return{privateJwk:A,keyId:WV(this.issuer,`/.well-known/jwks.json#${A.kid}`)}}grantA2APeerTrust(A){return this.peerTrustStore.grant(A)}getA2APeerTrust(A){return this.peerTrustStore.get(A)}revokeA2APeerTrust(A){return this.peerTrustStore.revoke(A)}getAuthorizationServerMetadata(A=this.issuer){let Q=ZV(A);return{issuer:Q,authorization_endpoint:WV(Q,"/authorize"),token_endpoint:WV(Q,"/token"),registration_endpoint:WV(Q,"/register"),revocation_endpoint:WV(Q,"/revoke"),jwks_uri:WV(Q,"/.well-known/jwks.json"),response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none","client_secret_basic","client_secret_post"],scopes_supported:["openid","profile","email","offline_access","mcp"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["ES256"]}}getProtectedResourceMetadata(A,Q=this.issuer){return{resource:A,authorization_servers:[ZV(Q)],bearer_methods_supported:["header"],resource_signing_alg_values_supported:["ES256"],scopes_supported:["mcp"]}}async registerClient(A){return this.clientStore.registerClient(A)}async getRegisteredClient(A){return this.clientStore.getClient(A)}async createOperatorSession(A="single-operator",Q={}){return this.sessionStore.createSession(A,Q)}async getOperatorSession(A){return this.sessionStore.getSessionFromRequest(A)}createOperatorLoginResponse(A){return Y$0(A)}async verifyBearerToken(A,Q={}){let $=y8A(A);if(!$)return;let w=Q.issuer?ZV(Q.issuer):this.resolveRequestIssuer(A);return T8A($,await this.getJwks(),{issuer:w,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,$)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(w){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:w instanceof Error?w.message:String(w)}),new Response("Untrusted OAuth issuer",{status:400})}let $=new URL(A.url).pathname;if(A.method==="OPTIONS"&&Zj1($))return Wj1();if(A.method==="GET"){if($==="/.well-known/oauth-authorization-server")return _O(FG(this.getAuthorizationServerMetadata(Q)));if($==="/.well-known/jwks.json")return _O(FG(await this.getJwks()));if($==="/.well-known/oauth-protected-resource")return _O(FG(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&$==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&$==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&$==="/logout")return this.handleLogout(A);if(A.method==="POST"&&$==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&$==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&$==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&$==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&$==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&$==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&$==="/register")return _O(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&$==="/token")return _O(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&$==="/revoke")return _O(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=FO(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&JO(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=c8A(new URL(A.url).searchParams.get("return_to"));return Ni(p8A(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=c8A(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":N8A($$0(A)),"Cache-Control":"no-store"}})}}Y20();zA();h0();var zj1={name:"@brains/auth-service",version:"0.2.0-alpha.196",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var KD6=W.union([W.string().email(),W.object({to:W.string().email(),subject:W.string().min(1),body:W.string().min(1)}).strict()]),UD6=W.object({issuer:W.string().optional(),trustedIssuers:W.array(W.string()).default([]),allowLocalhostIssuers:W.boolean().optional(),storageDir:W.string().default("./data/auth"),setupTokenTtlSeconds:W.number().int().positive().default(Z$0),setupEmail:KD6.optional()}),bF0;function xY(){return bF0}class o8A extends d6{service;constructor(A={}){super("auth-service",zj1,A,UD6)}async onRegister(A){await super.onRegister(A);let Q=this.config.issuer??(A.preferLocalUrls?A.localSiteUrl??A.siteUrl:A.siteUrl??A.localSiteUrl);this.service=new PF0({storageDir:this.config.storageDir,...Q?{issuer:Q}:{},trustedIssuers:this.config.trustedIssuers,...this.config.allowLocalhostIssuers!==void 0?{allowLocalhostIssuers:this.config.allowLocalhostIssuers}:{},setupTokenTtlSeconds:this.config.setupTokenTtlSeconds,logger:A.logger}),await this.service.initialize(),bF0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(bF0===this.service)bF0=void 0;this.service=void 0}async getTools(){return[{name:`${this.id}_get_passkey_setup_url`,description:"Get the first-passkey setup URL when operator setup is required. Anchor-only.",inputSchema:{},visibility:"anchor",handler:async()=>{let A=this.getService();if(await A.hasPasskeyCredentials())return{success:!0,data:{status:"complete"}};let Q=await A.getOperatorSetupRequired();if(Q)return{success:!0,data:{status:"setup_required",setupUrl:Q.setupUrl,expiresAt:Q.expiresAt}};return{success:!0,data:{status:"unavailable",reason:"Passkey setup URL is not available."}}},sideEffects:"none"}]}getWebRoutes(){let A=(Q)=>this.getService().handleRequest(Q);return[{path:"/.well-known/oauth-authorization-server",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-authorization-server",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"GET",public:!0,handler:A},{path:"/.well-known/jwks.json",method:"OPTIONS",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"GET",public:!0,handler:A},{path:"/.well-known/oauth-protected-resource",method:"OPTIONS",public:!0,handler:A},{path:"/setup",method:"GET",public:!0,handler:A},{path:"/login",method:"GET",public:!0,handler:A},{path:"/logout",method:"GET",public:!0,handler:A},{path:"/logout",method:"POST",public:!0,handler:A},{path:"/authorize",method:"GET",public:!0,handler:A},{path:"/authorize",method:"POST",public:!0,handler:A},{path:"/register",method:"POST",public:!0,handler:A},{path:"/register",method:"OPTIONS",public:!0,handler:A},{path:"/token",method:"POST",public:!0,handler:A},{path:"/token",method:"OPTIONS",public:!0,handler:A},{path:"/revoke",method:"POST",public:!0,handler:A},{path:"/revoke",method:"OPTIONS",public:!0,handler:A},{path:"/webauthn/register/options",method:"POST",public:!0,handler:A},{path:"/webauthn/register/verify",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/options",method:"POST",public:!0,handler:A},{path:"/webauthn/auth/verify",method:"POST",public:!0,handler:A}]}getService(){if(!this.service)throw Error("AuthServicePlugin has not been registered");return this.service}async requestSetupEmailIfNeeded(A){if(!this.config.setupEmail)return;let Q=this.getService();if(await Q.hasPasskeyCredentials())return;let $=await Q.getOperatorSetupRequired();if(!$)return;let w=GD6(this.config.setupEmail,$);if(await Q.hasSetupEmailDelivery($.setupTokenId,w.to))return;let B=await A.messaging.send({type:$h,payload:{recipient:{type:"email",address:w.to},title:w.subject,body:w.body,sensitivity:"secret"}});if(!("success"in B)||!B.success||!B.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let X=X20.safeParse(B.data);if(!X.success||X.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery($.setupTokenId,w.to,X.data.deliveryId?{deliveryId:X.data.deliveryId}:{})}}function GD6(A,Q){if(typeof A==="string"){let $=new Date(Q.expiresAt*1000).toISOString(),w=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${$}.`,`Dashboard: ${w}/`,`MCP endpoint: ${w}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
2348
+ `)}}return{to:A.to,subject:Vj1(A.subject,Q),body:Vj1(A.body,Q)}}function Vj1(A,Q){let $=new Date(Q.expiresAt*1000).toISOString(),w=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",$).replaceAll("{{origin}}",w)}function W$0(A={}){return new o8A(A)}h0();var s8A=W.object({transport:W.enum(["stdio","http"]).default("http"),mode:W.enum(["basic","debug"]).default("basic"),httpPort:W.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:W.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:W.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});h0();import{createHash as VD6,randomUUID as JD6}from"crypto";function DD6(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function H$0(A,Q){let $=A?.[Q];return typeof $==="string"&&$.length>0?$:void 0}function qD6(A){let Q=DD6(A.data)?A.data:void 0,$=A.args,w=H$0(Q,"entityId")??H$0(Q,"id"),B=A.jobId??H$0(Q,"jobId"),X=H$0($,"entityType")??H$0($,"type");if(!w&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...w?{entityId:w}:{},...B?{jobId:B}:{}}}function zD6(A){return A?.map(qD6).filter((Q)=>Q!==void 0)??[]}function a8A(A,Q={}){let $=A.pendingConfirmations?.[0];if($)return{needsConfirmation:!0,toolName:$.toolName,summary:$.summary,...$.completionSummary?{completionSummary:$.completionSummary}:{},...$.preview?{preview:$.preview}:{},args:{approvalId:$.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...$.toolCallId?{toolCallId:$.toolCallId}:{},originalArgs:$.args}};let w=zD6(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...w.length>0?{readYourWrites:w}:{}}}}var Jj1=W.object({message:W.string().min(1),conversationId:W.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),Fj1=W.object({approvalId:W.string().min(1),confirmed:W.boolean(),conversationId:W.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function Lj1(A,Q,$,w){let B=A.conversationId??$??w??`conversation-${JD6()}`,X=VD6("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function Ij1(A){return{userPermissionLevel:A.userPermissionLevel??"public",interfaceType:"mcp",...A.channelId?{channelId:A.channelId}:{},...A.channelName?{channelName:A.channelName}:{},actor:{actorId:A.userId,interfaceType:"mcp",role:"user"}}}function Nj1(A,Q){return[{name:"chat",description:"Talk to the brain to make changes or get reasoned answers. Use this for any create/update/delete request or questions requiring reasoning across content. For simple lookups, use search/get/list directly.",inputSchema:Jj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Jj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=Lj1(B,w.userId,w.conversationId,w.channelId),Z=Ij1(w),H=w.signal?await X.agent.chat(B.message,Y.internalId,Z,w.signal):await X.agent.chat(B.message,Y.internalId,Z);return a8A(H,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:Fj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Fj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=Lj1(B,w.userId,w.conversationId,w.channelId),Z=Ij1(w),H=w.signal?await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z,w.signal):await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z);return a8A(H,{conversationId:Y.handle})}}]}zA();function t8A(A,Q){A.messaging.subscribe("job-progress",async($)=>{let w=eS.safeParse($.payload);if(!w.success)return Q.warn("Received invalid job-progress message",{error:w.error.message}),{success:!1};let B=w.data,X=B.type,Y=B.status,Z=B.id;if(Q.debug(`${X} ${Z} - ${Y}:`,{id:B.id,message:B.message,progress:B.progress,metadata:B.metadata}),B.batchDetails)Q.debug(`Batch details for ${Z}:`,{totalOperations:B.batchDetails.totalOperations,completedOperations:B.batchDetails.completedOperations,failedOperations:B.batchDetails.failedOperations,currentOperation:B.batchDetails.currentOperation,errors:B.batchDetails.errors});if(B.jobDetails)Q.debug(`Job details for ${Z}:`,{jobType:B.jobDetails.jobType,priority:B.jobDetails.priority,retryCount:B.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var _j1={name:"@brains/mcp",version:"0.2.0-alpha.196",dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0",cors:"^2.8.5",express:"^4.18.0","express-async-handler":"^1.2.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/cors":"^2.8.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class PO extends _F{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",_j1,Q,s8A)}async getTools(){return Nj1(this.id,()=>this.context)}async getResources(){return[]}async onRegister(A){if(this.domain=A.domain,this.config.transport==="http"&&!A.plugins.has("webserver"))throw Error("MCP HTTP transport requires the webserver interface. Standalone HTTP listeners have been removed.");if(this.logger.debug(`MCP interface initialized with ${this.config.transport} transport`),this.config.transport==="http")A.endpoints.register({label:"MCP",url:"/mcp",priority:30,visibility:"trusted"}),A.interactions.register({id:"mcp",label:"MCP",description:"Connect a trusted client through the Model Context Protocol.",href:"/mcp",kind:"protocol",priority:30,visibility:"trusted"});t8A(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=xY();return this.httpServer=SF.createFresh({port:this.config.httpPort,logger:this.logger,sessionIdleTtlMs:this.config.sessionIdleTtlMs,auth:this.config.authToken?{token:this.config.authToken}:A?{requiredScopes:["mcp"],verifyBearerToken:async(Q)=>A.verifyBearerToken(Q)}:{disabled:!0}}),this.httpServer}getWebRoutes(){if(this.config.transport!=="http")return[];let A=(Q)=>this.getOrCreateHttpServer().handleRequest(Q);return[{path:"/status",method:"GET",public:!0,handler:A},{path:"/mcp",method:"GET",public:!0,handler:A},{path:"/mcp",method:"POST",public:!0,handler:A},{path:"/mcp",method:"DELETE",public:!0,handler:A},{path:"/mcp",method:"OPTIONS",public:!0,handler:A}]}createDaemon(){return{start:async()=>{await this.startServer()},stop:async()=>{await this.stopServer()},healthCheck:async()=>{let A=this.isServerRunning(),Q="MCP server not running";if(A)if(this.config.transport==="http")Q=`MCP HTTP: ${this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp"}`;else Q="MCP stdio server running";return{status:A?"healthy":"error",message:Q,lastCheck:new Date,details:{transport:this.config.transport,mode:this.config.mode,url:this.config.transport==="http"?this.domain?`https://${this.domain}/mcp`:"http://localhost:8080/mcp":void 0,running:A}}}}}isServerRunning(){if(this.config.transport==="stdio")return this.stdioServer!==void 0&&this.mcpTransport!==void 0;else return this.httpServer!==void 0&&this.mcpTransport!==void 0}async startServer(){if(!this.context)throw Error("Context not initialized");let A=this.context;this.mcpTransport=A.mcpTransport;let Q=this.config.transport==="stdio"?"stdio":"http",$=this.context.permissions.getUserLevel("mcp",Q),w=xY(),B=this.config.transport==="http"&&(this.config.authToken?!0:w!==void 0);if(B)$="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!B)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if($!=="anchor")throw Error("MCP debug mode requires anchor permissions.")}if(this.mcpTransport.setProtocolMode(this.config.mode),this.mcpTransport.setPermissionLevel($),this.logger.debug(`Starting MCP ${this.config.transport} transport in ${this.config.mode} mode with ${$} permissions`),this.config.transport==="stdio"){this.stdioServer=s3.createFresh();let X=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(X),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let X=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(X,this.mcpTransport),this.logger.debug("MCP HTTP transport mounted on shared webserver host")}}async stopServer(){if(this.logger.debug(`Stopping MCP ${this.config.transport} transport`),this.stdioServer)this.stdioServer.stop(),this.stdioServer=void 0;if(this.httpServer)await this.httpServer.stop(),this.httpServer=void 0;this.mcpTransport=void 0}async handleProgressEvent(A,Q){}async onShutdown(){s3.resetInstance(),await SF.resetInstance()}}zA();function K$0(A,Q=2000){if(A.length<=Q)return[A];let $=ND6(A),w=[],B="";for(let X of $){let Y=B?`
2349
2349
 
2350
2350
  `:"";if(B.length+Y.length+X.length<=Q){B+=Y+X;continue}if(B)w.push(B),B="";if(X.length<=Q){B=X;continue}LD6(X,Q,w,(Z)=>{B=Z})}if(B)w.push(B);return w}function LD6(A,Q,$,w){let B="",X=A.split(`
2351
2351
  `);for(let Y of X){let Z=B?`
2352
2352
  `:"";if(B.length+Z.length+Y.length<=Q){B+=Z+Y;continue}if(B)$.push(B),B="";if(Y.length<=Q){B=Y;continue}ID6(Y,Q,$,(H)=>{B=H})}w(B)}function ID6(A,Q,$,w){let B="",X=A.split(" ");for(let Y of X){let Z=B?" ":"";if(B.length+Z.length+Y.length<=Q){B+=Z+Y;continue}if(B)$.push(B);if(Y.length>Q)for(let H=0;H<Y.length;H+=Q){let K=Y.slice(H,H+Q);if(H+Q>=Y.length)B=K;else $.push(K)}else B=Y}w(B)}function ND6(A){let Q=[],$=A.split(`
2353
2353
  `),w="",B=!1;for(let X of $){if(X.startsWith("```"))B=!B;if(!B&&X===""&&w){Q.push(w),w="";continue}w+=(w?`
2354
- `:"")+X}if(w)Q.push(w);return Q}p2();var kG=k1(qYA(),1);zA();h0();var zYA=W.object({botToken:W.string().min(1).describe("Discord bot token"),allowedChannels:W.array(W.string()).default([]),requireMention:W.boolean().default(!0),allowDMs:W.boolean().default(!0),showTypingIndicator:W.boolean().default(!0),statusMessage:W.string().default("Mention me to chat"),useThreads:W.boolean().default(!0),threadAutoArchive:W.union([W.literal(60),W.literal(1440),W.literal(4320),W.literal(10080)]).default(1440),...gA0.shape,captureUrlEmoji:W.string().default("\uD83D\uDD16")});var hX2={name:"@brains/discord",version:"0.2.0-alpha.195",description:"Discord interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.26.4"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var o80=2000,sA$={completed:"Action completed",declined:"Action declined",failed:"Action failed"},aA$={completed:2278750,declined:9741240,failed:15680580},tA$=8388608,eA$=8000,A1$=100;function lN0(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class Wf extends f3{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;eventHandlerController=new AbortController;activeEventHandlers=new Set;eventHandlerStopPromise=null;eventHandlersClosed=!1;constructor(A,Q={}){super("discord",hX2,A,zYA);this.fetchText=Q.fetchText??MG1}async onRegister(A){await super.onRegister(A),this.client=new kG.Client({intents:[kG.GatewayIntentBits.Guilds,kG.GatewayIntentBits.GuildMessages,kG.GatewayIntentBits.MessageContent,kG.GatewayIntentBits.DirectMessages],partials:[kG.Partials.Channel]}),this.client.on(kG.Events.MessageCreate,(Q)=>{this.runEventHandler("message",($)=>this.handleMessage(Q,$))}),this.client.on(kG.Events.InteractionCreate,(Q)=>{this.runEventHandler("interaction",($)=>this.handleInteraction(Q,$))}),this.client.once(kG.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:()=>this.stopEventHandlers(),healthCheck:async()=>({status:this.client?.user?"healthy":"error",message:this.client?.user?`Connected as ${this.client.user.tag}`:"Not connected",lastCheck:new Date})}}runEventHandler(A,Q){if(this.eventHandlersClosed)return;let $=this.eventHandlerController.signal,w=Q($).catch((B)=>{if($.aborted)return;this.logger.error(`Discord ${A} handler failed`,{error:B})});this.activeEventHandlers.add(w),w.then(()=>{this.activeEventHandlers.delete(w)})}stopEventHandlers(){if(this.eventHandlerStopPromise)return this.eventHandlerStopPromise;this.eventHandlersClosed=!0,this.eventHandlerController.abort(Error("Discord interface has been stopped"));for(let w of this.typingIntervals.values())clearInterval(w);this.typingIntervals.clear();let A=this.client;this.client=null;let Q=A?.destroy()??Promise.resolve(),$=[...this.activeEventHandlers];return this.eventHandlerStopPromise=this.drainEventHandlers(Q,$),this.eventHandlerStopPromise}async drainEventHandlers(A,Q){let $=await Promise.allSettled([A,...Q]);this.pendingConfirmations.clear();let w=$.find((B)=>B.status==="rejected");if(w)throw w.reason}sendMessageToChannel({channelId:A,message:Q}){if(!A||!this.client)return;let $=this.client.channels.cache.get(A);if(!lN0($))return;let w=K$0(Q,o80);for(let B of w)$.send(B).catch((X)=>this.logger.error("Failed to send message",{error:X}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:$,approvalCards:w}){let B=w??($?[$]:[]),X=B.length>0?this.buildApprovalMessagePayload(Q,B):Q;return this.sendPayloadWithId(A,X)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let $=this.client.channels.cache.get(A);if(!lN0($))return;if(typeof Q!=="string")return(await $.send(Q)).id;let w=K$0(Q,o80),B;for(let X of w)B=(await $.send(X)).id;return B}async editMessage({channelId:A,messageId:Q,newMessage:$}){if(!A||!this.client)return!1;let w=this.client.channels.cache.get(A);if(!lN0(w))return!1;try{return await(await w.messages.fetch(Q)).edit($.slice(0,o80)),!0}catch{return!1}}supportsMessageEditing(){return!0}async handleMessage(A,Q){if(Q.throwIfAborted(),A.author.id===this.client?.user?.id)return;if(!this.context)return;let $=!A.guild,w=A.channel.isThread();if($&&!this.config.allowDMs)return;let B=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!B)return;let X=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,Y=this.getSpaceChannelId(A),Z=!$&&this.isConfiguredSpace(Y),H={channelId:Y,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!$&&!this.isAllowedChannel(A.channel.id,Y))return;let K=$||X||!this.config.requireMention||B;if(Z&&(!K||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,Y).catch((D)=>this.logger.error("Passive Discord space capture failed",{error:D,channelId:Y})),Q.throwIfAborted();if(!K){if(this.config.captureUrls){let D=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(D.length>0){await A.react(this.config.captureUrlEmoji).catch((q)=>this.logger.debug("React failed",{error:q}));for(let q of D)await this.captureUrlViaAgent(q,A.channel.id,A.author.id,"discord",H).catch((J)=>this.logger.error("URL capture failed",{error:J,url:q})),Q.throwIfAborted()}}return}let U=this.stripMention(A.content);if(A.attachments.size>0){let D=this.context.permissions.getUserLevel("discord",A.author.id,H);if(D==="anchor"||D==="trusted")for(let J of A.attachments.values()){let F=J.name,L=J.contentType??void 0,_=J.size;if(!this.isUploadableTextFile(F,L))continue;if(!this.isFileSizeAllowed(_))continue;try{let j=await this.fetchText(J.url);Q.throwIfAborted(),U+=`
2354
+ `:"")+X}if(w)Q.push(w);return Q}p2();var kG=k1(qYA(),1);zA();h0();var zYA=W.object({botToken:W.string().min(1).describe("Discord bot token"),allowedChannels:W.array(W.string()).default([]),requireMention:W.boolean().default(!0),allowDMs:W.boolean().default(!0),showTypingIndicator:W.boolean().default(!0),statusMessage:W.string().default("Mention me to chat"),useThreads:W.boolean().default(!0),threadAutoArchive:W.union([W.literal(60),W.literal(1440),W.literal(4320),W.literal(10080)]).default(1440),...gA0.shape,captureUrlEmoji:W.string().default("\uD83D\uDD16")});var hX2={name:"@brains/discord",version:"0.2.0-alpha.196",description:"Discord interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","discord.js":"^14.26.4"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var o80=2000,sA$={completed:"Action completed",declined:"Action declined",failed:"Action failed"},aA$={completed:2278750,declined:9741240,failed:15680580},tA$=8388608,eA$=8000,A1$=100;function lN0(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class Wf extends f3{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;eventHandlerController=new AbortController;activeEventHandlers=new Set;eventHandlerStopPromise=null;eventHandlersClosed=!1;constructor(A,Q={}){super("discord",hX2,A,zYA);this.fetchText=Q.fetchText??MG1}async onRegister(A){await super.onRegister(A),this.client=new kG.Client({intents:[kG.GatewayIntentBits.Guilds,kG.GatewayIntentBits.GuildMessages,kG.GatewayIntentBits.MessageContent,kG.GatewayIntentBits.DirectMessages],partials:[kG.Partials.Channel]}),this.client.on(kG.Events.MessageCreate,(Q)=>{this.runEventHandler("message",($)=>this.handleMessage(Q,$))}),this.client.on(kG.Events.InteractionCreate,(Q)=>{this.runEventHandler("interaction",($)=>this.handleInteraction(Q,$))}),this.client.once(kG.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:()=>this.stopEventHandlers(),healthCheck:async()=>({status:this.client?.user?"healthy":"error",message:this.client?.user?`Connected as ${this.client.user.tag}`:"Not connected",lastCheck:new Date})}}runEventHandler(A,Q){if(this.eventHandlersClosed)return;let $=this.eventHandlerController.signal,w=Q($).catch((B)=>{if($.aborted)return;this.logger.error(`Discord ${A} handler failed`,{error:B})});this.activeEventHandlers.add(w),w.then(()=>{this.activeEventHandlers.delete(w)})}stopEventHandlers(){if(this.eventHandlerStopPromise)return this.eventHandlerStopPromise;this.eventHandlersClosed=!0,this.eventHandlerController.abort(Error("Discord interface has been stopped"));for(let w of this.typingIntervals.values())clearInterval(w);this.typingIntervals.clear();let A=this.client;this.client=null;let Q=A?.destroy()??Promise.resolve(),$=[...this.activeEventHandlers];return this.eventHandlerStopPromise=this.drainEventHandlers(Q,$),this.eventHandlerStopPromise}async drainEventHandlers(A,Q){let $=await Promise.allSettled([A,...Q]);this.pendingConfirmations.clear();let w=$.find((B)=>B.status==="rejected");if(w)throw w.reason}sendMessageToChannel({channelId:A,message:Q}){if(!A||!this.client)return;let $=this.client.channels.cache.get(A);if(!lN0($))return;let w=K$0(Q,o80);for(let B of w)$.send(B).catch((X)=>this.logger.error("Failed to send message",{error:X}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:$,approvalCards:w}){let B=w??($?[$]:[]),X=B.length>0?this.buildApprovalMessagePayload(Q,B):Q;return this.sendPayloadWithId(A,X)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let $=this.client.channels.cache.get(A);if(!lN0($))return;if(typeof Q!=="string")return(await $.send(Q)).id;let w=K$0(Q,o80),B;for(let X of w)B=(await $.send(X)).id;return B}async editMessage({channelId:A,messageId:Q,newMessage:$}){if(!A||!this.client)return!1;let w=this.client.channels.cache.get(A);if(!lN0(w))return!1;try{return await(await w.messages.fetch(Q)).edit($.slice(0,o80)),!0}catch{return!1}}supportsMessageEditing(){return!0}async handleMessage(A,Q){if(Q.throwIfAborted(),A.author.id===this.client?.user?.id)return;if(!this.context)return;let $=!A.guild,w=A.channel.isThread();if($&&!this.config.allowDMs)return;let B=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!B)return;let X=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,Y=this.getSpaceChannelId(A),Z=!$&&this.isConfiguredSpace(Y),H={channelId:Y,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!$&&!this.isAllowedChannel(A.channel.id,Y))return;let K=$||X||!this.config.requireMention||B;if(Z&&(!K||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,Y).catch((D)=>this.logger.error("Passive Discord space capture failed",{error:D,channelId:Y})),Q.throwIfAborted();if(!K){if(this.config.captureUrls){let D=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(D.length>0){await A.react(this.config.captureUrlEmoji).catch((q)=>this.logger.debug("React failed",{error:q}));for(let q of D)await this.captureUrlViaAgent(q,A.channel.id,A.author.id,"discord",H).catch((J)=>this.logger.error("URL capture failed",{error:J,url:q})),Q.throwIfAborted()}}return}let U=this.stripMention(A.content);if(A.attachments.size>0){let D=this.context.permissions.getUserLevel("discord",A.author.id,H);if(D==="anchor"||D==="trusted")for(let J of A.attachments.values()){let F=J.name,L=J.contentType??void 0,_=J.size;if(!this.isUploadableTextFile(F,L))continue;if(!this.isFileSizeAllowed(_))continue;try{let j=await this.fetchText(J.url);Q.throwIfAborted(),U+=`
2355
2355
 
2356
2356
  `+this.formatFileUploadMessage(F,j)}catch(j){this.logger.error("Failed to download attachment",{error:j,filename:F})}}}if(U=U.trim(),!U)return;let G=A.channel.id;Q.throwIfAborted(),await this.routeToAgent(U,G,A,H,Q)}async handleInteraction(A,Q){if(Q.throwIfAborted(),!this.context||!A.isButton())return;let $=this.parseApprovalButtonCustomId(A.customId);if(!$)return;let w=`discord-${A.channelId}`;if(!this.pendingConfirmations.get(w)?.has($.approvalId)){await A.reply({content:"This approval is no longer pending or has changed.",ephemeral:!0}).catch((Z)=>this.logger.debug("Failed to reply to stale approval button",{error:Z}));return}await A.deferUpdate().catch((Z)=>this.logger.debug("Failed to defer approval button",{error:Z})),await this.clearApprovalInteractionComponents(A),Q.throwIfAborted();let X=this.buildInteractionConfirmationContext(A),Y=await this.context.agent.confirmPendingAction(w,$.confirmed,$.approvalId,X,Q);Q.throwIfAborted(),await this.handleAgentResponseToolStatuses(Y,w),Q.throwIfAborted(),this.syncPendingApprovalsAfterResolution(w,$.approvalId,Y),await this.sendApprovalResultMessage({channelId:A.channelId,response:Y,userPermissionLevel:X.userPermissionLevel??"public"})}async clearApprovalInteractionComponents(A){await A.message.edit({components:[]}).catch((Q)=>this.logger.debug("Failed to clear approval buttons",{error:Q}))}buildInteractionConfirmationContext(A){if(!this.context)throw Error("Discord context is not registered");return{userPermissionLevel:this.context.permissions.getUserLevel("discord",A.user.id,{channelId:A.channelId}),interfaceType:"discord",channelId:A.channelId,actor:{actorId:`discord:${A.user.id}`,interfaceType:"discord",role:"user",displayName:A.user.displayName,username:A.user.username,isBot:Boolean(A.user.bot)}}}async capturePassiveSpaceMessage(A,Q){if(!this.context)return;let $=this.stripMention(A.content).trim();if(!$)return;let w=`discord-${Q}`,B=this.getChannelName(A);await this.context.conversations.start({sessionId:w,interfaceType:"discord",channelId:Q,metadata:{channelName:B,interfaceType:"discord",channelId:Q}}),await this.context.conversations.addMessage({conversationId:w,role:"user",content:$,metadata:this.buildUserMessageMetadata(A,Q,B,{threadId:A.channel.isThread()?A.channel.id:void 0})})}async routeToAgent(A,Q,$,w,B){if(!this.context)return;let X=this.context.agent,Y=Q;if(this.config.useThreads&&$.guild&&!$.channel.isThread())try{Y=(await $.startThread({name:cW(A,A1$),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(U){this.logger.error("Failed to create thread",{error:U})}B.throwIfAborted();let Z=`discord-${Y}`,H=this.context.permissions.getUserLevel("discord",$.author.id,w),K=this.getChannelName($);this.startProcessingInput(Y);try{let U=this.client?.channels.cache.get(Y);if(lN0(U))this.startTypingIndicator(U);if(this.pendingConfirmations.has(Z)){if(await this.handleConfirmationResponse(A,Z,Y,$,w,B))return}let G=await X.chat(A,Z,{userPermissionLevel:H,interfaceType:"discord",channelId:Y,channelName:K,...this.buildUserMessageMetadata($,Q,K,{threadId:Y!==Q||$.channel.isThread()?Y:void 0})},B);B.throwIfAborted(),await this.handleAgentResponseToolStatuses(G,Z),B.throwIfAborted();let D=CC(G.cards);if(D.length>0)this.pendingConfirmations.set(Z,new Set(D.map((J)=>J.id)));else if(G.pendingConfirmations)this.pendingConfirmations.set(Z,new Set(G.pendingConfirmations.map((J)=>J.id)));else this.pendingConfirmations.delete(Z);let q=await this.sendMessageWithId({channelId:Y,message:Vc(G.text,D),approvalCards:D});if(q&&G.toolResults){for(let J of G.toolResults)if(J.jobId)this.trackAgentResponseForJob(J.jobId,q,Y)}}catch(U){if(B.aborted)return;this.logger.error("Error handling message",{error:U,channelId:Y}),this.sendMessageToChannel({channelId:Y,message:`**Error:** ${U instanceof Error?U.message:"Unknown error"}`})}finally{this.endProcessingInput(),this.stopTypingIndicator(Y)}}buildApprovalMessagePayload(A,Q){let $=Q.length>1;return{content:cW(A.trim().length>0?`${A}
2357
2357
 
@@ -2467,7 +2467,7 @@ ${A.value}
2467
2467
  ${gWA(A)}
2468
2468
  \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToMrkdwn(Q))}};function fP2(A){return Uw0(A,(Q,$)=>`<@${$}>`)}function TKA(A){if(!(A.contextId||A.privateMetadata))return;return JSON.stringify({c:A.contextId,m:A.privateMetadata})}function xP2(A){if(!A)return{};try{let Q=JSON.parse(A);if(typeof Q==="object"&&Q!==null&&(("c"in Q)||("m"in Q)))return{contextId:Q.c||void 0,privateMetadata:Q.m||void 0}}catch{}return{contextId:A}}function r_0(A,Q){return{type:"modal",callback_id:A.callbackId,title:{type:"plain_text",text:A.title.slice(0,24)},submit:A.submitLabel?{type:"plain_text",text:A.submitLabel}:{type:"plain_text",text:"Submit"},close:A.closeLabel?{type:"plain_text",text:A.closeLabel}:{type:"plain_text",text:"Cancel"},notify_on_close:A.notifyOnClose,private_metadata:Q,blocks:A.children.map(cH$)}}function cH$(A){switch(A.type){case"text_input":return pH$(A);case"select":return lH$(A);case"external_select":return iH$(A);case"radio_select":return dH$(A);case"text":return TP2(A);case"fields":return gP2(A);default:throw Error(`Unknown modal child type: ${A.type}`)}}function o_0(A){return{text:{type:"plain_text",text:A.label},value:A.value,...A.description?{description:{type:"plain_text",text:A.description}}:{}}}function pH$(A){let Q={type:"plain_text_input",action_id:A.id,multiline:A.multiline??!1};if(A.placeholder)Q.placeholder={type:"plain_text",text:A.placeholder};if(A.initialValue)Q.initial_value=A.initialValue;if(A.maxLength)Q.max_length=A.maxLength;return{type:"input",block_id:A.id,optional:A.optional??!1,label:{type:"plain_text",text:A.label},element:Q}}function lH$(A){let Q=A.options.map(o_0),$={type:"static_select",action_id:A.id,options:Q};if(A.placeholder)$.placeholder={type:"plain_text",text:A.placeholder};if(A.initialOption){let w=Q.find((B)=>B.value===A.initialOption);if(w)$.initial_option=w}return{type:"input",block_id:A.id,optional:A.optional??!1,label:{type:"plain_text",text:A.label},element:$}}function iH$(A){let Q={type:"external_select",action_id:A.id};if(A.placeholder)Q.placeholder={type:"plain_text",text:A.placeholder};if(A.minQueryLength!==void 0)Q.min_query_length=A.minQueryLength;if(A.initialOption)Q.initial_option=o_0(A.initialOption);return{type:"input",block_id:A.id,optional:A.optional??!1,label:{type:"plain_text",text:A.label},element:Q}}function dH$(A){let $=A.options.slice(0,10).map((B)=>{let X={text:{type:"mrkdwn",text:B.label},value:B.value};if(B.description)X.description={type:"mrkdwn",text:B.description};return X}),w={type:"radio_buttons",action_id:A.id,options:$};if(A.initialOption){let B=$.find((X)=>X.value===A.initialOption);if(B)w.initial_option=B}return{type:"input",block_id:A.id,optional:A.optional??!1,label:{type:"plain_text",text:A.label},element:w}}var yKA=/^[A-Z0-9_]+$/,RP2=/^U[A-Z0-9]+$/,vP2=2500;function nH$(A,Q){let $=Buffer.from(A,"utf8"),w=Buffer.from(Q,"utf8");if($.length!==w.length)return!1;return DH$($,w)}function rH$(A,Q,$){let w=A;if(w.code!=="slack_webapi_platform_error"||w.data?.error!=="invalid_blocks")return A;let B=[...w.data.errors??[],...w.data.response_metadata?.messages??[]];$.error("Slack rejected blocks (invalid_blocks)",{details:B,blocks:JSON.stringify(Q)});let X=Error(`Slack rejected blocks (invalid_blocks): ${JSON.stringify(B)}`);return X.cause=A,X}function CP2(A){let Q=A.indexOf("<@"),$=A.indexOf("<#");if(Q===-1)return $;if($===-1)return Q;return Math.min(Q,$)}var hP2=/\/$/,oH$=2000,sH$=150,aH$=/^https?:\/\/[^/]+\.slack\.com\/archives\/([A-Z0-9]+)\/p(\d+)(?:\?.*)?$/;function tH$(A={}){return{type:"context_actions",elements:[{type:"feedback_buttons",action_id:A.actionId??"message_feedback",positive_button:{text:{type:"plain_text",text:A.positiveLabel??"Good response"},value:A.positiveValue??"positive"},negative_button:{text:{type:"plain_text",text:A.negativeLabel??"Bad response"},value:A.negativeValue??"negative"}}]}}var gKA=4,eH$=new Set(["feature_not_enabled","method_deprecated","unknown_method"]);function AK$(A){let Q=A;return Q?.code==="slack_webapi_platform_error"?Q.data?.error:void 0}function QK$(A){if(A===void 0)return;if(typeof A==="function")return A;return()=>A}var $K$=class A{name="slack";userName;_client;tokenClientCache=new Map;slackApiUrl;webClientOptions;signingSecret;webhookVerifier;defaultBotTokenProvider;chat=null;logger;_botUserId=null;_botId=null;formatConverter=new uH$;static USER_CACHE_TTL_MS=691200000;static CHANNEL_CACHE_TTL_MS=691200000;static REVERSE_INDEX_TTL_MS=691200000;_externalChannels=new Set;appToken;agentView;suggestedPrompts;loadingMessages;feedbackButtons;nativeStreaming;nativeStreamingBroken=!1;mode;socketForwardingSecret;socketClient=null;clientId;clientSecret;encryptionKey;installationKeyPrefix;installationProvider;requestContext=new GH$;get botUserId(){let Q=this.requestContext.getStore();if(Q?.botUserId)return Q.botUserId;return this._botUserId||void 0}get isSocketMode(){return this.mode==="socket"}get webClient(){let Q=this.requestContext.getStore();if(Q?.token)return this.getClientForToken(Q.token);if(this.defaultBotTokenProvider){let $=this.defaultBotTokenProvider();if(typeof $==="string")return this.getClientForToken($);throw new md("slack","botToken is configured as an async resolver and cannot be resolved synchronously for `.webClient`. Wrap the work in `adapter.withBotToken(token, () => adapter.webClient...)` after awaiting the token.")}throw new md("slack","No bot token available. In multi-workspace mode, ensure the webhook is being processed or use `adapter.withBotToken(token, fn)` to bind a token explicitly.")}get client(){return this.webClient}getClientForToken(Q){let $=this.tokenClientCache.get(Q);if(!$)$=new mKA.WebClient(Q,{...this.webClientOptions,...this.webClientOptions?.headers?{headers:{...this.webClientOptions.headers}}:{},...this.slackApiUrl?{slackApiUrl:this.slackApiUrl}:{}}),this.tokenClientCache.set(Q,$);return $}constructor(Q={}){let $=Q.webhookVerifier,w=$?void 0:Q.signingSecret??process.env.SLACK_SIGNING_SECRET;if(!(w||$)&&(Q.mode??"webhook")==="webhook")throw new G7("slack","signingSecret or webhookVerifier is required for webhook mode. Set SLACK_SIGNING_SECRET, provide signingSecret in config, or provide a webhookVerifier.");let B=!(Q.signingSecret||Q.botToken||Q.clientId||Q.clientSecret),X=Q.botToken??(B?process.env.SLACK_BOT_TOKEN:void 0),Y=QK$(X);if(this.slackApiUrl=Q.apiUrl??process.env.SLACK_API_URL,this.webClientOptions=Q.webClientOptions,this._client=new mKA.WebClient(void 0,{...this.webClientOptions,...this.webClientOptions?.headers?{headers:{...this.webClientOptions.headers}}:{},...this.slackApiUrl?{slackApiUrl:this.slackApiUrl}:{}}),this.signingSecret=w,this.webhookVerifier=$,this.defaultBotTokenProvider=Y,this.logger=Q.logger??new dWA("info").child("slack"),this.userName=Q.userName||"bot",this._botUserId=Q.botUserId||null,this.appToken=Q.appToken,this.agentView=Q.agentView??!1,this.suggestedPrompts=Q.suggestedPrompts,this.loadingMessages=Q.loadingMessages,this.nativeStreaming=Q.nativeStreaming??!0,Q.feedbackButtons)this.feedbackButtons=Q.feedbackButtons===!0?{}:Q.feedbackButtons;this.mode=Q.mode??"webhook",this.socketForwardingSecret=Q.socketForwardingSecret??Q.appToken,this.clientId=Q.clientId??(B?process.env.SLACK_CLIENT_ID:void 0),this.clientSecret=Q.clientSecret??(B?process.env.SLACK_CLIENT_SECRET:void 0),this.installationKeyPrefix=Q.installationKeyPrefix??"slack:installation";let Z=Q.encryptionKey??process.env.SLACK_ENCRYPTION_KEY;if(Z)this.encryptionKey=uV2(Z);this.installationProvider=Q.installationProvider}async getToken(){let Q=this.requestContext.getStore();if(Q?.token)return Q.token;if(this.defaultBotTokenProvider)return await this.defaultBotTokenProvider();throw new md("slack","No bot token available. In multi-workspace mode, ensure the webhook is being processed.")}async withToken(Q){return{...Q,token:await this.getToken()}}async initialize(Q){if(this.chat=Q,this.defaultBotTokenProvider&&!this._botUserId)try{let $=await this._client.auth.test(await this.withToken({}));if(this._botUserId=$.user_id,this._botId=$.bot_id||null,$.user)this.userName=$.user;this.logger.info("Slack auth completed",{botUserId:this._botUserId,botId:this._botId})}catch($){this.logger.warn("Could not fetch bot user ID",{error:$})}if(!this.defaultBotTokenProvider)this.logger.info("Slack adapter initialized in multi-workspace mode");if(this.mode==="socket")await this.startSocketMode()}installationKey(Q){return`${this.installationKeyPrefix}:${Q}`}async setInstallation(Q,$){if(!this.chat)throw new G7("slack","Adapter not initialized. Ensure chat.initialize() has been called first.");let w=this.chat.getState(),B=this.installationKey(Q),X=this.encryptionKey?{...$,botToken:gV2($.botToken,this.encryptionKey)}:$;await w.set(B,X),this.logger.info("Slack installation saved",{teamId:Q,teamName:$.teamName})}async getInstallation(Q){if(!this.chat)throw new G7("slack","Adapter not initialized. Ensure chat.initialize() has been called first.");let $=this.chat.getState(),w=this.installationKey(Q),B=await $.get(w);if(!B)return null;if(this.encryptionKey&&mV2(B.botToken))return{...B,botToken:SV2(B.botToken,this.encryptionKey)};return B}async handleOAuthCallback(Q,$){if(!(this.clientId&&this.clientSecret))throw new G7("slack","clientId and clientSecret are required for OAuth. Pass them in createSlackAdapter().");let w=new URL(Q.url),B=w.searchParams.get("code");if(!B)throw new G7("slack","Missing 'code' query parameter in OAuth callback request.");let X=$?.redirectUri??w.searchParams.get("redirect_uri")??void 0,Y=await this._client.oauth.v2.access({client_id:this.clientId,client_secret:this.clientSecret,code:B,...X?{redirect_uri:X}:{}});if(!(Y.ok&&Y.access_token&&Y.team?.id))throw new md("slack",`Slack OAuth failed: ${Y.error||"missing access_token or team.id"}`);let Z=Y.team.id,H={botToken:Y.access_token,botUserId:Y.bot_user_id,teamName:Y.team.name};return await this.setInstallation(Z,H),{teamId:Z,installation:H}}async deleteInstallation(Q){if(!this.chat)throw new G7("slack","Adapter not initialized. Ensure chat.initialize() has been called first.");await this.chat.getState().delete(this.installationKey(Q)),this.logger.info("Slack installation deleted",{teamId:Q})}withBotToken(Q,$){return this.requestContext.run({token:Q},$)}async resolveTokenForTeam(Q,$=!1){try{if(this.installationProvider){let B=await this.installationProvider.getInstallation(Q,$);if(B)return{token:B.botToken,botUserId:B.botUserId};return this.logger.warn("No installation found from provider",{installationId:Q,isEnterpriseInstall:$}),null}let w=await this.getInstallation(Q);if(w)return{token:w.botToken,botUserId:w.botUserId};return this.logger.warn("No installation found for team",{installationId:Q,isEnterpriseInstall:$}),null}catch(w){return this.logger.error("Failed to resolve token for team",{installationId:Q,isEnterpriseInstall:$,error:w}),null}}extractInstallationFromInteractive(Q){try{let w=new URLSearchParams(Q).get("payload");if(!w)return null;let B=JSON.parse(w),X=Boolean(B.is_enterprise_install),Y=B.enterprise?.id||B.enterprise_id||void 0,Z=B.team?.id||B.team_id||void 0,H=X?Y:Z;if(!H)return null;return{installationId:H,isEnterpriseInstall:X,enterpriseId:Y}}catch{return null}}async lookupUser(Q){let $=`slack:user:${Q}`;if(this.chat){let w=await this.chat.getState().get($);if(w)return w}try{let B=(await this._client.users.info(await this.withToken({user:Q}))).user,X=B?.profile?.display_name||B?.profile?.real_name||B?.real_name||B?.name||Q,Y=B?.real_name||B?.profile?.real_name||X,Z={avatarUrl:B?.profile?.image_192,displayName:X,email:B?.profile?.email,isBot:B?.is_bot,realName:Y};if(this.chat){await this.chat.getState().set($,Z,A.USER_CACHE_TTL_MS);let K=`slack:user-by-name:${X.toLowerCase()}`;if(!(await this.chat.getState().getList(K)).includes(Q))await this.chat.getState().appendToList(K,Q,{maxLength:50,ttlMs:A.REVERSE_INDEX_TTL_MS})}return this.logger.debug("Fetched user info",{userId:Q,displayName:X,realName:Y}),Z}catch(w){return this.logger.warn("Could not fetch user info",{userId:Q,error:w}),null}}async lookupChannel(Q){let $=`slack:channel:${Q}`;if(this.chat){let w=await this.chat.getState().get($);if(w)return w.name}try{let B=(await this._client.conversations.info(await this.withToken({channel:Q}))).channel?.name||Q;if(this.chat)await this.chat.getState().set($,{name:B},A.CHANNEL_CACHE_TTL_MS);return this.logger.debug("Fetched channel info",{channelId:Q,name:B}),B}catch(w){return this.logger.warn("Could not fetch channel info",{channelId:Q,error:w}),Q}}async getUser(Q){try{let $=await this.lookupUser(Q);if(!$)return null;return{avatarUrl:$.avatarUrl,email:$.email,fullName:$.realName,isBot:$.isBot??!1,userId:Q,userName:$.displayName}}catch{return null}}async handleWebhook(Q,$){let w=Q.headers.get("x-slack-socket-token");if(w){if(!(this.socketForwardingSecret&&nH$(w,this.socketForwardingSecret)))return this.logger.warn("Invalid socket forwarding token"),new Response("Invalid socket token",{status:401});this.logger.info("Slack forwarded socket event received");try{let Z=await Q.text(),H=JSON.parse(Z),K=async()=>{};return await this.routeSocketEvent(H.body,H.eventType,K,$),new Response("ok",{status:200})}catch{return new Response("Invalid JSON",{status:400})}}if(this.mode==="socket")return new Response("Webhooks are disabled in socket mode",{status:405});let B;try{B=await HV2(Q,{signingSecret:this.signingSecret,webhookVerifier:this.webhookVerifier})}catch(Z){return this.logger.warn("Webhook verifier rejected request",{error:Z}),new Response("Invalid signature",{status:401})}if(this.logger.debug("Slack webhook raw body",{body:B}),(Q.headers.get("content-type")||"").includes("application/x-www-form-urlencoded")){let Z=new URLSearchParams(B);if(Z.has("command")&&!Z.has("payload")){if(!this.defaultBotTokenProvider){let H=Z.get("is_enterprise_install")==="true",K=H?Z.get("enterprise_id"):Z.get("team_id");if(K){let U=await this.resolveTokenForTeam(K,H);if(U)return this.requestContext.run({...U,enterpriseId:Z.get("enterprise_id")??void 0,isEnterpriseInstall:H},()=>this.handleSlashCommand(Z,$));this.logger.warn("Could not resolve token for slash command",{installationId:K,isEnterpriseInstall:H})}}return this.handleSlashCommand(Z,$)}if(!this.defaultBotTokenProvider){let H=this.extractInstallationFromInteractive(B);if(H){let K=await this.resolveTokenForTeam(H.installationId,H.isEnterpriseInstall);if(K)return this.requestContext.run({...K,enterpriseId:H.enterpriseId,isEnterpriseInstall:H.isEnterpriseInstall},()=>this.handleInteractivePayload(B,$))}this.logger.warn("Could not resolve token for interactive payload")}return this.handleInteractivePayload(B,$)}let Y;try{Y=JSON.parse(B)}catch{return new Response("Invalid JSON",{status:400})}if(Y.type==="url_verification"&&Y.challenge)return Response.json({challenge:Y.challenge});if(!this.defaultBotTokenProvider&&Y.type==="event_callback"){let Z=Boolean(Y.is_enterprise_install),H=Z?Y.enterprise_id:Y.team_id;if(H){let K=await this.resolveTokenForTeam(H,Z);if(K)return this.requestContext.run({...K,enterpriseId:Y.enterprise_id,isEnterpriseInstall:Z},()=>{return this.processEventPayload(Y,$),new Response("ok",{status:200})});return this.logger.warn("Could not resolve token for installation",{installationId:H,isEnterpriseInstall:Z}),new Response("ok",{status:200})}}return this.processEventPayload(Y,$),new Response("ok",{status:200})}processEventPayload(Q,$){if(Q.type==="event_callback"&&Q.event){let w=Q.event;if(Q.is_ext_shared_channel){let B;if("channel"in w)B=w.channel;else if("item"in w)B=w.item.channel;if(B)this._externalChannels.add(B)}if(w.type==="message"||w.type==="app_mention"){let B=w;if(!(B.team||B.team_id)&&Q.team_id)B.team_id=Q.team_id;this.handleMessageEvent(B,$)}else if(w.type==="reaction_added"||w.type==="reaction_removed"){let B=this.handleReactionEvent(w,$);$?.waitUntil?.(B)}else if(w.type==="assistant_thread_started")this.handleAssistantThreadStarted(w,$);else if(w.type==="assistant_thread_context_changed")this.handleAssistantContextChanged(w,$);else if(w.type==="app_context_changed")this.handleAppContextChanged(w,$);else if(w.type==="app_home_opened"){let B=w;if(this.agentView||B.tab==="home")this.handleAppHomeOpened(B,$)}else if(w.type==="member_joined_channel")this.handleMemberJoinedChannel(w,$);else if(w.type==="user_change")this.handleUserChange(w)}}handleInteractivePayload(Q,$){let B=new URLSearchParams(Q).get("payload");if(!B)return new Response("Missing payload",{status:400});let X;try{X=JSON.parse(B)}catch{return new Response("Invalid payload JSON",{status:400})}return this.dispatchInteractivePayload(X,$)}dispatchInteractivePayload(Q,$){switch(Q.type){case"block_actions":return this.handleBlockActions(Q,$),new Response("",{status:200});case"block_suggestion":return this.handleBlockSuggestion(Q,$);case"view_submission":return this.handleViewSubmission(Q,$);case"view_closed":return this.handleViewClosed(Q,$),new Response("",{status:200});default:return new Response("",{status:200})}}async handleSlashCommand(Q,$){if(!this.chat)return this.logger.warn("Chat instance not initialized, ignoring slash command"),new Response("",{status:200});let w=Q.get("command")||"",B=Q.get("text")||"",X=Q.get("user_id")||"",Y=Q.get("channel_id")||"",Z=Q.get("trigger_id")||void 0;this.logger.debug("Processing Slack slash command",{command:w,text:B,userId:X,channelId:Y,triggerId:Z});let H=await this.lookupUser(X),K={command:w,text:B,user:{userId:X,userName:H?.displayName??X,fullName:H?.realName??X,isBot:!1,isMe:!1},adapter:this,raw:Object.fromEntries(Q),triggerId:Z,channelId:Y?`slack:${Y}`:""};return this.chat.processSlashCommand(K,$),new Response("",{status:200})}handleBlockActions(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring action");return}let w=Q.channel?.id||Q.container?.channel_id,B=Q.message?.ts||Q.container?.message_ts,X=Q.message?.thread_ts||Q.container?.thread_ts||B;if(!(Q.container?.type==="view"||w)){this.logger.warn("Missing channel in block_actions",{channel:w});return}let Z=w&&(X||B)?this.encodeThreadId({channel:w,threadTs:X||B||""}):"",H=Q.container?.is_ephemeral===!0,K=Q.response_url,U=H&&K&&B?this.encodeEphemeralMessageId(B,K,Q.user.id):B||"";for(let G of Q.actions){let D=G.selected_option?.value??G.value,q={actionId:G.action_id,value:D,user:{userId:Q.user.id,userName:Q.user.username||Q.user.name||"unknown",fullName:Q.user.name||Q.user.username||"unknown",isBot:!1,isMe:!1},messageId:U,threadId:Z,adapter:this,raw:Q,triggerId:Q.trigger_id};this.logger.debug("Processing Slack block action",{actionId:G.action_id,value:G.value,messageId:B,threadId:Z,triggerId:Q.trigger_id}),this.chat.processAction(q,$)}}async handleBlockSuggestion(Q,$){if(!this.chat)return this.logger.warn("Chat instance not initialized, ignoring block suggestion"),this.optionsLoadResponse([]);let w=this.chat.processOptionsLoad({actionId:Q.action_id,query:Q.value??"",user:{userId:Q.user.id,userName:Q.user.username||Q.user.name||Q.user.id,fullName:Q.user.name||Q.user.username||Q.user.id,isBot:!1,isMe:!1},adapter:this,raw:Q},$),B=Symbol("options_load_timeout"),X,Y=new Promise((H)=>{X=setTimeout(()=>H(B),vP2)}),Z=await Promise.race([w,Y]);if(X)clearTimeout(X);if(Z===B)return this.logger.warn("Options load handler timed out",{actionId:Q.action_id,timeoutMs:vP2}),w.catch((H)=>this.logger.error("Options load handler error after timeout",{error:H,actionId:Q.action_id})),this.optionsLoadResponse([]);return this.optionsLoadResponse(Z??[])}optionsLoadResponse(Q){if(Q.length>0&&"options"in Q[0]&&Array.isArray(Q[0].options)){let B=Q.slice(0,100).map((X)=>({label:{type:"plain_text",text:X.label.slice(0,75)},options:X.options.slice(0,100).map(o_0)}));return new Response(JSON.stringify({option_groups:B}),{status:200,headers:{"Content-Type":"application/json"}})}let w=Q.slice(0,100).map(o_0);return new Response(JSON.stringify({options:w}),{status:200,headers:{"Content-Type":"application/json"}})}async handleViewSubmission(Q,$){if(!this.chat)return this.logger.warn("Chat instance not initialized, ignoring view submission"),new Response("",{status:200});let w={};for(let H of Object.values(Q.view.state.values))for(let[K,U]of Object.entries(H))w[K]=U.value??U.selected_option?.value??"";let{contextId:B,privateMetadata:X}=xP2(Q.view.private_metadata||void 0),Y={callbackId:Q.view.callback_id,viewId:Q.view.id,values:w,privateMetadata:X,user:{userId:Q.user.id,userName:Q.user.username||Q.user.name||"unknown",fullName:Q.user.name||Q.user.username||"unknown",isBot:!1,isMe:!1},adapter:this,raw:Q},Z=await this.chat.processModalSubmit(Y,B,$);if(Z){let H=this.modalResponseToSlack(Z,B);return new Response(JSON.stringify(H),{status:200,headers:{"Content-Type":"application/json"}})}return new Response("",{status:200})}handleViewClosed(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring view closed");return}let{contextId:w,privateMetadata:B}=xP2(Q.view.private_metadata||void 0),X={callbackId:Q.view.callback_id,viewId:Q.view.id,privateMetadata:B,user:{userId:Q.user.id,userName:Q.user.username||Q.user.name||"unknown",fullName:Q.user.name||Q.user.username||"unknown",isBot:!1,isMe:!1},adapter:this,raw:Q};this.chat.processModalClose(X,w,$)}modalResponseToSlack(Q,$){switch(Q.action){case"close":return{};case"clear":return{response_action:"clear"};case"errors":return{response_action:"errors",errors:Q.errors};case"update":{let w=this.convertModalJSX(Q.modal),B=TKA({contextId:$,privateMetadata:w.privateMetadata});return{response_action:"update",view:r_0(w,B)}}case"push":{let w=this.convertModalJSX(Q.modal),B=TKA({contextId:$,privateMetadata:w.privateMetadata});return{response_action:"push",view:r_0(w,B)}}default:return{}}}convertModalJSX(Q){if(MV2(Q)){let $=kV2(Q);if(!$)throw new G7("slack","Invalid JSX element: must be a Modal element");return $}return Q}async startSocketMode(){if(!this.appToken)throw new G7("slack","appToken is required for socket mode. Set SLACK_APP_TOKEN or provide it in config.");this.socketClient=new SKA.SocketModeClient({appToken:this.appToken}),this.socketClient.on("slack_event",async({ack:Q,body:$,type:w,retry_num:B,retry_reason:X})=>{if(B&&B>0)this.logger.info("Processing socket mode retry",{retry_num:B,retry_reason:X,type:w});await this.routeSocketEvent($,w,Q)}),await this.socketClient.start(),this.logger.info("Slack socket mode connected")}async routeSocketEvent(Q,$,w,B){let X=(Y)=>{if(B?.waitUntil)B.waitUntil(Y);else Y.catch((Z)=>{this.logger.error("Error in socket mode async handler",{error:Z})})};switch($){case"events_api":{if(await w(),!Q.event||typeof Q.event!=="object"){this.logger.warn("Socket mode events_api missing event field",{body:Q});break}let Y={type:"event_callback",event:Q.event,team_id:Q.team_id,event_id:Q.event_id,event_time:Q.event_time};try{this.processEventPayload(Y,B)}catch(Z){this.logger.error("Error processing socket mode events_api",{error:Z})}break}case"slash_commands":{await w();let Y=new URLSearchParams;for(let[Z,H]of Object.entries(Q))if(typeof H==="string")Y.set(Z,H);X(this.handleSlashCommand(Y,B));break}case"interactive":{let Y=Q,Z=this.dispatchInteractivePayload(Y,B),H=Z instanceof Promise?await Z:Z,K=H.headers.get("content-type")?.includes("application/json")?await H.json():void 0;await w(K);break}default:await w(),this.logger.debug("Unhandled socket mode event type",{type:$})}}async startSocketModeListener(Q,$=180000,w,B){if(!this.appToken)return new Response("appToken is required for socket mode listener",{status:500});if(!Q.waitUntil)return new Response("waitUntil not provided",{status:500});this.logger.info("Starting Slack socket mode listener",{durationMs:$,webhookUrl:B?"configured":"not configured"});let X=this.runSocketModeListener($,w,B,Q);return Q.waitUntil(X),new Response(JSON.stringify({status:"listening",durationMs:$,message:`Socket mode listener started, will run for ${$/1000} seconds`}),{status:200,headers:{"Content-Type":"application/json"}})}async runSocketModeListener(Q,$,w,B){let X=this.appToken,Y=new SKA.SocketModeClient({appToken:X}),Z=!1;Y.on("slack_event",async({ack:H,body:K,type:U,retry_num:G,retry_reason:D})=>{if(Z)return;if(G&&G>0)this.logger.info("Processing socket mode retry",{retry_num:G,retry_reason:D,type:U});let q=U;if(w)await H(),await this.forwardSocketEvent(w,{type:"socket_event",eventType:q,body:K,timestamp:Date.now()});else await this.routeSocketEvent(K,q,H,B)});try{await Y.start(),this.logger.info("Slack socket mode listener connected"),await new Promise((H)=>{let K=setTimeout(H,Q);if($){if($.aborted){clearTimeout(K),H();return}$.addEventListener("abort",()=>{this.logger.info("Slack socket mode listener received abort signal"),clearTimeout(K),H()},{once:!0})}}),this.logger.info("Slack socket mode listener duration elapsed, disconnecting")}catch(H){this.logger.error("Slack socket mode listener error",{error:String(H)})}finally{Z=!0,await Y.disconnect(),this.logger.info("Slack socket mode listener stopped")}}async forwardSocketEvent(Q,$){try{this.logger.debug("Forwarding socket event to webhook",{type:$.body.type||"unknown",webhookUrl:Q});let w=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-slack-socket-token":this.socketForwardingSecret},body:JSON.stringify($)});if(w.ok)this.logger.debug("Socket event forwarded successfully",{type:$.body.type||"unknown"});else{let B=await w.text();this.logger.error("Failed to forward socket event",{type:$.body.type||"unknown",status:w.status,error:B})}}catch(w){this.logger.error("Error forwarding socket event",{type:$.body.type||"unknown",error:String(w)})}}async disconnect(){if(this.socketClient)await this.socketClient.disconnect(),this.socketClient=null,this.logger.info("Slack socket mode disconnected")}handleMessageEvent(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring event");return}let w=new Set(["message_deleted","message_replied","channel_join","channel_leave","channel_topic","channel_purpose","channel_name","channel_archive","channel_unarchive","group_join","group_leave","group_topic","group_purpose","group_name","group_archive","group_unarchive","ekm_access_denied","tombstone"]);if(Q.subtype==="message_changed"){this.handleMessageChanged(Q,$);return}if(Q.subtype&&w.has(Q.subtype)){this.logger.debug("Ignoring message subtype",{subtype:Q.subtype});return}if(!(Q.channel&&Q.ts)){this.logger.debug("Ignoring event without channel or ts",{channel:Q.channel,ts:Q.ts});return}let B=Q.channel_type==="im",X=B&&!this.agentView?Q.thread_ts||"":Q.thread_ts||Q.ts,Y=this.encodeThreadId({channel:Q.channel,threadTs:X}),Z=Q.type==="app_mention",H=(K)=>async()=>{let U=await this.parseSlackMessage(Q,K);if(Z)U.isMention=!0;return U};if(this.agentView&&B&&!Q.thread_ts){let K=this.chat,U=this.encodeThreadId({channel:Q.channel,threadTs:""}),G=(async()=>{let D=Y;try{if(await K.getState().isSubscribed(U))D=U}catch(q){this.logger.warn("agent_view DM subscription check failed; using per-message thread",{error:String(q),threadId:Y})}K.processMessage(this,D,H(D),$)})();$?.waitUntil?.(G);return}this.chat.processMessage(this,Y,H(Y),$)}handleMessageChanged(Q,$){let w=Q.message;if(!(w&&Q.channel))return;if(!w.attachments?.some((Y)=>Y.from_url||Y.original_url)){this.logger.debug("Ignoring message_changed without unfurl data");return}if(this.logger.debug("Processing message_changed for link unfurls",{channel:Q.channel,ts:w.ts,attachmentCount:w.attachments?.length}),!(this.chat&&w.ts&&w.attachments))return;let X={};for(let Y of w.attachments){let Z=Y.from_url||Y.original_url;if(Z&&(Y.title||Y.text))X[Z]={title:Y.title,description:Y.text,imageUrl:Y.image_url||Y.thumb_url,siteName:Y.service_name}}if(Object.keys(X).length>0)this.chat.getState().set(`slack:unfurls:${w.ts}`,X,3600000).catch((Y)=>{this.logger.error("Failed to cache unfurl metadata",{error:Y})})}async handleReactionEvent(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring reaction");return}if(Q.item.type!=="message"){this.logger.debug("Ignoring reaction to non-message item",{itemType:Q.item.type});return}let w=Q.item.ts;try{let F=(await this._client.conversations.replies(await this.withToken({channel:Q.item.channel,ts:Q.item.ts,limit:1}))).messages?.[0];if(F?.thread_ts)w=F.thread_ts}catch(J){this.logger.warn("Failed to resolve parent thread for reaction, using message ts",{error:String(J),channel:Q.item.channel,ts:Q.item.ts})}let B=this.encodeThreadId({channel:Q.item.channel,threadTs:w}),X=Q.item.ts,Y=Q.reaction,Z=gd.fromSlack(Y),H=this.requestContext.getStore(),K=H?.botUserId&&Q.user===H.botUserId||this._botUserId!==null&&Q.user===this._botUserId||this._botId!==null&&Q.user===this._botId,U=await this.lookupUser(Q.user),G=U?.displayName??Q.user,D=U?.realName??G,q={emoji:Z,rawEmoji:Y,added:Q.type==="reaction_added",user:{userId:Q.user,userName:G,fullName:D,isBot:U?.isBot??!1,isMe:K},messageId:X,threadId:B,raw:Q};this.chat.processReaction({...q,adapter:this},$)}handleAssistantThreadStarted(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring assistant_thread_started");return}if(!Q.assistant_thread){this.logger.warn("Malformed assistant_thread_started: missing assistant_thread");return}let{channel_id:w,thread_ts:B,user_id:X,context:Y}=Q.assistant_thread,Z=this.encodeThreadId({channel:w,threadTs:B}),H=this.applyConfiguredSuggestedPrompts({channelId:w,enterpriseId:Y.enterprise_id,teamId:Y.team_id,threadTs:B,userId:X});$?.waitUntil?.(H),this.chat.processAssistantThreadStarted({threadId:Z,userId:X,channelId:w,threadTs:B,context:{channelId:Y.channel_id,teamId:Y.team_id,enterpriseId:Y.enterprise_id,threadEntryPoint:Y.thread_entry_point,forceSearch:Y.force_search},adapter:this},$)}handleAssistantContextChanged(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring assistant_thread_context_changed");return}if(!Q.assistant_thread){this.logger.warn("Malformed assistant_thread_context_changed: missing assistant_thread");return}let{channel_id:w,thread_ts:B,user_id:X,context:Y}=Q.assistant_thread,Z=this.encodeThreadId({channel:w,threadTs:B});this.chat.processAssistantContextChanged({threadId:Z,userId:X,channelId:w,threadTs:B,context:{channelId:Y.channel_id,teamId:Y.team_id,enterpriseId:Y.enterprise_id,threadEntryPoint:Y.thread_entry_point,forceSearch:Y.force_search},adapter:this},$)}handleAppHomeOpened(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring app_home_opened");return}if(this.agentView&&Q.tab==="messages"){let w=this.applyConfiguredSuggestedPrompts({channelId:Q.channel,userId:Q.user,...Q.context?{entities:CKA(Q.context)}:{}});$?.waitUntil?.(w)}this.chat.processAppHomeOpened({userId:Q.user,channelId:Q.channel,tab:Q.tab,adapter:this,...Q.context?{entities:CKA(Q.context)}:{}},$)}handleAppContextChanged(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring app_context_changed");return}this.chat.processAppContextChanged({channelId:Q.channel,userId:Q.user,entities:CKA(Q.context),raw:Q,adapter:this},$)}handleMemberJoinedChannel(Q,$){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring member_joined_channel");return}this.chat.processMemberJoinedChannel({userId:Q.user,channelId:this.encodeThreadId({channel:Q.channel,threadTs:""}),inviterId:Q.inviter,adapter:this},$)}async handleUserChange(Q){if(!this.chat)return;try{await this.chat.getState().delete(`slack:user:${Q.user.id}`)}catch($){this.logger.warn("Failed to invalidate user cache",{userId:Q.user.id,error:$})}}async publishHomeView(Q,$){await this._client.views.publish(await this.withToken({user_id:Q,view:$}))}async setSuggestedPrompts(Q,$,w,B){await this._client.assistant.threads.setSuggestedPrompts(await this.withToken({channel_id:Q,prompts:w,...$?{thread_ts:$}:{},...B?{title:B}:{}}))}async applyConfiguredSuggestedPrompts(Q){if(!this.suggestedPrompts)return;try{let $=typeof this.suggestedPrompts==="function"?await this.suggestedPrompts(Q):this.suggestedPrompts;if(!$||$.prompts.length===0)return;let w=$.prompts;if(w.length>gKA)this.logger.warn(`Slack shows at most ${gKA} suggested prompts; dropping the rest`,{configured:w.length}),w=w.slice(0,gKA);await this.setSuggestedPrompts(Q.channelId,Q.threadTs,w,$.title)}catch($){this.logger.warn("Failed to apply configured suggested prompts",{channelId:Q.channelId,error:$})}}async setAssistantStatus(Q,$,w,B){let X=B??this.loadingMessages;await this._client.assistant.threads.setStatus(await this.withToken({channel_id:Q,thread_ts:$,status:w,...X&&{loading_messages:X}}))}async setAssistantTitle(Q,$,w){await this._client.assistant.threads.setTitle(await this.withToken({channel_id:Q,thread_ts:$,title:w}))}async resolveInlineMentions(Q,$){let w=new Set,B=new Set;for(let q of Q.split("<")){let J=q.indexOf(">");if(J===-1)continue;let F=q.slice(0,J);if(F.startsWith("@")){let L=F.slice(1),_=L.indexOf("|"),j=_>=0?L.slice(0,_):L;if(yKA.test(j))w.add(j)}else if(F.startsWith("#")){let L=F.slice(1);if(L.indexOf("|")===-1&&yKA.test(L))B.add(L)}}if(w.size===0&&B.size===0)return Q;let X=this.botUserId;if($&&X)w.delete(X);if(w.size===0&&B.size===0)return Q;let[Y,Z]=await Promise.all([Promise.all([...w].map(async(q)=>{let J=await this.lookupUser(q);return[q,J?.displayName??q]})),Promise.all([...B].map(async(q)=>{let J=await this.lookupChannel(q);return[q,J]}))]),H=new Map(Y),K=new Map(Z),U="",G=Q,D=CP2(G);while(D!==-1){U+=G.slice(0,D),G=G.slice(D);let q=G.indexOf(">");if(q===-1)break;let J=G[1],F=G.slice(2,q),L=F.indexOf("|"),_=L>=0?F.slice(0,L):F;if(J==="@"&&yKA.test(_)){let j=H.get(_);U+=j?`<@${_}|${j}>`:`<@${_}>`}else if(J==="#"&&L===-1&&K.has(_)){let j=K.get(_);U+=`<#${_}|${j}>`}else U+=G.slice(0,q+1);G=G.slice(q+1),D=CP2(G)}return U+G}extractLinks(Q){let $=new Set;if(Q.blocks){for(let B of Q.blocks)if(B.type==="rich_text"&&B.elements){for(let X of B.elements)if(X.elements){for(let Y of X.elements)if(Y.type==="link"&&Y.url)$.add(Y.url)}}}if($.size===0&&Q.text){let B=/<(https?:\/\/[^>]+)>/g;for(let X of Q.text.matchAll(B)){let Y=X[1],Z=Y.indexOf("|");$.add(Z>=0?Y.slice(0,Z):Y)}}let w=new Map;if(Q.attachments)for(let B of Q.attachments){let X=B.from_url||B.original_url;if(X&&(B.title||B.text))w.set(X,{title:B.title,description:B.text,imageUrl:B.image_url||B.thumb_url,siteName:B.service_name}),$.add(X)}return[...$].map((B)=>{let X=this.createLinkPreview(B),Y=w.get(B)||w.get(B.replace(hP2,""))||w.get(`${B}/`);if(Y)return{...X,...Y};return X})}createLinkPreview(Q){let $=aH$.exec(Q);if(!$)return{url:Q};let w=$[1],B=$[2],X=`${B.slice(0,B.length-6)}.${B.slice(B.length-6)}`,Y=this.encodeThreadId({channel:w,threadTs:X});return{url:Q,fetchMessage:async()=>{let K=((await this._client.conversations.history(await this.withToken({channel:w,latest:X,inclusive:!0,limit:1}))).messages||[]).find((U)=>U.ts===X);if(!K)throw Error(`Message not found: ${Q}`);return this.parseSlackMessage(K,Y)}}}async parseSlackMessage(Q,$,w){let B=this.isMessageFromSelf(Q),X=w?.skipSelfMention??!0,Y=Q.text||"",Z=Q.username||"unknown",H=Q.username||"unknown";if(Q.user&&!Q.username){let U=await this.lookupUser(Q.user);Z=U?.displayName??Q.user,H=U?.realName??Z}if(Q.user&&this.chat)try{let U=`slack:thread-participants:${$}`;if(!(await this.chat.getState().getList(U)).includes(Q.user))await this.chat.getState().appendToList(U,Q.user,{maxLength:100,ttlMs:A.REVERSE_INDEX_TTL_MS})}catch(U){this.logger.warn("Failed to track thread participant",{threadId:$,userId:Q.user,error:U})}let K=await this.resolveInlineMentions(Y,X);return new iWA({id:Q.ts||"",threadId:$,text:this.formatConverter.extractPlainText(K),formatted:this.formatConverter.toAst(K),raw:Q,author:{userId:Q.user||Q.bot_id||"unknown",userName:Z,fullName:H,isBot:!!Q.bot_id,isMe:B},metadata:{dateSent:new Date(Number.parseFloat(Q.ts||"0")*1000),edited:!!Q.edited,editedAt:Q.edited?new Date(Number.parseFloat(Q.edited.ts)*1000):void 0},attachments:(Q.files||[]).map((U)=>this.createAttachment(U,Q.team_id??Q.team)),links:await this.enrichLinks(this.extractLinks(Q),Q.ts)})}async enrichLinks(Q,$){if(!(this.chat&&$)||Q.length===0)return Q;if(Q.every((Z)=>Z.title||Z.fetchMessage))return Q;let B=Date.now()+oH$,X=this.chat.getState(),Y=null;while(!0){try{Y=await X.get(`slack:unfurls:${$}`)}catch{return Q}if(Y||Date.now()>=B)break;await new Promise((Z)=>setTimeout(Z,sH$))}if(!Y)return Q;return Q.map((Z)=>{if(Z.title)return Z;let H=Y[Z.url]||Y[Z.url.replace(hP2,"")]||Y[`${Z.url}/`];if(H)return{...Z,...H};return Z})}createAttachment(Q,$){let w=Q.url_private,B=this.requestContext.getStore(),X=B?.token,Y=B?.enterpriseId,Z=B?.isEnterpriseInstall,H="file";if(Q.mimetype?.startsWith("image/"))H="image";else if(Q.mimetype?.startsWith("video/"))H="video";else if(Q.mimetype?.startsWith("audio/"))H="audio";let K={};if(w)K.url=w;if($)K.teamId=$;if(Y)K.enterpriseId=Y;if(Z)K.isEnterpriseInstall="true";return{type:H,url:w,name:Q.name,mimeType:Q.mimetype,size:Q.size,width:Q.original_w,height:Q.original_h,fetchMetadata:Object.keys(K).length>0?K:void 0,fetchData:w?async()=>this.fetchSlackFile(w,X??await this.getToken()):void 0}}async fetchSlackFile(Q,$){let w=await fetch(Q,{headers:{Authorization:`Bearer ${$}`}});if(!w.ok)throw new Kw0("slack",`Failed to fetch file: ${w.status} ${w.statusText}`);if((w.headers.get("content-type")??"").includes("text/html"))throw new Kw0("slack",`Failed to download file from Slack: received HTML login page instead of file data. Ensure your Slack app has the "files:read" OAuth scope. URL: ${Q}`);let X=await w.arrayBuffer();return Buffer.from(X)}rehydrateAttachment(Q){let $=Q.fetchMetadata?.url??Q.url,w=Q.fetchMetadata?.teamId,B=Q.fetchMetadata?.enterpriseId,X=Q.fetchMetadata?.isEnterpriseInstall==="true";if(!$)return Q;return{...Q,fetchData:async()=>{let Y,Z=X?B:w;if(Z){let H=await this.resolveTokenForTeam(Z,X);if(!H)throw new md("slack",`Installation not found for ${X?"enterprise":"team"} ${Z}`);Y=H.token}else Y=await this.getToken();return this.fetchSlackFile($,Y)}}}async resolveOutgoingMentions(Q,$){if(!this.chat)return Q;let w=this.chat.getState(),B=new Map;if(Uw0(Q,(Z,H)=>{if(RP2.test(H))return Z;if(!B.has(H.toLowerCase()))B.set(H.toLowerCase(),[]);return Z}),B.size===0)return Q;for(let Z of B.keys()){let H=await w.getList(`slack:user-by-name:${Z}`),K=[...new Set(H)];B.set(Z,K)}let X=null;if([...B.values()].some((Z)=>Z.length>1)){let Z=await w.getList(`slack:thread-participants:${$}`);X=new Set(Z)}return Uw0(Q,(Z,H)=>{if(RP2.test(H))return Z;let K=B.get(H.toLowerCase());if(!K||K.length===0)return Z;if(K.length===1)return`<@${K[0]}>`;if(X){let U=K.filter((G)=>X.has(G));if(U.length===1)return`<@${U[0]}>`}return Z})}async resolveMessageMentions(Q,$){if(!this.chat)return Q;if(typeof Q==="string")return this.resolveOutgoingMentions(Q,$);if(typeof Q==="object"&&Q!==null){if("raw"in Q&&typeof Q.raw==="string")return{...Q,raw:await this.resolveOutgoingMentions(Q.raw,$)};if("markdown"in Q&&typeof Q.markdown==="string")return{...Q,markdown:await this.resolveOutgoingMentions(Q.markdown,$)}}return Q}async postMessage(Q,$){let w=await this.resolveMessageMentions($,Q),{channel:B,threadTs:X}=this.decodeThreadId(Q),Y=X||void 0;try{let Z,H=oWA(w);if(H.length>0){Z=await this.uploadFiles(H,B,Y);let D=typeof w==="string"||typeof w==="object"&&w!==null&&(("raw"in w)&&w.raw||("markdown"in w)&&w.markdown||("ast"in w)&&w.ast),q=DT(w);if(!(D||q))return{id:`file-${Date.now()}`,threadId:Q,raw:{files:H,uploadedFileIds:Z}}}let K=DT(w);if(K){let D=mw0(K),q=uw0(K);this.logger.debug("Slack API: chat.postMessage (blocks)",{channel:B,threadTs:Y,blockCount:D.length});let J;try{J=await this._client.chat.postMessage(await this.withToken({channel:B,thread_ts:Y,text:q,blocks:D,unfurl_links:!1,unfurl_media:!1}))}catch(F){throw rH$(F,D,this.logger)}return this.logger.debug("Slack API: chat.postMessage response",{messageId:J.ts,ok:J.ok}),{id:J.ts,threadId:Q,raw:Z===void 0?J:{...J,uploadedFileIds:Z}}}let U=this.formatConverter.toSlackPayload(w);this.logger.debug("Slack API: chat.postMessage",{channel:B,threadTs:Y,payloadKey:"markdown_text"in U?"markdown_text":"text"});let G=await this._client.chat.postMessage(await this.withToken({channel:B,thread_ts:Y,...U,unfurl_links:!1,unfurl_media:!1}));return this.logger.debug("Slack API: chat.postMessage response",{messageId:G.ts,ok:G.ok}),{id:G.ts,threadId:Q,raw:Z===void 0?G:{...G,uploadedFileIds:Z}}}catch(Z){this.handleSlackError(Z)}}async postEphemeral(Q,$,w){let B=await this.resolveMessageMentions(w,Q),{channel:X,threadTs:Y}=this.decodeThreadId(Q),Z=Y||void 0;try{let H=DT(B);if(H){let G=mw0(H),D=uw0(H);this.logger.debug("Slack API: chat.postEphemeral (blocks)",{channel:X,threadTs:Z,userId:$,blockCount:G.length});let q=await this._client.chat.postEphemeral(await this.withToken({channel:X,thread_ts:Z,user:$,text:D,blocks:G}));return this.logger.debug("Slack API: chat.postEphemeral response",{messageTs:q.message_ts,ok:q.ok}),{id:q.message_ts||"",threadId:Q,usedFallback:!1,raw:q}}let K=this.formatConverter.toSlackPayload(B);this.logger.debug("Slack API: chat.postEphemeral",{channel:X,threadTs:Z,userId:$,payloadKey:"markdown_text"in K?"markdown_text":"text"});let U=await this._client.chat.postEphemeral(await this.withToken({channel:X,thread_ts:Z,user:$,...K}));return this.logger.debug("Slack API: chat.postEphemeral response",{messageTs:U.message_ts,ok:U.ok}),{id:U.message_ts||"",threadId:Q,usedFallback:!1,raw:U}}catch(H){this.handleSlackError(H)}}async scheduleMessage(Q,$,w){let B=await this.resolveMessageMentions($,Q),{channel:X,threadTs:Y}=this.decodeThreadId(Q),Z=Y||void 0,H=Math.floor(w.postAt.getTime()/1000);if(H<=Math.floor(Date.now()/1000))throw new G7("slack","postAt must be in the future");if(oWA(B).length>0)throw new G7("slack","File uploads are not supported in scheduled messages");let U=this.requestContext.getStore()?.token,G=U?()=>Promise.resolve(U):()=>this.getToken(),D=U??await this.getToken();try{let q=DT(B);if(q){let j=mw0(q),b=uw0(q);this.logger.debug("Slack API: chat.scheduleMessage (blocks)",{channel:X,threadTs:Z,postAt:H,blockCount:j.length});let f=await this._client.chat.scheduleMessage({token:D,channel:X,thread_ts:Z,post_at:H,text:b,blocks:j,unfurl_links:!1,unfurl_media:!1}),v=f.scheduled_message_id,R=this;return{scheduledMessageId:v,channelId:X,postAt:w.postAt,raw:f,async cancel(){await R._client.chat.deleteScheduledMessage({token:await G(),channel:X,scheduled_message_id:v})}}}let J=this.formatConverter.toSlackPayload(B);this.logger.debug("Slack API: chat.scheduleMessage",{channel:X,threadTs:Z,postAt:H,payloadKey:"markdown_text"in J?"markdown_text":"text"});let F=await this._client.chat.scheduleMessage({token:D,channel:X,thread_ts:Z,post_at:H,...J,unfurl_links:!1,unfurl_media:!1}),L=F.scheduled_message_id,_=this;return{scheduledMessageId:L,channelId:X,postAt:w.postAt,raw:F,async cancel(){await _._client.chat.deleteScheduledMessage({token:await G(),channel:X,scheduled_message_id:L})}}}catch(q){this.handleSlackError(q)}}async openModal(Q,$,w){let B=TKA({contextId:w,privateMetadata:$.privateMetadata}),X=r_0($,B);this.logger.debug("Slack API: views.open",{triggerId:Q,callbackId:$.callbackId});try{let Y=await this._client.views.open(await this.withToken({trigger_id:Q,view:X}));return this.logger.debug("Slack API: views.open response",{viewId:Y.view?.id,ok:Y.ok}),{viewId:Y.view?.id}}catch(Y){this.handleSlackError(Y)}}async updateModal(Q,$){let w=r_0($);this.logger.debug("Slack API: views.update",{viewId:Q,callbackId:$.callbackId});try{let B=await this._client.views.update(await this.withToken({view_id:Q,view:w}));return this.logger.debug("Slack API: views.update response",{viewId:B.view?.id,ok:B.ok}),{viewId:B.view?.id}}catch(B){this.handleSlackError(B)}}async uploadFiles(Q,$,w){let X=(await Promise.all(Q.map(async(K)=>{try{let U=await CV2(K.data,{platform:"slack"});if(!U)return null;return{file:U,filename:K.filename}}catch(U){return this.logger.error("Failed to convert file to buffer",{filename:K.filename,error:U}),null}}))).filter((K)=>K!==null);if(X.length===0)return[];this.logger.debug("Slack API: files.uploadV2 (batch)",{fileCount:X.length,filenames:X.map((K)=>K.filename)});let Y={channel_id:$,file_uploads:X};if(w)Y.thread_ts=w;Y.token=await this.getToken();let Z=await this._client.files.uploadV2(Y);this.logger.debug("Slack API: files.uploadV2 response",{ok:Z.ok});let H=[];if(Z.files?.[0]?.files){for(let K of Z.files[0].files)if(K.id)H.push(K.id)}return H}async editMessage(Q,$,w){let B=await this.resolveMessageMentions(w,Q),X=this.decodeEphemeralMessageId($);if(X){let{threadTs:Z}=this.decodeThreadId(Q),H=await this.sendToResponseUrl(X.responseUrl,"replace",{message:B,threadTs:Z});return{id:X.messageTs,threadId:Q,raw:{ephemeral:!0,...H}}}let{channel:Y}=this.decodeThreadId(Q);try{let Z=DT(B);if(Z){let U=mw0(Z),G=uw0(Z);this.logger.debug("Slack API: chat.update (blocks)",{channel:Y,messageId:$,blockCount:U.length});let D=await this._client.chat.update(await this.withToken({channel:Y,ts:$,text:G,blocks:U}));return this.logger.debug("Slack API: chat.update response",{messageId:D.ts,ok:D.ok}),{id:D.ts,threadId:Q,raw:D}}let H=this.formatConverter.toSlackPayload(B);this.logger.debug("Slack API: chat.update",{channel:Y,messageId:$,payloadKey:"markdown_text"in H?"markdown_text":"text"});let K=await this._client.chat.update(await this.withToken({channel:Y,ts:$,...H}));return this.logger.debug("Slack API: chat.update response",{messageId:K.ts,ok:K.ok}),{id:K.ts,threadId:Q,raw:K}}catch(Z){this.handleSlackError(Z)}}async postObject(Q,$,w){if($!=="plan")return this.postMessage(Q,`[${$}]`);let B=w,{channel:X,threadTs:Y}=this.decodeThreadId(Q),Z=this.renderPlanFallbackText(B),H=this.planToBlockKit(B);try{this.logger.debug("Slack API: chat.postMessage (plan)",{channel:X,threadTs:Y,blockCount:H.length});let K=await this._client.chat.postMessage(await this.withToken({channel:X,thread_ts:Y,text:Z,blocks:H,unfurl_links:!1,unfurl_media:!1}));return{id:K.ts,threadId:Q,raw:K}}catch(K){this.handleSlackError(K)}}async editObject(Q,$,w,B){if(w!=="plan")return this.editMessage(Q,$,`[${w}]`);let X=B,{channel:Y}=this.decodeThreadId(Q),Z=this.renderPlanFallbackText(X),H=this.planToBlockKit(X);try{this.logger.debug("Slack API: chat.update (plan)",{channel:Y,messageId:$,blockCount:H.length});let K=await this._client.chat.update(await this.withToken({channel:Y,ts:$,text:Z,blocks:H}));return{id:K.ts,threadId:Q,raw:K}}catch(K){this.handleSlackError(K)}}renderPlanFallbackText(Q){let $=[];$.push(Q.title||"Plan");for(let w of Q.tasks)$.push(`- (${w.status}) ${w.title}`);return $.join(`
2469
2469
  `)}planToBlockKit(Q){let $=Q.tasks.map((w)=>{let B=this.planContentToRichText(w.details),X=this.planContentToRichText(w.output);return{type:"task_card",task_id:w.id,title:w.title,status:w.status,...B?{details:B}:null,...X?{output:X}:null}});return[{type:"plan",title:Q.title||"Plan",tasks:$}]}planContentToPlainText(Q){if(!Q)return"";if(Array.isArray(Q))return Q.join(`
2470
- `);if(typeof Q==="string")return Q;if("markdown"in Q)return Hw0(GT(Q.markdown));if("ast"in Q)return Hw0(Q.ast);return""}planContentToRichText(Q){if(!Q)return;if(Array.isArray(Q))return{type:"rich_text",elements:[{type:"rich_text_list",style:"bullet",elements:Q.map((w)=>({type:"rich_text_section",elements:[{type:"text",text:String(w)}]}))}]};let $=this.planContentToPlainText(Q);if(!$)return;return{type:"rich_text",elements:[{type:"rich_text_section",elements:[{type:"text",text:$}]}]}}async deleteMessage(Q,$){let w=this.decodeEphemeralMessageId($);if(w){await this.sendToResponseUrl(w.responseUrl,"delete");return}let{channel:B}=this.decodeThreadId(Q);try{this.logger.debug("Slack API: chat.delete",{channel:B,messageId:$}),await this._client.chat.delete(await this.withToken({channel:B,ts:$})),this.logger.debug("Slack API: chat.delete response",{ok:!0})}catch(X){this.handleSlackError(X)}}async addReaction(Q,$,w){let{channel:B}=this.decodeThreadId(Q),Y=gd.toSlack(w).replace(/:/g,"");try{this.logger.debug("Slack API: reactions.add",{channel:B,messageId:$,emoji:Y}),await this._client.reactions.add(await this.withToken({channel:B,timestamp:$,name:Y})),this.logger.debug("Slack API: reactions.add response",{ok:!0})}catch(Z){this.handleSlackError(Z)}}async removeReaction(Q,$,w){let{channel:B}=this.decodeThreadId(Q),Y=gd.toSlack(w).replace(/:/g,"");try{this.logger.debug("Slack API: reactions.remove",{channel:B,messageId:$,emoji:Y}),await this._client.reactions.remove(await this.withToken({channel:B,timestamp:$,name:Y})),this.logger.debug("Slack API: reactions.remove response",{ok:!0})}catch(Z){this.handleSlackError(Z)}}async startTyping(Q,$){let{channel:w,threadTs:B}=this.decodeThreadId(Q);if(!B){this.logger.debug("Slack: startTyping skipped - no thread context");return}this.logger.debug("Slack API: assistant.threads.setStatus",{channel:w,threadTs:B,status:$});try{let X=$?[$]:this.loadingMessages??["Typing..."];await this._client.assistant.threads.setStatus(await this.withToken({channel_id:w,thread_ts:B,status:$??this.loadingMessages?.[0]??"Typing...",loading_messages:X}))}catch(X){this.logger.warn("Slack API: assistant.threads.setStatus failed",{channel:w,threadTs:B,error:X})}}async stream(Q,$,w){let{channel:B,threadTs:X}=this.decodeThreadId(Q),Y=X||void 0;if(!Y)return this.logger.debug("Slack: using fallback stream - no thread context"),null;if(!(B.startsWith("D")||w?.recipientUserId&&w?.recipientTeamId))return this.logger.debug("Slack: using fallback stream - no recipient context"),null;if(!this.nativeStreaming||this.nativeStreamingBroken)return this.logger.debug("Slack: using fallback stream - native streaming disabled",{configured:this.nativeStreaming,broken:this.nativeStreamingBroken}),null;this.logger.debug("Slack: starting stream",{channel:B,threadTs:Y});let Z=await this.getToken(),H=this._client.chatStream({channel:B,thread_ts:Y,...w?.recipientUserId&&{recipient_user_id:w.recipientUserId},...w?.recipientTeamId&&{recipient_team_id:w.recipientTeamId},...w?.taskDisplayMode&&{task_display_mode:w.taskDisplayMode}}),K="",U=new bV2({wrapTablesForAppend:!1}),G={message:null,mode:"native",nativeRendered:!1},D=w?.updateIntervalMs??1000,q="",J=0,F=async(O)=>{let S=U.getCommittableText();if(S.length===0||S===q)return;let u=Date.now();if(!(O||u-J>=D))return;if(G.message)await this.editMessage(Q,G.message.id,S);else G.message=await this.postMessage(Q,S);q=S,J=u},L=(O)=>{G.mode="fallback";let S=AK$(O);if(S&&eH$.has(S))this.nativeStreamingBroken=!0;this.logger.warn("Slack native streaming unavailable, falling back to post-and-edit",{channel:B,error:O})},_=async(O=!1)=>{if(G.mode==="fallback"){await F(O);return}let S=U.getCommittableText(),u=S.slice(K.length);if(u.length===0)return;try{if(await H.append({markdown_text:u,token:Z}))G.nativeRendered=!0;K=S}catch(i){if(G.nativeRendered)throw i;L(i),await F(O)}},j=!0,b=async(O)=>{if(await _(),G.mode==="fallback"||!j){this.logger.debug("Slack: structured chunk skipped",{chunkType:O.type,mode:G.mode});return}try{await H.append({chunks:[O],token:Z}),G.nativeRendered=!0}catch(S){j=!1,this.logger.warn("Structured streaming chunk failed, falling back to text-only streaming. Ensure your Slack app manifest includes the agent/assistant feature and the assistant:write scope",{chunkType:O.type,error:S})}};for await(let O of $)if(typeof O==="string")U.push(O),await _();else if(O.type==="markdown_text")U.push(O.text),await _();else await b(O);if(U.finish(),await _(!0),G.mode==="fallback"){if(w?.stopBlocks||this.feedbackButtons)this.logger.warn("Slack: stream-end blocks (stopBlocks/feedbackButtons) skipped - post-and-edit fallback cannot attach stream blocks",{channel:B});return this.logger.debug("Slack: fallback stream complete",{messageId:G.message?.id}),G.message}let f=[...w?.stopBlocks??[],...this.feedbackButtons?[tH$(this.feedbackButtons)]:[]],v;try{v=await H.stop({token:Z,...f.length>0?{blocks:f}:{}})}catch(O){if(G.nativeRendered)throw O;return L(O),await F(!0),this.logger.debug("Slack: fallback stream complete",{messageId:G.message?.id}),G.message}let R=v.message?.ts??v.ts;return this.logger.debug("Slack: stream complete",{messageId:R}),{id:R,threadId:Q,raw:v}}async openDM(Q){try{this.logger.debug("Slack API: conversations.open",{userId:Q});let $=await this._client.conversations.open(await this.withToken({users:Q}));if(!$.channel?.id)throw new Kw0("slack","Failed to open DM - no channel returned");let w=$.channel.id;return this.logger.debug("Slack API: conversations.open response",{channelId:w,ok:$.ok}),this.encodeThreadId({channel:w,threadTs:""})}catch($){this.handleSlackError($)}}async fetchMessages(Q,$={}){let{channel:w,threadTs:B}=this.decodeThreadId(Q),X=$.direction??"backward",Y=$.limit||100;try{if(X==="forward")return await this.fetchMessagesForward(w,B,Q,Y,$.cursor);return await this.fetchMessagesBackward(w,B,Q,Y,$.cursor)}catch(Z){this.handleSlackError(Z)}}async fetchMessagesForward(Q,$,w,B,X){this.logger.debug("Slack API: conversations.replies (forward)",{channel:Q,threadTs:$,limit:B,cursor:X});let Y=await this._client.conversations.replies(await this.withToken({channel:Q,ts:$,limit:B,cursor:X})),Z=Y.messages||[],H=Y.response_metadata?.next_cursor;return this.logger.debug("Slack API: conversations.replies response",{messageCount:Z.length,ok:Y.ok,hasNextCursor:!!H}),{messages:await Promise.all(Z.map((U)=>this.parseSlackMessage(U,w))),nextCursor:H||void 0}}async fetchMessagesBackward(Q,$,w,B,X){let Y=X||void 0;this.logger.debug("Slack API: conversations.replies (backward)",{channel:Q,threadTs:$,limit:B,latest:Y});let Z=Math.min(1000,Math.max(B*2,200)),H=await this._client.conversations.replies(await this.withToken({channel:Q,ts:$,limit:Z,latest:Y,inclusive:!1})),K=H.messages||[];this.logger.debug("Slack API: conversations.replies response (backward)",{messageCount:K.length,ok:H.ok,hasMore:H.has_more});let U=Math.max(0,K.length-B),G=K.slice(U),D=await Promise.all(G.map((J)=>this.parseSlackMessage(J,w))),q;if(U>0||H.has_more){let J=G[0];if(J?.ts)q=J.ts}return{messages:D,nextCursor:q}}async fetchThread(Q){let{channel:$,threadTs:w}=this.decodeThreadId(Q);try{this.logger.debug("Slack API: conversations.info",{channel:$});let B=await this._client.conversations.info(await this.withToken({channel:$})),X=B.channel;if(X?.is_ext_shared)this._externalChannels.add($);this.logger.debug("Slack API: conversations.info response",{channelName:X?.name,ok:B.ok});let Y="unknown";if(X?.is_ext_shared)Y="external";else if(X?.is_private||$.startsWith("D"))Y="private";else if($.startsWith("C"))Y="workspace";return{id:Q,channelId:$,channelName:X?.name,channelVisibility:Y,metadata:{threadTs:w,channel:B.channel}}}catch(B){this.handleSlackError(B)}}async fetchMessage(Q,$){let{channel:w,threadTs:B}=this.decodeThreadId(Q);try{let Z=((await this._client.conversations.replies(await this.withToken({channel:w,ts:B,oldest:$,inclusive:!0,limit:1}))).messages||[]).find((H)=>H.ts===$);if(!Z)return null;return this.parseSlackMessage(Z,Q)}catch(X){this.handleSlackError(X)}}encodeThreadId(Q){return`slack:${Q.channel}:${Q.threadTs}`}isDM(Q){let{channel:$}=this.decodeThreadId(Q);return $.startsWith("D")}getChannelVisibility(Q){let{channel:$}=this.decodeThreadId(Q);if(this._externalChannels.has($))return"external";if($.startsWith("G")||$.startsWith("D"))return"private";if($.startsWith("C"))return"workspace";return"unknown"}decodeThreadId(Q){let $=Q.split(":");if($.length<2||$.length>3||$[0]!=="slack")throw new G7("slack",`Invalid Slack thread ID: ${Q}`);return{channel:$[1],threadTs:$.length===3?$[2]:""}}parseMessage(Q){let $=Q,w=$.thread_ts||$.ts||"",B=this.encodeThreadId({channel:$.channel||"",threadTs:w});return this.parseSlackMessageSync($,B)}parseSlackMessageSync(Q,$){let w=this.isMessageFromSelf(Q),B=Q.text||"",X=Q.username||Q.user||"unknown",Y=Q.username||Q.user||"unknown";return new iWA({id:Q.ts||"",threadId:$,text:this.formatConverter.extractPlainText(B),formatted:this.formatConverter.toAst(B),raw:Q,author:{userId:Q.user||Q.bot_id||"unknown",userName:X,fullName:Y,isBot:!!Q.bot_id,isMe:w},metadata:{dateSent:new Date(Number.parseFloat(Q.ts||"0")*1000),edited:!!Q.edited,editedAt:Q.edited?new Date(Number.parseFloat(Q.edited.ts)*1000):void 0},attachments:(Q.files||[]).map((Z)=>this.createAttachment(Z,Q.team_id??Q.team)),links:this.extractLinks(Q)})}channelIdFromThreadId(Q){let{channel:$}=this.decodeThreadId(Q);return`slack:${$}`}async fetchChannelMessages(Q,$={}){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=$.direction??"backward",X=$.limit||100;try{if(B==="forward")return await this.fetchChannelMessagesForward(w,X,$.cursor);return await this.fetchChannelMessagesBackward(w,X,$.cursor)}catch(Y){this.handleSlackError(Y)}}async fetchChannelMessagesForward(Q,$,w){this.logger.debug("Slack API: conversations.history (forward)",{channel:Q,limit:$,cursor:w});let B=await this._client.conversations.history(await this.withToken({channel:Q,limit:$,oldest:w,inclusive:w?!1:void 0})),X=(B.messages||[]).reverse(),Y=await Promise.all(X.map((H)=>{let K=H.thread_ts||H.ts||"",U=`slack:${Q}:${K}`;return this.parseSlackMessage(H,U,{skipSelfMention:!1})})),Z;if(B.has_more&&X.length>0){let H=X.at(-1);if(H?.ts)Z=H.ts}return{messages:Y,nextCursor:Z}}async fetchChannelMessagesBackward(Q,$,w){this.logger.debug("Slack API: conversations.history (backward)",{channel:Q,limit:$,cursor:w});let B=await this._client.conversations.history(await this.withToken({channel:Q,limit:$,latest:w,inclusive:w?!1:void 0})),Y=[...B.messages||[]].reverse(),Z=await Promise.all(Y.map((K)=>{let U=K.thread_ts||K.ts||"",G=`slack:${Q}:${U}`;return this.parseSlackMessage(K,G,{skipSelfMention:!1})})),H;if(B.has_more&&Y.length>0){let K=Y[0];if(K?.ts)H=K.ts}return{messages:Z,nextCursor:H}}async listThreads(Q,$={}){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=$.limit||50;try{this.logger.debug("Slack API: conversations.history (listThreads)",{channel:w,limit:B,cursor:$.cursor});let X=await this._client.conversations.history(await this.withToken({channel:w,limit:Math.min(B*3,200),cursor:$.cursor})),H=(X.messages||[]).filter((G)=>(G.reply_count??0)>0).slice(0,B),K=await Promise.all(H.map(async(G)=>{let D=G.ts||"",q=`slack:${w}:${D}`,J=await this.parseSlackMessage(G,q,{skipSelfMention:!1});return{id:q,rootMessage:J,replyCount:G.reply_count,lastReplyAt:G.latest_reply?new Date(Number.parseFloat(G.latest_reply)*1000):void 0}})),U=X.response_metadata?.next_cursor;return{threads:K,nextCursor:U||void 0}}catch(X){this.handleSlackError(X)}}async fetchChannelInfo(Q){let $=Q.split(":")[1];if(!$)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);try{this.logger.debug("Slack API: conversations.info (channel)",{channel:$});let B=(await this._client.conversations.info(await this.withToken({channel:$}))).channel;if(B?.is_ext_shared)this._externalChannels.add($);let X="unknown";if(B?.is_ext_shared)X="external";else if(B?.is_im||B?.is_mpim||B?.is_private||$.startsWith("D"))X="private";else if($.startsWith("C"))X="workspace";return{id:Q,name:B?.name?`#${B.name}`:void 0,isDM:Boolean(B?.is_im||B?.is_mpim),channelVisibility:X,memberCount:B?.num_members,metadata:{purpose:B?.purpose?.value,topic:B?.topic?.value}}}catch(w){this.handleSlackError(w)}}async postChannelMessage(Q,$){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=`slack:${w}:`;return await this.postMessage(B,$)}renderFormatted(Q){return this.formatConverter.fromAst(Q)}isMessageFromSelf(Q){let $=this.requestContext.getStore();if($?.botUserId&&Q.user===$.botUserId)return!0;if(this._botUserId&&Q.user===this._botUserId)return!0;if(this._botId&&Q.bot_id===this._botId)return!0;return!1}handleSlackError(Q){let $=Q;if($.code==="slack_webapi_platform_error"&&$.data?.error==="ratelimited")throw new vV2("slack");throw Q}encodeEphemeralMessageId(Q,$,w){let B=JSON.stringify({responseUrl:$,userId:w});return`ephemeral:${Q}:${btoa(B)}`}decodeEphemeralMessageId(Q){if(!Q.startsWith("ephemeral:"))return null;let $=Q.split(":");if($.length<3)return null;let w=$[1],B=$.slice(2).join(":");try{let X=atob(B);try{let Y=JSON.parse(X);if(Y.responseUrl&&Y.userId)return{messageTs:w,responseUrl:Y.responseUrl,userId:Y.userId}}catch{return{messageTs:w,responseUrl:X,userId:""}}return null}catch{return this.logger.warn("Failed to decode ephemeral messageId",{messageId:Q}),null}}async sendToResponseUrl(Q,$,w){let B;if($==="delete")B={delete_original:!0};else{let Z=w?.message;if(!Z)throw new G7("slack","Message required for replace action");let H=DT(Z);if(H)B={replace_original:!0,text:uw0(H),blocks:mw0(H)};else B={replace_original:!0,text:this.formatConverter.toResponseUrlText(Z)};if(w?.threadTs)B.thread_ts=w.threadTs}this.logger.debug("Slack response_url request",{action:$,threadTs:w?.threadTs});let X=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(B)});if(!X.ok){let Z=await X.text();throw this.logger.error("Slack response_url failed",{action:$,status:X.status,body:Z}),new Kw0("slack",`Failed to ${$} via response_url: ${Z}`)}let Y=await X.text();if(Y)try{return JSON.parse(Y)}catch{return{raw:Y}}return{}}};function SP2(A){let Q=A?.mode??"webhook",$=A?.appToken??process.env.SLACK_APP_TOKEN;if(Q==="socket"){if(!$)throw new G7("slack","appToken is required for socket mode. Set SLACK_APP_TOKEN or provide it in config.");if(A?.clientId||A?.clientSecret)throw new G7("slack","Multi-workspace (clientId/clientSecret) is not supported in socket mode.")}let w=A?.webhookVerifier,B=w?void 0:A?.signingSecret??process.env.SLACK_SIGNING_SECRET;if(Q==="webhook"&&!(B||w))throw new G7("slack","signingSecret or webhookVerifier is required. Set SLACK_SIGNING_SECRET, provide signingSecret in config, or provide a webhookVerifier.");let X=!(A?.botToken||A?.clientId||A?.clientSecret||A?.installationProvider||A?.signingSecret||A?.webhookVerifier),Y={agentView:A?.agentView,apiUrl:A?.apiUrl,appToken:$,mode:Q,signingSecret:B,botToken:A?.botToken??(X?process.env.SLACK_BOT_TOKEN:void 0),clientId:A?.clientId??(X?process.env.SLACK_CLIENT_ID:void 0),clientSecret:A?.clientSecret??(X?process.env.SLACK_CLIENT_SECRET:void 0),encryptionKey:A?.encryptionKey??process.env.SLACK_ENCRYPTION_KEY,installationKeyPrefix:A?.installationKeyPrefix,feedbackButtons:A?.feedbackButtons,installationProvider:A?.installationProvider,loadingMessages:A?.loadingMessages,logger:A?.logger??new dWA("info").child("slack"),nativeStreaming:A?.nativeStreaming,suggestedPrompts:A?.suggestedPrompts,socketForwardingSecret:A?.socketForwardingSecret??process.env.SLACK_SOCKET_FORWARDING_SECRET,userName:A?.userName,botUserId:A?.botUserId,webClientOptions:A?.webClientOptions,webhookVerifier:w};return new $K$(Y)}var wK$=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let $=this.locks.get(A);if($&&$.expiresAt>Date.now())return null;let w={threadId:A,token:BK$(),expiresAt:Date.now()+Q};return this.locks.set(A,w),w}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let $=this.locks.get(A.threadId);if(!$||$.token!==A.token)return!1;if($.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return $.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,$){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:$?Date.now()+$:null})}async setIfNotExists(A,Q,$){this.ensureConnected();let w=this.cache.get(A);if(w)if(w.expiresAt!==null&&w.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:$?Date.now()+$:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,$){this.ensureConnected();let w=this.cache.get(A),B;if(w&&w.expiresAt!==null&&w.expiresAt<=Date.now())B=[];else if(w&&Array.isArray(w.value))B=w.value;else B=[];if(B.push(Q),$?.maxLength&&B.length>$.maxLength)B=B.slice(B.length-$.maxLength);this.cache.set(A,{value:B,expiresAt:$?.ttlMs?Date.now()+$.ttlMs:null})}async enqueue(A,Q,$){this.ensureConnected();let w=this.queues.get(A);if(!w)w=[],this.queues.set(A,w);if(w.push(Q),w.length>$)w.splice(0,w.length-$);return w.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let $=Q.shift();if(Q.length===0)this.queues.delete(A);return $??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,$]of this.locks)if($.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function BK$(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function s_0(A){return new wK$}h0();var XK$=W.object({subscribedAt:W.string().datetime(),routingMode:W.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:W.boolean().optional()});var YK$="chat.discord.subscriptions",ZK$="chat.slack.subscriptions";function WK$(A){return A==="discord"?YK$:ZK$}function uKA(A,Q){return A.scoped({namespace:WK$(Q),schema:XK$})}function mP2(A){return uKA(A,"discord")}function uP2(A){return uKA(A,"slack")}function cP2(A,Q,$=s_0()){let w=new Map;for(let B of Q)w.set(B,uKA(A,B));return new pP2($,w)}class pP2{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){let Q=this.getSubscriptionStore(A);if(!Q)return this.memoryState.subscribe(A);await Q.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){let Q=this.getSubscriptionStore(A);if(!Q)return this.memoryState.unsubscribe(A);await Q.delete(A)}isSubscribed(A){let Q=this.getSubscriptionStore(A);return Q?Q.has(A):this.memoryState.isSubscribed(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,$){return this.memoryState.appendToList(A,Q,$)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,$){return this.memoryState.enqueue(A,Q,$)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,$){return this.memoryState.set(A,Q,$)}setIfNotExists(A,Q,$){return this.memoryState.setIfNotExists(A,Q,$)}getSubscriptionStore(A){let Q=A.split(":")[0];if(Q!=="discord"&&Q!=="slack")return;return this.subscriptions.get(Q)}}function lP2(A,Q){if(!A)throw Error(Q);return A}function iP2(A){let{discord:Q,slack:$}=A,w=Q?YV2({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds}):void 0;if(w)A.gatewayLoop.setAdapter(w);let X=$?SP2($.mode==="socket"?{botToken:$.botToken,mode:"socket",appToken:lP2($.appToken,"Slack app token is required in socket mode")}:{botToken:$.botToken,signingSecret:lP2($.signingSecret,"Slack signing secret is required in webhook mode")}):void 0;if(X&&$?.mode==="socket")A.slackSocketLoop.setAdapter(X);let Y={...w?{discord:w}:{},...X?{slack:X}:{}},Z=[...Q?["discord"]:[],...$?["slack"]:[]],H=Z.length>0?cP2(A.runtimeState,Z):s_0();return new lY2({userName:A.userName,adapters:Y,...Q||$?{concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"}}:{},state:H})}class cKA{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;await this.subscribeThread(A)}async subscribeThread(A){try{await A.subscribe(),await this.getSubscriptions(A)?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(Q){this.deps.logger.debug("Chat thread subscription failed",{error:Q,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){let $=this.getSubscriptions(A);if(!$)return!1;if(A.isDM)return!0;let w=await $.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let X={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,X);else await $.set(A.id,X);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.getSubscriptions(A)?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((w)=>!w.isBot&&!w.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect chat thread participants",{error:Q,threadId:A.id}),!1}}getSubscriptions(A){return this.deps.getSubscriptions(this.deps.getPlatform(A))}}zA();class pKA{deps;constructor(A){this.deps=A}async build(A,Q,$,w){let B={message:HK$(A,$),attachments:[],notices:[]};if($.attachments.length===0)return B;if(!(w==="anchor"||w==="trusted"))return B;let Y=this.deps.getUploadStore(A);if(!Y)return B;for(let Z of $.attachments){let H=Z.name;if(!H)continue;let K=x_(H,"upload"),U=Kk(K,Z.mimeType),G=Z.size??0,D=Zq0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!Wq0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let J=R_({filename:K,mediaType:U,content:q,fallbackFilename:"upload"});if(!J.ok){B.notices.push(J.message);continue}let F=await Y.save({filename:J.filename,mediaType:J.mediaType,content:q,metadata:this.buildMetadata(A,Q,$)});B.attachments.push(dP2(F.filename,F.mediaType,q,F.ref,J.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:K}),B.notices.push(`Could not read file upload: ${K}`)}}return B}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let $=await Q.arrayBuffer();return Buffer.from(new Uint8Array($))}buildMetadata(A,Q,$){let w=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:$.id,uploaderId:$.author.userId,uploaderUsername:$.author.userName,...w.guildId?{guildId:w.guildId}:{},...w.threadId?{threadId:w.threadId}:{}}}}function lKA(A,Q,$,w){return dP2(A,Q,$,w,Uk(A,Q))}function HK$(A,Q){let $=Q.text.trim();if(A!=="slack"||!Q.isMention)return $;return $.replace(/(^|\s)@[UW][A-Z0-9]+\b\s*/g,"$1").trim()}function dP2(A,Q,$,w,B){if(B)return{kind:"text",filename:A,mediaType:Q,content:$.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:$.byteLength,source:w};return{kind:"file",filename:A,mediaType:Q,data:$,sizeBytes:$.byteLength,source:w}}var iKA="discord-chat-upload",dKA="slack-chat-upload",a_0="upload";function nP2(){return{namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}}function nKA(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function rKA(){return{namespace:"slack-chat",refKind:"slack-chat-upload",routePath:"/api/webhooks/chat/slack/uploads"}}function Jf(A){let Q=A.split(":");if(Q[0]!=="discord")return{};return{...Q[1]?{guildId:Q[1]}:{},...Q[2]?{channelId:Q[2]}:{},...Q[3]?{threadId:Q[3]}:{}}}function KK$(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let $=Q.channel_id;return typeof $==="string"?$:void 0}function rP2(A,Q){if(A.isDM)return!1;let $=Jf(A.id);if(!$.threadId)return!1;let w=KK$(Q);return w!==void 0&&w!==$.threadId}function t_0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let $=Jf(A.id),w=A.id.split(":")[0]==="slack"?A.id.split(":")[1]:void 0;return[A.id,A.channelId,$.channelId,$.threadId,w].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function e_0(A,Q,$){if(A.isDM&&!$.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return t_0(A,$)}function oKA(A,Q){if(!Q)return!1;if(A.isDM&&!Q.allowDMs)return!1;return t_0(A,Q)}function cw0(A,Q){let $=Jf(A.id),w=A.id.split(":")[0]==="slack"?A.id.split(":")[1]:void 0;return{channelId:$.channelId??w??A.channelId,isBot:Boolean(Q.author.isBot)}}function $n(A){return A.isDM?"DM":A.channelId}var UK$="https://discord.com/api/v10";async function oP2(A){let Q=Jf(A.threadId),$=Q.threadId??Q.channelId;if(!$)return;let w=A.fetchFn??fetch;try{let B=await w(`${UK$}/channels/${$}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!B.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:$,status:B.status})}catch(B){A.logger.debug("Failed to clear Discord message components",{error:B,messageId:A.messageId,channelId:$})}}var sP2={name:"@brains/chat",version:"0.2.0-alpha.195",description:"Multi-platform Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.33.0","@chat-adapter/slack":"^4.33.0","@chat-adapter/state-memory":"^4.33.0",chat:"^4.33.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","slack:preflight":"bun scripts/slack-preflight.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var DK$=/https?:\/\/\S+/i,qK$=/[\s\S]+/,zK$=/^(?:(?:confirmation|approval) required|please confirm(?: this action)?)\.?$/i,VK$=1000,JK$=W.looseObject({type:W.literal("card"),children:W.array(W.looseObject({type:W.string()})),imageUrl:W.string().optional(),subtitle:W.string().optional(),title:W.string().optional()}),FK$=W.object({card:W.custom((A)=>JK$.safeParse(A).success),fallbackText:W.string().optional()});class AP0 extends f3{threadRegistry=new iN0;pendingApprovals;uploadContinuity;promptActions=new JYA(VK$);pendingJobArtifacts=new Map;toolStatusMessenger=new FYA(this.threadRegistry);compactingSlackApprovalToolStatuses=new Set;activeSlackConfirmationConversations=new Set;cardBuilder=new NYA({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new _YA({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new PYA({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let $=this.config.adapters.discord?.botToken;if(!$)return;await oP2({threadId:A,messageId:Q,botToken:$,logger:this.logger})}});subscriptionRouter=new cKA({getSubscriptions:(A)=>A==="discord"?this.discordSubscriptions:A==="slack"?this.slackSubscriptions:void 0,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rP2,logger:this.logger});chatInputBuilder=new pKA({getUploadStore:(A)=>A==="discord"||A==="slack"?this.getCanonicalUploadStore():void 0,getThreadIdParts:Jf,logger:this.logger});gatewayLoop;slackSocketLoop;chatApp;discordSubscriptions;slackSubscriptions;chatAppRunning=!1;constructor(A={}){super("chat",sP2,A,VYA);this.gatewayLoop=new bYA({getApp:()=>this.chatApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.slackSocketLoop=new jYA({listenerRunMs:this.config.gatewayRunMs,restartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.chatApp=new MYA({discord:this.config.adapters.discord,slack:this.config.adapters.slack,getUploadStore:(Q)=>this.getUploadStore(Q),buildApp:(Q)=>iP2({userName:this.config.userName,discord:this.config.adapters.discord,slack:this.config.adapters.slack,gatewayLoop:this.gatewayLoop,slackSocketLoop:this.slackSocketLoop,runtimeState:Q})}),this.pendingApprovals=new pA0({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,$)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:$})}}),this.uploadContinuity={discord:this.createUploadContinuity("discord"),slack:this.createUploadContinuity("slack")}}async onRegister(A){if(await super.onRegister(A),this.config.adapters.discord)this.discordSubscriptions=mP2(A.runtimeState);if(this.config.adapters.slack)this.slackSubscriptions=uP2(A.runtimeState);this.registerChatHandlers(this.chatApp.build(A.runtimeState))}getWebRoutes(){return this.chatApp.getWebRoutes()}createDaemon(){let A=Boolean(this.config.adapters.discord),Q=this.config.adapters.slack?.mode==="socket";if(!A&&!this.config.adapters.slack)return;return{start:async()=>{if(await this.chatApp.initialize(),this.chatAppRunning=!0,A)this.gatewayLoop.start();if(Q)this.slackSocketLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),await this.slackSocketLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.discord.clear(),this.uploadContinuity.slack.clear(),this.pendingJobArtifacts.clear(),this.toolStatusMessenger.clear(),await this.chatApp.shutdown(),this.chatAppRunning=!1},healthCheck:async()=>{let $=this.chatAppRunning&&(!A||this.gatewayLoop.isRunning())&&(!Q||this.slackSocketLoop.isRunning());return{status:$?"healthy":"error",message:$?"Chat SDK app running":"Chat SDK app stopped",lastCheck:new Date}}}}sendMessageToChannel({channelId:A,message:Q}){let $=this.threadRegistry.get(A);if(!$)return;let w=this.toPlatformPostOutput(A,Q);if(w!==void 0){$.post(w).catch((B)=>this.logger.error("Failed to send chat message",{error:B,channelId:A}));return}if(typeof Q!=="string")return;for(let B of a80(A,Q))$.post(B).catch((X)=>this.logger.error("Failed to send chat message",{error:X,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let $=this.threadRegistry.get(A);if(!$)return;let w=this.toPlatformPostOutput(A,Q);if(w!==void 0){let X=await $.post(w);return this.threadRegistry.trackMessage($.id,X),X.id}if(typeof Q!=="string")return;let B;for(let X of a80(A,Q))B=await $.post(X),this.threadRegistry.trackMessage($.id,B);return B?.id}async editMessage({channelId:A,messageId:Q,newMessage:$}){let w=this.threadRegistry.getMessage(A,Q);if(!w)return!1;try{let B=await w.edit(this.toPlatformPostOutput(A,$)??(typeof $==="string"?$:""));if(A)this.threadRegistry.trackMessage(A,B);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=FK$.safeParse(A);if(!Q.success)return;let{card:$,fallbackText:w}=Q.data;if(w===void 0)return{card:$};return{card:$,fallbackText:w}}toPlatformPostOutput(A,Q){if(typeof Q==="string")return;let $=this.toDiscordCardOutput(Q);if(!$)return;if(rN0(A)==="slack"&&$.fallbackText)return $.fallbackText;return $}formatProgressOutput(A){return IYA(A)}formatCompletionOutput(A){return IYA(A)}async handleProgressEvent(A,Q){let $=A.metadata.interfaceType,w=A,B=Q;if($&&$!==this.id){if(!this.isEnabledPlatform($))return;w={...A,metadata:{...A.metadata,interfaceType:this.id}},B=w.metadata}await super.handleProgressEvent(w,B),await this.deliverCompletedJobArtifacts(w)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;let Q=rN0(A.channelId)==="slack",$=Q&&this.activeSlackConfirmationConversations.has(A.conversationId);if(Q&&this.compactingSlackApprovalToolStatuses.has(Yk(A))||$||Q&&A.state==="completed"){await this.toolStatusMessenger.dismiss(A);return}await this.toolStatusMessenger.handle(A)}async handleAgentResponseToolStatuses(A,Q){let $=new Set([...(A.pendingConfirmations??[]).map((B)=>B.toolName),...(A.cards??[]).filter((B)=>B.kind==="tool-approval").map((B)=>B.toolName)]),w=Q.startsWith("slack-")?[...$].map((B)=>`${Q}:${B}`):[];for(let B of w)this.compactingSlackApprovalToolStatuses.add(B);try{await super.handleAgentResponseToolStatuses(A,Q)}finally{for(let B of w)this.compactingSlackApprovalToolStatuses.delete(B)}}isEnabledPlatform(A){let Q=new Set;if(this.config.adapters.discord)Q.add("discord");if(this.config.adapters.slack)Q.add("slack");return SX2(A,Q)}registerChatHandlers(A){if(A.onDirectMessage(async(Q,$,w,B)=>{await this.handleRoutedMessage(Q,$,B)}),A.onNewMention(async(Q,$,w)=>{let B=this.getPlatformConfig(Q),X=this.getPlatform(Q);if(X==="discord"&&this.config.adapters.discord&&B&&e_0(Q,$,B)&&!Q.isDM&&this.config.adapters.discord.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,$);else if(X==="slack"&&B&&e_0(Q,$,B)&&!Q.isDM)await this.subscriptionRouter.subscribeThread(Q);await this.handleRoutedMessage(Q,$,w)}),A.onSubscribedMessage(async(Q,$,w)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,$))return;await this.handleRoutedMessage(Q,$,w)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention||this.config.adapters.slack&&!this.config.adapters.slack.requireMention)A.onNewMessage(qK$,async(Q,$,w)=>{let B=this.getPlatformConfig(Q);if(!B||B.requireMention)return;await this.handleRoutedMessage(Q,$,w)});A.onNewMessage(DK$,async(Q,$)=>{await this.handlePassiveUrlCapture(Q,$)}),A.onAction([dN0,LYA],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(s80,async(Q)=>{await this.handlePromptAction(Q)}),A.onAction(async(Q)=>{if(!Q.actionId.startsWith(`${s80}:`))return;await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;if(Q!=="discord"&&Q!=="slack")return;let $=A.thread;if(!oKA($,this.getPlatformConfig($)))return;let w=this.promptActions.get(A.value);if(w?.threadId!==$.id){await $.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let B=this.context.permissions.getUserLevel(Q,A.user.userId,cw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}})),X=this.getConversationId(Q,$.id),Y=$.id;await this.runAgentTurn({thread:$,channelId:Y,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let Z=await this.uploadContinuity[Q].selectPriorUploads({conversationId:X,currentAttachments:[],canRestore:B==="anchor"||B==="trusted"}),H=await this.context.agent.chat(w.prompt,X,{userPermissionLevel:B,interfaceType:Q,channelId:Y,channelName:$n($),...this.buildActionEventMetadata(Q,$,A),...Z.length>0?{attachments:Z}:{}});await this.renderAgentResponse({thread:$,channelId:Y,conversationId:X,response:H,userPermissionLevel:B})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;if(Q!=="discord"&&Q!=="slack")return;let $=A.thread;if(!oKA($,this.getPlatformConfig($)))return;let w=this.getConversationId(Q,$.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await $.post(this.formatNoticePayload("That approval is no longer pending."));return}let X=this.context.permissions.getUserLevel(Q,A.user.userId,cw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}}));await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===dN0,userPermissionLevel:X,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,$){if(!this.context)return;let w=this.getPlatform(A);if(!this.isEnabledPlatform(w))return;if(w!=="discord"&&w!=="slack")return;let B=this.getPlatformConfig(A);if(!B)return;if(!e_0(A,Q,B))return;await this.routeToAgent(w,A,Q,$)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,$){let w=this.formatErrorPayload($),B=this.toPlatformPostOutput(Q,w);if(B!==void 0){await A.post(B);return}let X=typeof w==="string"?w:"Message failed.";for(let Y of a80(Q,X))await A.post(Y)}async routeToAgent(A,Q,$,w){if(!this.context)return;this.threadRegistry.set(Q);let B=this.getConversationId(A,Q.id),X=Q.id,Y=cw0(Q,$),Z=this.context.permissions.getUserLevel(A,$.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,$,Z),K=[...H.attachments];if(await this.attachPriorUploads(A,B,H,Z),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments(A,B,K),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let U=await this.getPendingApprovalIds(B);if(U.size>0){if(await this.handleConfirmationResponse(H.message,B,Q,U,Z,this.buildUserMessageMetadata(A,Q,$)))return}let G=this.buildCoalescedAgentInput(H.message,w),D=await this.context.agent.chat(G.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:$n(Q),...this.buildUserMessageMetadata(A,Q,$,G.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:D,userPermissionLevel:Z})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),$=EC(A.response,{deniedCardIds:Q.deniedCardIds});this.rememberPendingJobArtifacts($,A.channelId,A.userPermissionLevel,Q.deliveredCardIds,Q.deniedCardIds);let w=!1;if(A.confirmation){let b=Fc(A.response,A.confirmation.confirmed?"approved":"declined");w=await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,{title:lA0(b.variant),detail:b.label})}let X=$.directives.find((b)=>b.kind==="approvals")?.confirmations,Y=this.getPlatform(A.thread)==="slack",Z=$.directives.some((b)=>b.kind==="artifact"),H=$.directives.some((b)=>b.kind==="artifact"&&Boolean(b.card.jobId)),K=$.directives.some((b)=>b.kind==="denied-artifact"),U=Y&&!A.confirmation&&Boolean(X?.length)&&zK$.test(A.response.text.trim()),G=Y&&Boolean(A.confirmation)&&H&&Q.files.length===0,D=Y&&w&&!X?.length&&!Z&&!K&&Q.files.length===0,q=G||D,J=U||q,F=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText($,Q.deniedCardIds),L=J?void 0:await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:F,files:Q.files}),_=await this.sendArtifactCards(A.thread,$,Y?Q.deliveredCardIds:void 0);if(await this.sendSupplementalCards(A.thread,$,q),Y&&X&&X.length>1){let b=hC(X);if(b)await A.thread.post(b)}else await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,X);let j=_??L;if(j)for(let b of $.jobIds)this.trackAgentResponseForJob(b,j,A.channelId)}rememberPendingJobArtifacts(A,Q,$,w,B){for(let X of A.directives){if(X.kind!=="artifact"||!X.card.jobId)continue;if(w.has(X.card.id)||B.has(X.card.id))continue;let Y=this.pendingJobArtifacts.get(X.card.jobId)??[];this.pendingJobArtifacts.set(X.card.jobId,[...Y.filter((Z)=>Z.card.id!==X.card.id),{card:X.card,channelId:Q,userPermissionLevel:$}])}}async deliverCompletedJobArtifacts(A){if(A.status==="failed"){this.pendingJobArtifacts.delete(A.id);return}if(A.status!=="completed")return;let Q=this.pendingJobArtifacts.get(A.id);if(!Q)return;this.pendingJobArtifacts.delete(A.id);for(let $ of Q){let w=this.threadRegistry.get($.channelId);if(!w)continue;try{let B=await this.artifactDelivery.resolve([$.card],$.userPermissionLevel);if(B.files.length===0)continue;let X=await w.post(this.getPlatform(w)==="slack"?{raw:"",files:B.files}:{markdown:`Generated artifact ready: ${B.files.map((Y)=>Y.filename).join(", ")}`,files:B.files});this.threadRegistry.trackMessage($.channelId,X)}catch(B){this.logger.error("Failed to deliver completed chat artifact",{error:B,jobId:A.id,cardId:$.card.id})}}}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,$,w,B,X){if(!SA0(A,w))return!1;let Y=sD0({message:A,approvalIds:w});if(Y.kind==="not-confirmation"){this.pendingApprovals.deleteConversation(Q);let Z=this.formatNoticePayload("No pending approval to resolve.");return await $.post(this.toPlatformPostOutput($.id,Z)??Z.fallbackText??"No pending approval to resolve."),!0}if(Y.kind==="notice"){let Z=this.formatNoticePayload(Y.message);return await $.post(this.toPlatformPostOutput($.id,Z)??Z.fallbackText??Y.message),!0}return await this.confirmApproval({thread:$,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:B,...X?{metadata:X}:{}}),!0}async confirmApproval(A){let Q=this.getPlatform(A.thread),$=Q==="slack";if($)this.activeSlackConfirmationConversations.add(A.conversationId);try{let w=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:Q,channelId:A.thread.id,channelName:$n(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!w)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:w,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}finally{if($)this.activeSlackConfirmationConversations.delete(A.conversationId)}}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap(($)=>{if($.kind==="text")return[$.text];if($.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard($.card,Q)];return[]}).filter(($)=>$.trim().length>0).join(`
2470
+ `);if(typeof Q==="string")return Q;if("markdown"in Q)return Hw0(GT(Q.markdown));if("ast"in Q)return Hw0(Q.ast);return""}planContentToRichText(Q){if(!Q)return;if(Array.isArray(Q))return{type:"rich_text",elements:[{type:"rich_text_list",style:"bullet",elements:Q.map((w)=>({type:"rich_text_section",elements:[{type:"text",text:String(w)}]}))}]};let $=this.planContentToPlainText(Q);if(!$)return;return{type:"rich_text",elements:[{type:"rich_text_section",elements:[{type:"text",text:$}]}]}}async deleteMessage(Q,$){let w=this.decodeEphemeralMessageId($);if(w){await this.sendToResponseUrl(w.responseUrl,"delete");return}let{channel:B}=this.decodeThreadId(Q);try{this.logger.debug("Slack API: chat.delete",{channel:B,messageId:$}),await this._client.chat.delete(await this.withToken({channel:B,ts:$})),this.logger.debug("Slack API: chat.delete response",{ok:!0})}catch(X){this.handleSlackError(X)}}async addReaction(Q,$,w){let{channel:B}=this.decodeThreadId(Q),Y=gd.toSlack(w).replace(/:/g,"");try{this.logger.debug("Slack API: reactions.add",{channel:B,messageId:$,emoji:Y}),await this._client.reactions.add(await this.withToken({channel:B,timestamp:$,name:Y})),this.logger.debug("Slack API: reactions.add response",{ok:!0})}catch(Z){this.handleSlackError(Z)}}async removeReaction(Q,$,w){let{channel:B}=this.decodeThreadId(Q),Y=gd.toSlack(w).replace(/:/g,"");try{this.logger.debug("Slack API: reactions.remove",{channel:B,messageId:$,emoji:Y}),await this._client.reactions.remove(await this.withToken({channel:B,timestamp:$,name:Y})),this.logger.debug("Slack API: reactions.remove response",{ok:!0})}catch(Z){this.handleSlackError(Z)}}async startTyping(Q,$){let{channel:w,threadTs:B}=this.decodeThreadId(Q);if(!B){this.logger.debug("Slack: startTyping skipped - no thread context");return}this.logger.debug("Slack API: assistant.threads.setStatus",{channel:w,threadTs:B,status:$});try{let X=$?[$]:this.loadingMessages??["Typing..."];await this._client.assistant.threads.setStatus(await this.withToken({channel_id:w,thread_ts:B,status:$??this.loadingMessages?.[0]??"Typing...",loading_messages:X}))}catch(X){this.logger.warn("Slack API: assistant.threads.setStatus failed",{channel:w,threadTs:B,error:X})}}async stream(Q,$,w){let{channel:B,threadTs:X}=this.decodeThreadId(Q),Y=X||void 0;if(!Y)return this.logger.debug("Slack: using fallback stream - no thread context"),null;if(!(B.startsWith("D")||w?.recipientUserId&&w?.recipientTeamId))return this.logger.debug("Slack: using fallback stream - no recipient context"),null;if(!this.nativeStreaming||this.nativeStreamingBroken)return this.logger.debug("Slack: using fallback stream - native streaming disabled",{configured:this.nativeStreaming,broken:this.nativeStreamingBroken}),null;this.logger.debug("Slack: starting stream",{channel:B,threadTs:Y});let Z=await this.getToken(),H=this._client.chatStream({channel:B,thread_ts:Y,...w?.recipientUserId&&{recipient_user_id:w.recipientUserId},...w?.recipientTeamId&&{recipient_team_id:w.recipientTeamId},...w?.taskDisplayMode&&{task_display_mode:w.taskDisplayMode}}),K="",U=new bV2({wrapTablesForAppend:!1}),G={message:null,mode:"native",nativeRendered:!1},D=w?.updateIntervalMs??1000,q="",J=0,F=async(O)=>{let S=U.getCommittableText();if(S.length===0||S===q)return;let u=Date.now();if(!(O||u-J>=D))return;if(G.message)await this.editMessage(Q,G.message.id,S);else G.message=await this.postMessage(Q,S);q=S,J=u},L=(O)=>{G.mode="fallback";let S=AK$(O);if(S&&eH$.has(S))this.nativeStreamingBroken=!0;this.logger.warn("Slack native streaming unavailable, falling back to post-and-edit",{channel:B,error:O})},_=async(O=!1)=>{if(G.mode==="fallback"){await F(O);return}let S=U.getCommittableText(),u=S.slice(K.length);if(u.length===0)return;try{if(await H.append({markdown_text:u,token:Z}))G.nativeRendered=!0;K=S}catch(i){if(G.nativeRendered)throw i;L(i),await F(O)}},j=!0,b=async(O)=>{if(await _(),G.mode==="fallback"||!j){this.logger.debug("Slack: structured chunk skipped",{chunkType:O.type,mode:G.mode});return}try{await H.append({chunks:[O],token:Z}),G.nativeRendered=!0}catch(S){j=!1,this.logger.warn("Structured streaming chunk failed, falling back to text-only streaming. Ensure your Slack app manifest includes the agent/assistant feature and the assistant:write scope",{chunkType:O.type,error:S})}};for await(let O of $)if(typeof O==="string")U.push(O),await _();else if(O.type==="markdown_text")U.push(O.text),await _();else await b(O);if(U.finish(),await _(!0),G.mode==="fallback"){if(w?.stopBlocks||this.feedbackButtons)this.logger.warn("Slack: stream-end blocks (stopBlocks/feedbackButtons) skipped - post-and-edit fallback cannot attach stream blocks",{channel:B});return this.logger.debug("Slack: fallback stream complete",{messageId:G.message?.id}),G.message}let f=[...w?.stopBlocks??[],...this.feedbackButtons?[tH$(this.feedbackButtons)]:[]],v;try{v=await H.stop({token:Z,...f.length>0?{blocks:f}:{}})}catch(O){if(G.nativeRendered)throw O;return L(O),await F(!0),this.logger.debug("Slack: fallback stream complete",{messageId:G.message?.id}),G.message}let R=v.message?.ts??v.ts;return this.logger.debug("Slack: stream complete",{messageId:R}),{id:R,threadId:Q,raw:v}}async openDM(Q){try{this.logger.debug("Slack API: conversations.open",{userId:Q});let $=await this._client.conversations.open(await this.withToken({users:Q}));if(!$.channel?.id)throw new Kw0("slack","Failed to open DM - no channel returned");let w=$.channel.id;return this.logger.debug("Slack API: conversations.open response",{channelId:w,ok:$.ok}),this.encodeThreadId({channel:w,threadTs:""})}catch($){this.handleSlackError($)}}async fetchMessages(Q,$={}){let{channel:w,threadTs:B}=this.decodeThreadId(Q),X=$.direction??"backward",Y=$.limit||100;try{if(X==="forward")return await this.fetchMessagesForward(w,B,Q,Y,$.cursor);return await this.fetchMessagesBackward(w,B,Q,Y,$.cursor)}catch(Z){this.handleSlackError(Z)}}async fetchMessagesForward(Q,$,w,B,X){this.logger.debug("Slack API: conversations.replies (forward)",{channel:Q,threadTs:$,limit:B,cursor:X});let Y=await this._client.conversations.replies(await this.withToken({channel:Q,ts:$,limit:B,cursor:X})),Z=Y.messages||[],H=Y.response_metadata?.next_cursor;return this.logger.debug("Slack API: conversations.replies response",{messageCount:Z.length,ok:Y.ok,hasNextCursor:!!H}),{messages:await Promise.all(Z.map((U)=>this.parseSlackMessage(U,w))),nextCursor:H||void 0}}async fetchMessagesBackward(Q,$,w,B,X){let Y=X||void 0;this.logger.debug("Slack API: conversations.replies (backward)",{channel:Q,threadTs:$,limit:B,latest:Y});let Z=Math.min(1000,Math.max(B*2,200)),H=await this._client.conversations.replies(await this.withToken({channel:Q,ts:$,limit:Z,latest:Y,inclusive:!1})),K=H.messages||[];this.logger.debug("Slack API: conversations.replies response (backward)",{messageCount:K.length,ok:H.ok,hasMore:H.has_more});let U=Math.max(0,K.length-B),G=K.slice(U),D=await Promise.all(G.map((J)=>this.parseSlackMessage(J,w))),q;if(U>0||H.has_more){let J=G[0];if(J?.ts)q=J.ts}return{messages:D,nextCursor:q}}async fetchThread(Q){let{channel:$,threadTs:w}=this.decodeThreadId(Q);try{this.logger.debug("Slack API: conversations.info",{channel:$});let B=await this._client.conversations.info(await this.withToken({channel:$})),X=B.channel;if(X?.is_ext_shared)this._externalChannels.add($);this.logger.debug("Slack API: conversations.info response",{channelName:X?.name,ok:B.ok});let Y="unknown";if(X?.is_ext_shared)Y="external";else if(X?.is_private||$.startsWith("D"))Y="private";else if($.startsWith("C"))Y="workspace";return{id:Q,channelId:$,channelName:X?.name,channelVisibility:Y,metadata:{threadTs:w,channel:B.channel}}}catch(B){this.handleSlackError(B)}}async fetchMessage(Q,$){let{channel:w,threadTs:B}=this.decodeThreadId(Q);try{let Z=((await this._client.conversations.replies(await this.withToken({channel:w,ts:B,oldest:$,inclusive:!0,limit:1}))).messages||[]).find((H)=>H.ts===$);if(!Z)return null;return this.parseSlackMessage(Z,Q)}catch(X){this.handleSlackError(X)}}encodeThreadId(Q){return`slack:${Q.channel}:${Q.threadTs}`}isDM(Q){let{channel:$}=this.decodeThreadId(Q);return $.startsWith("D")}getChannelVisibility(Q){let{channel:$}=this.decodeThreadId(Q);if(this._externalChannels.has($))return"external";if($.startsWith("G")||$.startsWith("D"))return"private";if($.startsWith("C"))return"workspace";return"unknown"}decodeThreadId(Q){let $=Q.split(":");if($.length<2||$.length>3||$[0]!=="slack")throw new G7("slack",`Invalid Slack thread ID: ${Q}`);return{channel:$[1],threadTs:$.length===3?$[2]:""}}parseMessage(Q){let $=Q,w=$.thread_ts||$.ts||"",B=this.encodeThreadId({channel:$.channel||"",threadTs:w});return this.parseSlackMessageSync($,B)}parseSlackMessageSync(Q,$){let w=this.isMessageFromSelf(Q),B=Q.text||"",X=Q.username||Q.user||"unknown",Y=Q.username||Q.user||"unknown";return new iWA({id:Q.ts||"",threadId:$,text:this.formatConverter.extractPlainText(B),formatted:this.formatConverter.toAst(B),raw:Q,author:{userId:Q.user||Q.bot_id||"unknown",userName:X,fullName:Y,isBot:!!Q.bot_id,isMe:w},metadata:{dateSent:new Date(Number.parseFloat(Q.ts||"0")*1000),edited:!!Q.edited,editedAt:Q.edited?new Date(Number.parseFloat(Q.edited.ts)*1000):void 0},attachments:(Q.files||[]).map((Z)=>this.createAttachment(Z,Q.team_id??Q.team)),links:this.extractLinks(Q)})}channelIdFromThreadId(Q){let{channel:$}=this.decodeThreadId(Q);return`slack:${$}`}async fetchChannelMessages(Q,$={}){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=$.direction??"backward",X=$.limit||100;try{if(B==="forward")return await this.fetchChannelMessagesForward(w,X,$.cursor);return await this.fetchChannelMessagesBackward(w,X,$.cursor)}catch(Y){this.handleSlackError(Y)}}async fetchChannelMessagesForward(Q,$,w){this.logger.debug("Slack API: conversations.history (forward)",{channel:Q,limit:$,cursor:w});let B=await this._client.conversations.history(await this.withToken({channel:Q,limit:$,oldest:w,inclusive:w?!1:void 0})),X=(B.messages||[]).reverse(),Y=await Promise.all(X.map((H)=>{let K=H.thread_ts||H.ts||"",U=`slack:${Q}:${K}`;return this.parseSlackMessage(H,U,{skipSelfMention:!1})})),Z;if(B.has_more&&X.length>0){let H=X.at(-1);if(H?.ts)Z=H.ts}return{messages:Y,nextCursor:Z}}async fetchChannelMessagesBackward(Q,$,w){this.logger.debug("Slack API: conversations.history (backward)",{channel:Q,limit:$,cursor:w});let B=await this._client.conversations.history(await this.withToken({channel:Q,limit:$,latest:w,inclusive:w?!1:void 0})),Y=[...B.messages||[]].reverse(),Z=await Promise.all(Y.map((K)=>{let U=K.thread_ts||K.ts||"",G=`slack:${Q}:${U}`;return this.parseSlackMessage(K,G,{skipSelfMention:!1})})),H;if(B.has_more&&Y.length>0){let K=Y[0];if(K?.ts)H=K.ts}return{messages:Z,nextCursor:H}}async listThreads(Q,$={}){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=$.limit||50;try{this.logger.debug("Slack API: conversations.history (listThreads)",{channel:w,limit:B,cursor:$.cursor});let X=await this._client.conversations.history(await this.withToken({channel:w,limit:Math.min(B*3,200),cursor:$.cursor})),H=(X.messages||[]).filter((G)=>(G.reply_count??0)>0).slice(0,B),K=await Promise.all(H.map(async(G)=>{let D=G.ts||"",q=`slack:${w}:${D}`,J=await this.parseSlackMessage(G,q,{skipSelfMention:!1});return{id:q,rootMessage:J,replyCount:G.reply_count,lastReplyAt:G.latest_reply?new Date(Number.parseFloat(G.latest_reply)*1000):void 0}})),U=X.response_metadata?.next_cursor;return{threads:K,nextCursor:U||void 0}}catch(X){this.handleSlackError(X)}}async fetchChannelInfo(Q){let $=Q.split(":")[1];if(!$)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);try{this.logger.debug("Slack API: conversations.info (channel)",{channel:$});let B=(await this._client.conversations.info(await this.withToken({channel:$}))).channel;if(B?.is_ext_shared)this._externalChannels.add($);let X="unknown";if(B?.is_ext_shared)X="external";else if(B?.is_im||B?.is_mpim||B?.is_private||$.startsWith("D"))X="private";else if($.startsWith("C"))X="workspace";return{id:Q,name:B?.name?`#${B.name}`:void 0,isDM:Boolean(B?.is_im||B?.is_mpim),channelVisibility:X,memberCount:B?.num_members,metadata:{purpose:B?.purpose?.value,topic:B?.topic?.value}}}catch(w){this.handleSlackError(w)}}async postChannelMessage(Q,$){let w=Q.split(":")[1];if(!w)throw new G7("slack",`Invalid Slack channel ID: ${Q}`);let B=`slack:${w}:`;return await this.postMessage(B,$)}renderFormatted(Q){return this.formatConverter.fromAst(Q)}isMessageFromSelf(Q){let $=this.requestContext.getStore();if($?.botUserId&&Q.user===$.botUserId)return!0;if(this._botUserId&&Q.user===this._botUserId)return!0;if(this._botId&&Q.bot_id===this._botId)return!0;return!1}handleSlackError(Q){let $=Q;if($.code==="slack_webapi_platform_error"&&$.data?.error==="ratelimited")throw new vV2("slack");throw Q}encodeEphemeralMessageId(Q,$,w){let B=JSON.stringify({responseUrl:$,userId:w});return`ephemeral:${Q}:${btoa(B)}`}decodeEphemeralMessageId(Q){if(!Q.startsWith("ephemeral:"))return null;let $=Q.split(":");if($.length<3)return null;let w=$[1],B=$.slice(2).join(":");try{let X=atob(B);try{let Y=JSON.parse(X);if(Y.responseUrl&&Y.userId)return{messageTs:w,responseUrl:Y.responseUrl,userId:Y.userId}}catch{return{messageTs:w,responseUrl:X,userId:""}}return null}catch{return this.logger.warn("Failed to decode ephemeral messageId",{messageId:Q}),null}}async sendToResponseUrl(Q,$,w){let B;if($==="delete")B={delete_original:!0};else{let Z=w?.message;if(!Z)throw new G7("slack","Message required for replace action");let H=DT(Z);if(H)B={replace_original:!0,text:uw0(H),blocks:mw0(H)};else B={replace_original:!0,text:this.formatConverter.toResponseUrlText(Z)};if(w?.threadTs)B.thread_ts=w.threadTs}this.logger.debug("Slack response_url request",{action:$,threadTs:w?.threadTs});let X=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(B)});if(!X.ok){let Z=await X.text();throw this.logger.error("Slack response_url failed",{action:$,status:X.status,body:Z}),new Kw0("slack",`Failed to ${$} via response_url: ${Z}`)}let Y=await X.text();if(Y)try{return JSON.parse(Y)}catch{return{raw:Y}}return{}}};function SP2(A){let Q=A?.mode??"webhook",$=A?.appToken??process.env.SLACK_APP_TOKEN;if(Q==="socket"){if(!$)throw new G7("slack","appToken is required for socket mode. Set SLACK_APP_TOKEN or provide it in config.");if(A?.clientId||A?.clientSecret)throw new G7("slack","Multi-workspace (clientId/clientSecret) is not supported in socket mode.")}let w=A?.webhookVerifier,B=w?void 0:A?.signingSecret??process.env.SLACK_SIGNING_SECRET;if(Q==="webhook"&&!(B||w))throw new G7("slack","signingSecret or webhookVerifier is required. Set SLACK_SIGNING_SECRET, provide signingSecret in config, or provide a webhookVerifier.");let X=!(A?.botToken||A?.clientId||A?.clientSecret||A?.installationProvider||A?.signingSecret||A?.webhookVerifier),Y={agentView:A?.agentView,apiUrl:A?.apiUrl,appToken:$,mode:Q,signingSecret:B,botToken:A?.botToken??(X?process.env.SLACK_BOT_TOKEN:void 0),clientId:A?.clientId??(X?process.env.SLACK_CLIENT_ID:void 0),clientSecret:A?.clientSecret??(X?process.env.SLACK_CLIENT_SECRET:void 0),encryptionKey:A?.encryptionKey??process.env.SLACK_ENCRYPTION_KEY,installationKeyPrefix:A?.installationKeyPrefix,feedbackButtons:A?.feedbackButtons,installationProvider:A?.installationProvider,loadingMessages:A?.loadingMessages,logger:A?.logger??new dWA("info").child("slack"),nativeStreaming:A?.nativeStreaming,suggestedPrompts:A?.suggestedPrompts,socketForwardingSecret:A?.socketForwardingSecret??process.env.SLACK_SOCKET_FORWARDING_SECRET,userName:A?.userName,botUserId:A?.botUserId,webClientOptions:A?.webClientOptions,webhookVerifier:w};return new $K$(Y)}var wK$=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let $=this.locks.get(A);if($&&$.expiresAt>Date.now())return null;let w={threadId:A,token:BK$(),expiresAt:Date.now()+Q};return this.locks.set(A,w),w}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let $=this.locks.get(A.threadId);if(!$||$.token!==A.token)return!1;if($.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return $.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,$){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:$?Date.now()+$:null})}async setIfNotExists(A,Q,$){this.ensureConnected();let w=this.cache.get(A);if(w)if(w.expiresAt!==null&&w.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:$?Date.now()+$:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,$){this.ensureConnected();let w=this.cache.get(A),B;if(w&&w.expiresAt!==null&&w.expiresAt<=Date.now())B=[];else if(w&&Array.isArray(w.value))B=w.value;else B=[];if(B.push(Q),$?.maxLength&&B.length>$.maxLength)B=B.slice(B.length-$.maxLength);this.cache.set(A,{value:B,expiresAt:$?.ttlMs?Date.now()+$.ttlMs:null})}async enqueue(A,Q,$){this.ensureConnected();let w=this.queues.get(A);if(!w)w=[],this.queues.set(A,w);if(w.push(Q),w.length>$)w.splice(0,w.length-$);return w.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let $=Q.shift();if(Q.length===0)this.queues.delete(A);return $??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,$]of this.locks)if($.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function BK$(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function s_0(A){return new wK$}h0();var XK$=W.object({subscribedAt:W.string().datetime(),routingMode:W.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:W.boolean().optional()});var YK$="chat.discord.subscriptions",ZK$="chat.slack.subscriptions";function WK$(A){return A==="discord"?YK$:ZK$}function uKA(A,Q){return A.scoped({namespace:WK$(Q),schema:XK$})}function mP2(A){return uKA(A,"discord")}function uP2(A){return uKA(A,"slack")}function cP2(A,Q,$=s_0()){let w=new Map;for(let B of Q)w.set(B,uKA(A,B));return new pP2($,w)}class pP2{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){let Q=this.getSubscriptionStore(A);if(!Q)return this.memoryState.subscribe(A);await Q.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){let Q=this.getSubscriptionStore(A);if(!Q)return this.memoryState.unsubscribe(A);await Q.delete(A)}isSubscribed(A){let Q=this.getSubscriptionStore(A);return Q?Q.has(A):this.memoryState.isSubscribed(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,$){return this.memoryState.appendToList(A,Q,$)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,$){return this.memoryState.enqueue(A,Q,$)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,$){return this.memoryState.set(A,Q,$)}setIfNotExists(A,Q,$){return this.memoryState.setIfNotExists(A,Q,$)}getSubscriptionStore(A){let Q=A.split(":")[0];if(Q!=="discord"&&Q!=="slack")return;return this.subscriptions.get(Q)}}function lP2(A,Q){if(!A)throw Error(Q);return A}function iP2(A){let{discord:Q,slack:$}=A,w=Q?YV2({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds}):void 0;if(w)A.gatewayLoop.setAdapter(w);let X=$?SP2($.mode==="socket"?{botToken:$.botToken,mode:"socket",appToken:lP2($.appToken,"Slack app token is required in socket mode")}:{botToken:$.botToken,signingSecret:lP2($.signingSecret,"Slack signing secret is required in webhook mode")}):void 0;if(X&&$?.mode==="socket")A.slackSocketLoop.setAdapter(X);let Y={...w?{discord:w}:{},...X?{slack:X}:{}},Z=[...Q?["discord"]:[],...$?["slack"]:[]],H=Z.length>0?cP2(A.runtimeState,Z):s_0();return new lY2({userName:A.userName,adapters:Y,...Q||$?{concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"}}:{},state:H})}class cKA{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;await this.subscribeThread(A)}async subscribeThread(A){try{await A.subscribe(),await this.getSubscriptions(A)?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(Q){this.deps.logger.debug("Chat thread subscription failed",{error:Q,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){let $=this.getSubscriptions(A);if(!$)return!1;if(A.isDM)return!0;let w=await $.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let X={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,X);else await $.set(A.id,X);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.getSubscriptions(A)?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((w)=>!w.isBot&&!w.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect chat thread participants",{error:Q,threadId:A.id}),!1}}getSubscriptions(A){return this.deps.getSubscriptions(this.deps.getPlatform(A))}}zA();class pKA{deps;constructor(A){this.deps=A}async build(A,Q,$,w){let B={message:HK$(A,$),attachments:[],notices:[]};if($.attachments.length===0)return B;if(!(w==="anchor"||w==="trusted"))return B;let Y=this.deps.getUploadStore(A);if(!Y)return B;for(let Z of $.attachments){let H=Z.name;if(!H)continue;let K=x_(H,"upload"),U=Kk(K,Z.mimeType),G=Z.size??0,D=Zq0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!Wq0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let J=R_({filename:K,mediaType:U,content:q,fallbackFilename:"upload"});if(!J.ok){B.notices.push(J.message);continue}let F=await Y.save({filename:J.filename,mediaType:J.mediaType,content:q,metadata:this.buildMetadata(A,Q,$)});B.attachments.push(dP2(F.filename,F.mediaType,q,F.ref,J.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:K}),B.notices.push(`Could not read file upload: ${K}`)}}return B}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let $=await Q.arrayBuffer();return Buffer.from(new Uint8Array($))}buildMetadata(A,Q,$){let w=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:$.id,uploaderId:$.author.userId,uploaderUsername:$.author.userName,...w.guildId?{guildId:w.guildId}:{},...w.threadId?{threadId:w.threadId}:{}}}}function lKA(A,Q,$,w){return dP2(A,Q,$,w,Uk(A,Q))}function HK$(A,Q){let $=Q.text.trim();if(A!=="slack"||!Q.isMention)return $;return $.replace(/(^|\s)@[UW][A-Z0-9]+\b\s*/g,"$1").trim()}function dP2(A,Q,$,w,B){if(B)return{kind:"text",filename:A,mediaType:Q,content:$.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:$.byteLength,source:w};return{kind:"file",filename:A,mediaType:Q,data:$,sizeBytes:$.byteLength,source:w}}var iKA="discord-chat-upload",dKA="slack-chat-upload",a_0="upload";function nP2(){return{namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}}function nKA(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function rKA(){return{namespace:"slack-chat",refKind:"slack-chat-upload",routePath:"/api/webhooks/chat/slack/uploads"}}function Jf(A){let Q=A.split(":");if(Q[0]!=="discord")return{};return{...Q[1]?{guildId:Q[1]}:{},...Q[2]?{channelId:Q[2]}:{},...Q[3]?{threadId:Q[3]}:{}}}function KK$(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let $=Q.channel_id;return typeof $==="string"?$:void 0}function rP2(A,Q){if(A.isDM)return!1;let $=Jf(A.id);if(!$.threadId)return!1;let w=KK$(Q);return w!==void 0&&w!==$.threadId}function t_0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let $=Jf(A.id),w=A.id.split(":")[0]==="slack"?A.id.split(":")[1]:void 0;return[A.id,A.channelId,$.channelId,$.threadId,w].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function e_0(A,Q,$){if(A.isDM&&!$.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return t_0(A,$)}function oKA(A,Q){if(!Q)return!1;if(A.isDM&&!Q.allowDMs)return!1;return t_0(A,Q)}function cw0(A,Q){let $=Jf(A.id),w=A.id.split(":")[0]==="slack"?A.id.split(":")[1]:void 0;return{channelId:$.channelId??w??A.channelId,isBot:Boolean(Q.author.isBot)}}function $n(A){return A.isDM?"DM":A.channelId}var UK$="https://discord.com/api/v10";async function oP2(A){let Q=Jf(A.threadId),$=Q.threadId??Q.channelId;if(!$)return;let w=A.fetchFn??fetch;try{let B=await w(`${UK$}/channels/${$}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!B.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:$,status:B.status})}catch(B){A.logger.debug("Failed to clear Discord message components",{error:B,messageId:A.messageId,channelId:$})}}var sP2={name:"@brains/chat",version:"0.2.0-alpha.196",description:"Multi-platform Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.33.0","@chat-adapter/slack":"^4.33.0","@chat-adapter/state-memory":"^4.33.0",chat:"^4.33.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","slack:preflight":"bun scripts/slack-preflight.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var DK$=/https?:\/\/\S+/i,qK$=/[\s\S]+/,zK$=/^(?:(?:confirmation|approval) required|please confirm(?: this action)?)\.?$/i,VK$=1000,JK$=W.looseObject({type:W.literal("card"),children:W.array(W.looseObject({type:W.string()})),imageUrl:W.string().optional(),subtitle:W.string().optional(),title:W.string().optional()}),FK$=W.object({card:W.custom((A)=>JK$.safeParse(A).success),fallbackText:W.string().optional()});class AP0 extends f3{threadRegistry=new iN0;pendingApprovals;uploadContinuity;promptActions=new JYA(VK$);pendingJobArtifacts=new Map;toolStatusMessenger=new FYA(this.threadRegistry);compactingSlackApprovalToolStatuses=new Set;activeSlackConfirmationConversations=new Set;cardBuilder=new NYA({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new _YA({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new PYA({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let $=this.config.adapters.discord?.botToken;if(!$)return;await oP2({threadId:A,messageId:Q,botToken:$,logger:this.logger})}});subscriptionRouter=new cKA({getSubscriptions:(A)=>A==="discord"?this.discordSubscriptions:A==="slack"?this.slackSubscriptions:void 0,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rP2,logger:this.logger});chatInputBuilder=new pKA({getUploadStore:(A)=>A==="discord"||A==="slack"?this.getCanonicalUploadStore():void 0,getThreadIdParts:Jf,logger:this.logger});gatewayLoop;slackSocketLoop;chatApp;discordSubscriptions;slackSubscriptions;chatAppRunning=!1;constructor(A={}){super("chat",sP2,A,VYA);this.gatewayLoop=new bYA({getApp:()=>this.chatApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.slackSocketLoop=new jYA({listenerRunMs:this.config.gatewayRunMs,restartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.chatApp=new MYA({discord:this.config.adapters.discord,slack:this.config.adapters.slack,getUploadStore:(Q)=>this.getUploadStore(Q),buildApp:(Q)=>iP2({userName:this.config.userName,discord:this.config.adapters.discord,slack:this.config.adapters.slack,gatewayLoop:this.gatewayLoop,slackSocketLoop:this.slackSocketLoop,runtimeState:Q})}),this.pendingApprovals=new pA0({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,$)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:$})}}),this.uploadContinuity={discord:this.createUploadContinuity("discord"),slack:this.createUploadContinuity("slack")}}async onRegister(A){if(await super.onRegister(A),this.config.adapters.discord)this.discordSubscriptions=mP2(A.runtimeState);if(this.config.adapters.slack)this.slackSubscriptions=uP2(A.runtimeState);this.registerChatHandlers(this.chatApp.build(A.runtimeState))}getWebRoutes(){return this.chatApp.getWebRoutes()}createDaemon(){let A=Boolean(this.config.adapters.discord),Q=this.config.adapters.slack?.mode==="socket";if(!A&&!this.config.adapters.slack)return;return{start:async()=>{if(await this.chatApp.initialize(),this.chatAppRunning=!0,A)this.gatewayLoop.start();if(Q)this.slackSocketLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),await this.slackSocketLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.discord.clear(),this.uploadContinuity.slack.clear(),this.pendingJobArtifacts.clear(),this.toolStatusMessenger.clear(),await this.chatApp.shutdown(),this.chatAppRunning=!1},healthCheck:async()=>{let $=this.chatAppRunning&&(!A||this.gatewayLoop.isRunning())&&(!Q||this.slackSocketLoop.isRunning());return{status:$?"healthy":"error",message:$?"Chat SDK app running":"Chat SDK app stopped",lastCheck:new Date}}}}sendMessageToChannel({channelId:A,message:Q}){let $=this.threadRegistry.get(A);if(!$)return;let w=this.toPlatformPostOutput(A,Q);if(w!==void 0){$.post(w).catch((B)=>this.logger.error("Failed to send chat message",{error:B,channelId:A}));return}if(typeof Q!=="string")return;for(let B of a80(A,Q))$.post(B).catch((X)=>this.logger.error("Failed to send chat message",{error:X,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let $=this.threadRegistry.get(A);if(!$)return;let w=this.toPlatformPostOutput(A,Q);if(w!==void 0){let X=await $.post(w);return this.threadRegistry.trackMessage($.id,X),X.id}if(typeof Q!=="string")return;let B;for(let X of a80(A,Q))B=await $.post(X),this.threadRegistry.trackMessage($.id,B);return B?.id}async editMessage({channelId:A,messageId:Q,newMessage:$}){let w=this.threadRegistry.getMessage(A,Q);if(!w)return!1;try{let B=await w.edit(this.toPlatformPostOutput(A,$)??(typeof $==="string"?$:""));if(A)this.threadRegistry.trackMessage(A,B);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=FK$.safeParse(A);if(!Q.success)return;let{card:$,fallbackText:w}=Q.data;if(w===void 0)return{card:$};return{card:$,fallbackText:w}}toPlatformPostOutput(A,Q){if(typeof Q==="string")return;let $=this.toDiscordCardOutput(Q);if(!$)return;if(rN0(A)==="slack"&&$.fallbackText)return $.fallbackText;return $}formatProgressOutput(A){return IYA(A)}formatCompletionOutput(A){return IYA(A)}async handleProgressEvent(A,Q){let $=A.metadata.interfaceType,w=A,B=Q;if($&&$!==this.id){if(!this.isEnabledPlatform($))return;w={...A,metadata:{...A.metadata,interfaceType:this.id}},B=w.metadata}await super.handleProgressEvent(w,B),await this.deliverCompletedJobArtifacts(w)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;let Q=rN0(A.channelId)==="slack",$=Q&&this.activeSlackConfirmationConversations.has(A.conversationId);if(Q&&this.compactingSlackApprovalToolStatuses.has(Yk(A))||$||Q&&A.state==="completed"){await this.toolStatusMessenger.dismiss(A);return}await this.toolStatusMessenger.handle(A)}async handleAgentResponseToolStatuses(A,Q){let $=new Set([...(A.pendingConfirmations??[]).map((B)=>B.toolName),...(A.cards??[]).filter((B)=>B.kind==="tool-approval").map((B)=>B.toolName)]),w=Q.startsWith("slack-")?[...$].map((B)=>`${Q}:${B}`):[];for(let B of w)this.compactingSlackApprovalToolStatuses.add(B);try{await super.handleAgentResponseToolStatuses(A,Q)}finally{for(let B of w)this.compactingSlackApprovalToolStatuses.delete(B)}}isEnabledPlatform(A){let Q=new Set;if(this.config.adapters.discord)Q.add("discord");if(this.config.adapters.slack)Q.add("slack");return SX2(A,Q)}registerChatHandlers(A){if(A.onDirectMessage(async(Q,$,w,B)=>{await this.handleRoutedMessage(Q,$,B)}),A.onNewMention(async(Q,$,w)=>{let B=this.getPlatformConfig(Q),X=this.getPlatform(Q);if(X==="discord"&&this.config.adapters.discord&&B&&e_0(Q,$,B)&&!Q.isDM&&this.config.adapters.discord.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,$);else if(X==="slack"&&B&&e_0(Q,$,B)&&!Q.isDM)await this.subscriptionRouter.subscribeThread(Q);await this.handleRoutedMessage(Q,$,w)}),A.onSubscribedMessage(async(Q,$,w)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,$))return;await this.handleRoutedMessage(Q,$,w)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention||this.config.adapters.slack&&!this.config.adapters.slack.requireMention)A.onNewMessage(qK$,async(Q,$,w)=>{let B=this.getPlatformConfig(Q);if(!B||B.requireMention)return;await this.handleRoutedMessage(Q,$,w)});A.onNewMessage(DK$,async(Q,$)=>{await this.handlePassiveUrlCapture(Q,$)}),A.onAction([dN0,LYA],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(s80,async(Q)=>{await this.handlePromptAction(Q)}),A.onAction(async(Q)=>{if(!Q.actionId.startsWith(`${s80}:`))return;await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;if(Q!=="discord"&&Q!=="slack")return;let $=A.thread;if(!oKA($,this.getPlatformConfig($)))return;let w=this.promptActions.get(A.value);if(w?.threadId!==$.id){await $.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let B=this.context.permissions.getUserLevel(Q,A.user.userId,cw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}})),X=this.getConversationId(Q,$.id),Y=$.id;await this.runAgentTurn({thread:$,channelId:Y,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let Z=await this.uploadContinuity[Q].selectPriorUploads({conversationId:X,currentAttachments:[],canRestore:B==="anchor"||B==="trusted"}),H=await this.context.agent.chat(w.prompt,X,{userPermissionLevel:B,interfaceType:Q,channelId:Y,channelName:$n($),...this.buildActionEventMetadata(Q,$,A),...Z.length>0?{attachments:Z}:{}});await this.renderAgentResponse({thread:$,channelId:Y,conversationId:X,response:H,userPermissionLevel:B})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;if(Q!=="discord"&&Q!=="slack")return;let $=A.thread;if(!oKA($,this.getPlatformConfig($)))return;let w=this.getConversationId(Q,$.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await $.post(this.formatNoticePayload("That approval is no longer pending."));return}let X=this.context.permissions.getUserLevel(Q,A.user.userId,cw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}}));await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===dN0,userPermissionLevel:X,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,$){if(!this.context)return;let w=this.getPlatform(A);if(!this.isEnabledPlatform(w))return;if(w!=="discord"&&w!=="slack")return;let B=this.getPlatformConfig(A);if(!B)return;if(!e_0(A,Q,B))return;await this.routeToAgent(w,A,Q,$)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,$){let w=this.formatErrorPayload($),B=this.toPlatformPostOutput(Q,w);if(B!==void 0){await A.post(B);return}let X=typeof w==="string"?w:"Message failed.";for(let Y of a80(Q,X))await A.post(Y)}async routeToAgent(A,Q,$,w){if(!this.context)return;this.threadRegistry.set(Q);let B=this.getConversationId(A,Q.id),X=Q.id,Y=cw0(Q,$),Z=this.context.permissions.getUserLevel(A,$.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,$,Z),K=[...H.attachments];if(await this.attachPriorUploads(A,B,H,Z),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments(A,B,K),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let U=await this.getPendingApprovalIds(B);if(U.size>0){if(await this.handleConfirmationResponse(H.message,B,Q,U,Z,this.buildUserMessageMetadata(A,Q,$)))return}let G=this.buildCoalescedAgentInput(H.message,w),D=await this.context.agent.chat(G.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:$n(Q),...this.buildUserMessageMetadata(A,Q,$,G.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:D,userPermissionLevel:Z})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),$=EC(A.response,{deniedCardIds:Q.deniedCardIds});this.rememberPendingJobArtifacts($,A.channelId,A.userPermissionLevel,Q.deliveredCardIds,Q.deniedCardIds);let w=!1;if(A.confirmation){let b=Fc(A.response,A.confirmation.confirmed?"approved":"declined");w=await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,{title:lA0(b.variant),detail:b.label})}let X=$.directives.find((b)=>b.kind==="approvals")?.confirmations,Y=this.getPlatform(A.thread)==="slack",Z=$.directives.some((b)=>b.kind==="artifact"),H=$.directives.some((b)=>b.kind==="artifact"&&Boolean(b.card.jobId)),K=$.directives.some((b)=>b.kind==="denied-artifact"),U=Y&&!A.confirmation&&Boolean(X?.length)&&zK$.test(A.response.text.trim()),G=Y&&Boolean(A.confirmation)&&H&&Q.files.length===0,D=Y&&w&&!X?.length&&!Z&&!K&&Q.files.length===0,q=G||D,J=U||q,F=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText($,Q.deniedCardIds),L=J?void 0:await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:F,files:Q.files}),_=await this.sendArtifactCards(A.thread,$,Y?Q.deliveredCardIds:void 0);if(await this.sendSupplementalCards(A.thread,$,q),Y&&X&&X.length>1){let b=hC(X);if(b)await A.thread.post(b)}else await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,X);let j=_??L;if(j)for(let b of $.jobIds)this.trackAgentResponseForJob(b,j,A.channelId)}rememberPendingJobArtifacts(A,Q,$,w,B){for(let X of A.directives){if(X.kind!=="artifact"||!X.card.jobId)continue;if(w.has(X.card.id)||B.has(X.card.id))continue;let Y=this.pendingJobArtifacts.get(X.card.jobId)??[];this.pendingJobArtifacts.set(X.card.jobId,[...Y.filter((Z)=>Z.card.id!==X.card.id),{card:X.card,channelId:Q,userPermissionLevel:$}])}}async deliverCompletedJobArtifacts(A){if(A.status==="failed"){this.pendingJobArtifacts.delete(A.id);return}if(A.status!=="completed")return;let Q=this.pendingJobArtifacts.get(A.id);if(!Q)return;this.pendingJobArtifacts.delete(A.id);for(let $ of Q){let w=this.threadRegistry.get($.channelId);if(!w)continue;try{let B=await this.artifactDelivery.resolve([$.card],$.userPermissionLevel);if(B.files.length===0)continue;let X=await w.post(this.getPlatform(w)==="slack"?{raw:"",files:B.files}:{markdown:`Generated artifact ready: ${B.files.map((Y)=>Y.filename).join(", ")}`,files:B.files});this.threadRegistry.trackMessage($.channelId,X)}catch(B){this.logger.error("Failed to deliver completed chat artifact",{error:B,jobId:A.id,cardId:$.card.id})}}}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,$,w,B,X){if(!SA0(A,w))return!1;let Y=sD0({message:A,approvalIds:w});if(Y.kind==="not-confirmation"){this.pendingApprovals.deleteConversation(Q);let Z=this.formatNoticePayload("No pending approval to resolve.");return await $.post(this.toPlatformPostOutput($.id,Z)??Z.fallbackText??"No pending approval to resolve."),!0}if(Y.kind==="notice"){let Z=this.formatNoticePayload(Y.message);return await $.post(this.toPlatformPostOutput($.id,Z)??Z.fallbackText??Y.message),!0}return await this.confirmApproval({thread:$,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:B,...X?{metadata:X}:{}}),!0}async confirmApproval(A){let Q=this.getPlatform(A.thread),$=Q==="slack";if($)this.activeSlackConfirmationConversations.add(A.conversationId);try{let w=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:Q,channelId:A.thread.id,channelName:$n(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!w)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:w,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}finally{if($)this.activeSlackConfirmationConversations.delete(A.conversationId)}}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap(($)=>{if($.kind==="text")return[$.text];if($.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard($.card,Q)];return[]}).filter(($)=>$.trim().length>0).join(`
2471
2471
 
2472
2472
  `)}formatConfirmationResponsePayload(A,Q,$,w){let B=wq0({response:A,confirmed:Q,remainingApprovalHelp:$,deniedCardIds:w,formatCard:(X)=>this.cardBuilder.formatStructuredCard(X,w),formatPendingConfirmationHelp:hC});return{card:{type:"card",title:lA0(B.variant),children:B.parts.map((X)=>({type:"text",content:X}))},fallbackText:B.parts.join(`
2473
2473
 
@@ -2539,7 +2539,7 @@ ${gWA(A)}
2539
2539
  <p>Once built, this page will be replaced with your actual website.</p>
2540
2540
  </div>
2541
2541
  </body>
2542
- </html>`;var Cb2={name:"@brains/webserver",version:"0.2.0-alpha.195",dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.1",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Lf extends _F{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",Cb2,A,DUA)}async onRegister(A){if(this.siteUrl=A.siteUrl,this.previewUrl=A.previewUrl,this.siteUrl)A.endpoints.register({label:"Site",url:this.siteUrl,priority:10}),A.interactions.register({id:"site",label:"Public site",description:"Visit the published public site for this brain.",href:this.siteUrl,kind:"human",priority:10});if(this.config.enablePreview&&this.previewUrl)A.endpoints.register({label:"Preview",url:this.previewUrl,priority:20,visibility:"anchor"}),A.interactions.register({id:"preview",label:"Preview site",description:"Open the private preview build.",href:this.previewUrl,kind:"admin",priority:20,visibility:"anchor"});this.serverManager=new GP0({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,$=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,w=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,B=[];if(Q){if(B.push(`Production: ${$}`),A?.previewUrl)B.push(`Preview: ${w}`)}return{status:Q?"healthy":"error",message:Q?B.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?w:void 0,productionUrl:Q?$:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!hb2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(Eb2(this.config.previewDistDir,"index.html"),qUA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!hb2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(Eb2(this.config.productionDistDir,"index.html"),qUA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Uw();zA();h0();aC();var Tb2={name:"@brains/web-chat",version:"0.2.0-alpha.195",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2","@tanstack/react-query":"^5.0.0",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","happy-dom":"^20.10.6",typescript:"^7.0.2",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};zA();async function yb2(A,Q){let $=await Q.resolvePermissionLevel(A);if($==="public")return Q.createOperatorLoginRequiredResponse(A);let w=new URL(A.url),B=w.searchParams.get("id")?.trim();if(!B)return new Response("Missing document id",{status:400});let X=await Sb2({entityType:"document",id:B,permissionLevel:$,entityService:Q.entityService});if(!X)return new Response("Document not found",{status:404});if(typeof X.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=M_("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=k_(X.metadata,B,"document",Y.mimeType);return mb2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function gb2(A,Q){let $=await Q.resolvePermissionLevel(A);if($==="public")return Q.createOperatorLoginRequiredResponse(A);let w=new URL(A.url),B=w.searchParams.get("id")?.trim();if(!B)return new Response("Missing image id",{status:400});let X=await Sb2({entityType:"image",id:B,permissionLevel:$,entityService:Q.entityService});if(!X)return new Response("Image not found",{status:404});if(typeof X.content!=="string")return new Response("Image content is not an image",{status:415});let Y=M_("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=k_(X.metadata,B,"image",Y.mimeType);return mb2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function Sb2(A){let Q={entityType:A.entityType,id:A.id},$=await O_({entityRef:Q,userLevel:A.permissionLevel,getEntity:(w)=>A.entityService.getEntity(w),getVisibleEntity:(w,B)=>A.entityService.getEntity({...w,visibilityScope:B})});return $.status==="visible"?$.entity:void 0}function mb2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":Wk({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}h0();zA();var ow0="upload",ub2=Wc;var DU$={namespace:"upload",refKind:ow0,routePath:"/api/chat/uploads"};function DP0(){return DU$}zA();Ha0();var cb2=Xq0;var pb2=Yq0;var qU$="file",zU$=16384;async function lb2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=Number(A.headers.get("content-length"));if(Number.isFinite($)&&$>pb2+zU$)return new Response("File upload too large",{status:400});let w;try{w=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let B=w.get(qU$);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=R_({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),H=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(H),{status:201})}async function ib2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=new URL(A.url).searchParams.get("id")?.trim();if(!$)return new Response("Missing upload id",{status:400});let w=await rb2($,Q.getUploadStore());if(w instanceof Response)return w;let{record:B,content:X}=w,Y=ob2(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(X).buffer;return new Response(H,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":Wk({disposition:Z,filename:B.filename})}})}function db2(A){let Q=x_(A.filename??cb2),$=JU$(A.url);if(!$)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let w=R_({filename:Q,mediaType:A.mediaType,content:$.buffer});if(!w.ok)return new Response(w.message,{status:400});return sb2(w,$.buffer)}async function nb2(A,Q){let $=await rb2(A,Q);if($ instanceof Response)return $;let{record:w,content:B}=$,X=ob2(w,B);if(X instanceof Response)return X;return sb2(X,B,{kind:ow0,id:A})}async function rb2(A,Q){try{return await Q.read(A)}catch($){if($ instanceof PF)return VU$($);throw $}}function ob2(A,Q){let $=R_({filename:A.filename,mediaType:A.mediaType,content:Q});if(!$.ok)return new Response($.message,{status:400});return $}function sb2(A,Q,$){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...$!==void 0?{source:$}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...$!==void 0?{source:$}:{}}}function VU$(A){switch(A.code){case"invalid_ref":return new Response("Invalid upload ref",{status:400});case"invalid_metadata":return new Response("Invalid upload metadata",{status:500});case"not_found":return new Response("Upload not found",{status:404})}}function JU$(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let w=A.slice(5,A.indexOf(",")).split(";").some((B)=>B.toLowerCase()==="base64");try{let B=w?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:B,byteLength:B.byteLength}}catch{return null}}var FU$=W.object({type:W.literal("text"),text:W.string()}),LU$=W.object({type:W.literal("file"),mediaType:W.string().optional(),filename:W.string().optional(),url:W.string()}),IU$=W.looseObject({state:W.literal("approval-responded"),approval:W.object({id:W.string(),approved:W.boolean()})}),NU$=W.object({id:W.string().optional(),role:W.string(),parts:W.array(W.unknown()).optional(),content:W.string().optional()}),ab2=W.object({id:W.string().optional(),messages:W.array(NU$).min(1),trigger:W.string().optional()}),_U$=W.object({kind:W.literal(ow0),id:W.string().regex(ub2)}),PU$=W.object({type:W.literal("data-upload"),data:W.object({ref:_U$})});async function tb2(A,Q){let $=bU$(A);if(!$)return{message:"",attachments:[]};let w=[],B=[];for(let Y of $.parts??[]){let Z=FU$.safeParse(Y);if(Z.success){if(Z.data.text.length>0)w.push(Z.data.text);continue}let H=LU$.safeParse(Y);if(H.success){let U=db2(H.data);if(U instanceof Response)return U;B.push(U);continue}let K=PU$.safeParse(Y);if(K.success){let U=await nb2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(jU$(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:w.length>0?w.join(`
2542
+ </html>`;var Cb2={name:"@brains/webserver",version:"0.2.0-alpha.196",dependencies:{"@brains/plugins":"workspace:*","@hono/bun-compress":"^0.1.1",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/messaging-service":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class Lf extends _F{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",Cb2,A,DUA)}async onRegister(A){if(this.siteUrl=A.siteUrl,this.previewUrl=A.previewUrl,this.siteUrl)A.endpoints.register({label:"Site",url:this.siteUrl,priority:10}),A.interactions.register({id:"site",label:"Public site",description:"Visit the published public site for this brain.",href:this.siteUrl,kind:"human",priority:10});if(this.config.enablePreview&&this.previewUrl)A.endpoints.register({label:"Preview",url:this.previewUrl,priority:20,visibility:"anchor"}),A.interactions.register({id:"preview",label:"Preview site",description:"Open the private preview build.",href:this.previewUrl,kind:"admin",priority:20,visibility:"anchor"});this.serverManager=new GP0({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,$=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,w=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,B=[];if(Q){if(B.push(`Production: ${$}`),A?.previewUrl)B.push(`Preview: ${w}`)}return{status:Q?"healthy":"error",message:Q?B.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?w:void 0,productionUrl:Q?$:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!hb2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(Eb2(this.config.previewDistDir,"index.html"),qUA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!hb2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(Eb2(this.config.productionDistDir,"index.html"),qUA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Uw();zA();h0();aC();var Tb2={name:"@brains/web-chat",version:"0.2.0-alpha.196",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2","@tanstack/react-query":"^5.0.0",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","happy-dom":"^20.10.6",typescript:"^7.0.2",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};zA();async function yb2(A,Q){let $=await Q.resolvePermissionLevel(A);if($==="public")return Q.createOperatorLoginRequiredResponse(A);let w=new URL(A.url),B=w.searchParams.get("id")?.trim();if(!B)return new Response("Missing document id",{status:400});let X=await Sb2({entityType:"document",id:B,permissionLevel:$,entityService:Q.entityService});if(!X)return new Response("Document not found",{status:404});if(typeof X.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=M_("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=k_(X.metadata,B,"document",Y.mimeType);return mb2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function gb2(A,Q){let $=await Q.resolvePermissionLevel(A);if($==="public")return Q.createOperatorLoginRequiredResponse(A);let w=new URL(A.url),B=w.searchParams.get("id")?.trim();if(!B)return new Response("Missing image id",{status:400});let X=await Sb2({entityType:"image",id:B,permissionLevel:$,entityService:Q.entityService});if(!X)return new Response("Image not found",{status:404});if(typeof X.content!=="string")return new Response("Image content is not an image",{status:415});let Y=M_("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=k_(X.metadata,B,"image",Y.mimeType);return mb2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function Sb2(A){let Q={entityType:A.entityType,id:A.id},$=await O_({entityRef:Q,userLevel:A.permissionLevel,getEntity:(w)=>A.entityService.getEntity(w),getVisibleEntity:(w,B)=>A.entityService.getEntity({...w,visibilityScope:B})});return $.status==="visible"?$.entity:void 0}function mb2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":Wk({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}h0();zA();var ow0="upload",ub2=Wc;var DU$={namespace:"upload",refKind:ow0,routePath:"/api/chat/uploads"};function DP0(){return DU$}zA();Ha0();var cb2=Xq0;var pb2=Yq0;var qU$="file",zU$=16384;async function lb2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=Number(A.headers.get("content-length"));if(Number.isFinite($)&&$>pb2+zU$)return new Response("File upload too large",{status:400});let w;try{w=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let B=w.get(qU$);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=R_({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),H=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(H),{status:201})}async function ib2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=new URL(A.url).searchParams.get("id")?.trim();if(!$)return new Response("Missing upload id",{status:400});let w=await rb2($,Q.getUploadStore());if(w instanceof Response)return w;let{record:B,content:X}=w,Y=ob2(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(X).buffer;return new Response(H,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":Wk({disposition:Z,filename:B.filename})}})}function db2(A){let Q=x_(A.filename??cb2),$=JU$(A.url);if(!$)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let w=R_({filename:Q,mediaType:A.mediaType,content:$.buffer});if(!w.ok)return new Response(w.message,{status:400});return sb2(w,$.buffer)}async function nb2(A,Q){let $=await rb2(A,Q);if($ instanceof Response)return $;let{record:w,content:B}=$,X=ob2(w,B);if(X instanceof Response)return X;return sb2(X,B,{kind:ow0,id:A})}async function rb2(A,Q){try{return await Q.read(A)}catch($){if($ instanceof PF)return VU$($);throw $}}function ob2(A,Q){let $=R_({filename:A.filename,mediaType:A.mediaType,content:Q});if(!$.ok)return new Response($.message,{status:400});return $}function sb2(A,Q,$){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...$!==void 0?{source:$}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...$!==void 0?{source:$}:{}}}function VU$(A){switch(A.code){case"invalid_ref":return new Response("Invalid upload ref",{status:400});case"invalid_metadata":return new Response("Invalid upload metadata",{status:500});case"not_found":return new Response("Upload not found",{status:404})}}function JU$(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let w=A.slice(5,A.indexOf(",")).split(";").some((B)=>B.toLowerCase()==="base64");try{let B=w?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:B,byteLength:B.byteLength}}catch{return null}}var FU$=W.object({type:W.literal("text"),text:W.string()}),LU$=W.object({type:W.literal("file"),mediaType:W.string().optional(),filename:W.string().optional(),url:W.string()}),IU$=W.looseObject({state:W.literal("approval-responded"),approval:W.object({id:W.string(),approved:W.boolean()})}),NU$=W.object({id:W.string().optional(),role:W.string(),parts:W.array(W.unknown()).optional(),content:W.string().optional()}),ab2=W.object({id:W.string().optional(),messages:W.array(NU$).min(1),trigger:W.string().optional()}),_U$=W.object({kind:W.literal(ow0),id:W.string().regex(ub2)}),PU$=W.object({type:W.literal("data-upload"),data:W.object({ref:_U$})});async function tb2(A,Q){let $=bU$(A);if(!$)return{message:"",attachments:[]};let w=[],B=[];for(let Y of $.parts??[]){let Z=FU$.safeParse(Y);if(Z.success){if(Z.data.text.length>0)w.push(Z.data.text);continue}let H=LU$.safeParse(Y);if(H.success){let U=db2(H.data);if(U instanceof Response)return U;B.push(U);continue}let K=PU$.safeParse(Y);if(K.success){let U=await nb2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(jU$(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:w.length>0?w.join(`
2543
2543
 
2544
2544
  `):$.content??"",attachments:B,...$.id?{messageId:$.id}:{}}}function eb2(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map(($)=>IU$.safeParse($)).filter(($)=>$.success).map(($)=>$.data.approval)}function bU$(A){for(let Q=A.messages.length-1;Q>=0;Q-=1){let $=A.messages[Q];if($?.role==="user")return $}return}function jU$(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}zA();var MU$=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function qP0(A){return A.replace(MU$,"").trimEnd()}zA();function Aj2(A,Q,$){A.write({type:"text-start",id:Q}),A.write({type:"text-delta",id:Q,delta:$}),A.write({type:"text-end",id:Q})}function zUA(A,Q){let $=Q.directives.flatMap((w)=>{switch(w.kind){case"artifact":case"supplemental":return[w.card];case"approvals":return w.cards;default:return[]}});for(let w of $){let B=Gq0(w);if(B.kind==="attachment"){A.write({type:"data-attachment",id:B.id,data:B});continue}if(B.kind==="sources"){A.write({type:"data-sources",id:B.id,data:B});continue}if(B.kind==="actions"){A.write({type:"data-actions",id:B.id,data:B});continue}let X=B.toolCallId??B.id,Y=B.input??{};switch(A.write({type:"tool-input-available",toolCallId:X,toolName:B.toolName,input:Y,dynamic:!0,title:B.preview?`${B.summary}
2545
2545
 
@@ -2586,7 +2586,7 @@ ${B.preview}`:B.summary}),B.state){case"approval-requested":A.write({type:"tool-
2586
2586
  --console-accent: var(--color-accent, #c44a1d);
2587
2587
  --console-secondary: var(--color-secondary, #6b2fa0);
2588
2588
  --console-ok: var(--color-success, #3d6b5c);
2589
- --console-warn: var(--color-warning-text-emphasis, #b3801a);
2589
+ --console-warn: var(--palette-warning-text-emphasis-light, #7a4a05);
2590
2590
  --console-err: var(--color-error, #932f2f);
2591
2591
  --console-on-accent: var(--color-on-accent, #fff);
2592
2592
  --console-shadow-card:
@@ -5830,7 +5830,7 @@ ${Uj2}</style></head><body>${aw0(A)}<main id="root" data-web-chat-root>Brain Cha
5830
5830
  `);B=Y.pop()??"";for(let Z of Y){let H=Z.split(`
5831
5831
  `).find((F)=>F.startsWith("data: "));if(!H)continue;let K;try{let F=FG$.safeParse(JSON.parse(H.slice(6)));if(!F.success)continue;K=F.data}catch{return $.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let U=K.result;if(!U?.final)continue;$.cancel().catch(()=>{});let G=U.status,D=G?.state??"unknown",J=(G?.message?.parts??[]).filter((F)=>F.kind==="text"&&typeof F.text==="string").map((F)=>F.text).join(`
5832
5832
  `)||"No response text";return{success:!0,data:{state:D,response:J}}}X=await pj2($,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class ew0 extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class A50 extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function kG$(A,Q,$,w){let B=new AbortController,X;try{return await Promise.race([A(Q,{...$,signal:B.signal}),new Promise((Y,Z)=>{X=setTimeout(()=>{B.abort(),Z(new ew0(w))},w)})])}catch(Y){if(Y instanceof ew0)throw Y;if(B.signal.aborted)throw new ew0(w);throw Y}finally{if(X)clearTimeout(X)}}async function pj2(A,Q){let $;try{return await Promise.race([A.read(),new Promise((w,B)=>{$=setTimeout(()=>B(new A50(Q)),Q)})])}catch(w){if(w instanceof A50)A.cancel().catch(()=>{});throw w}finally{if($)clearTimeout($)}}function OG$(A){if(A instanceof ew0||A instanceof A50)return!1;return A instanceof Error}function kUA(A,Q){let $=Q>1?` after ${Q} attempts`:"";if(A instanceof A50)return`${A.message}${$}`;let w=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${$}: ${w}`}async function OUA(A,Q={},$={}){let w=Q.fetch??globalThis.fetch,B={requestTimeoutMs:Q.requestTimeoutMs??LG$,streamIdleTimeoutMs:Q.streamIdleTimeoutMs??IG$,maxNetworkAttempts:Q.maxNetworkAttempts??NG$},X=bG$(A.agent);if(!X.ok)return{success:!1,error:X.error};let{agentId:Y}=X;if(!Q.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let Z=await Q.entityService.getEntity({entityType:"agent",id:Y,visibilityScope:p7("agent_call is anchor-only and resolves saved remote agents at any visibility")});if(!Z){if($.requireSaved)return{success:!1,error:`Agent ${Y} is not saved or approved.`,code:"agent_not_saved"};if(!jG$(Y))return{success:!1,error:`Agent ${A.agent} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let G=`https://${Y}`,D=await uj2(G,w);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${Y}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let q=mj2(D.url,Y);if(!q.ok)return{success:!1,error:q.error};let J=await cj2(D.url,A.message,w,Q.requestSigner,B);if("success"in J&&J.success===!0){let F=typeof J.data==="object"&&J.data!==null?J.data:{};return{...J,data:{...F,agentCall:{mode:"one-shot",agent:Y},agentContactCandidate:{source:{kind:"url",url:X.sourceUrl??Y}}}}}return J}if(Z.metadata.status==="archived")return{success:!1,error:`Agent ${Y} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(Z.metadata.status!=="approved")return{success:!1,error:`Agent ${Y} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let H=`https://${Y}`,K=await uj2(H,w);if(!K)return{success:!1,error:`Could not fetch Agent Card from ${H}`};let U=mj2(K.url,Y);if(!U.ok)return{success:!1,error:U.error};return cj2(K.url,A.message,w,Q.requestSigner,B)}function ij2(A={}){return{name:"agent_call",description:"Call a remote A2A agent by exact domain-like target or saved local agent id. Use this when the user asks what an exact domain-like agent id has to say, asks to talk/message/contact that id, or asks that agent for its skills/capabilities. For saved agents, the tool enforces approved/not-archived status before network contact. For unsaved exact domains, the tool verifies the A2A Agent Card over HTTPS and may perform a one-shot call without saving; it returns a typed save/connect candidate after success. Use bare ids such as yeehaa.io, docs.rizom.ai, or save-it-regression.example; .example test domains are exact domain-like ids. If the user provides an HTTPS URL such as https://docs.rizom.ai/a2a, pass only the hostname docs.rizom.ai. For follow-ups to a prior exact-id call, call again with the same id so the tool revalidates current state. Never pass a full URL, a display name like Brain, or a non-HTTPS URL. If the user gives an ambiguous name, ask them to connect/save or clarify the agent first.",inputSchema:_G$,visibility:"trusted",sideEffects:"external",handler:async(Q)=>{let $=PG$.safeParse(Q);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};return OUA($.data,A)}}}zA();h0();var fG$=W.object({agent:W.string().trim().min(1).max(253),instruction:W.string().trim().min(1).max(2000),selection:W.string().min(1).max(8000)});function dj2(A,Q){A.messaging.subscribe("a2a:call:request",async($)=>{let w=fG$.safeParse($.payload);if(!w.success)return{success:!1,error:"Invalid A2A call request"};let{agent:B,instruction:X,selection:Y}=w.data,Z=await OUA({agent:B,message:["A CMS author is asking about selected markdown.",`Instruction: ${X}`,"","Selected markdown:",Y].join(`
5833
- `)},Q,{requireSaved:!0});if("success"in Z&&Z.success===!0)return{success:!0,data:Z.data};return{success:!1,error:"error"in Z?Z.error:"Agent call failed"}}),A.messaging.subscribe("a2a:call:agents",async()=>{if(!A.entityService.hasEntityType("agent"))return{success:!0,data:{agents:[]}};return{success:!0,data:{agents:(await A.entityService.listEntities({entityType:"agent",options:{filter:{visibilityScope:p7("operator CMS lists approved A2A contacts at any visibility")}}})).filter((B)=>B.metadata.status==="approved").map((B)=>{let X=B.metadata.name;return{id:B.id,label:typeof X==="string"&&X.length>0?X:B.id}}).sort((B,X)=>B.label.localeCompare(X.label))}}})}var fUA={name:"@brains/a2a",version:"0.2.0-alpha.195",dependencies:{"@a2a-js/sdk":"^0.3.13","@brains/auth-service":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var RG$={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Signature, Signature-Input, Content-Digest, Date","X-Content-Type-Options":"nosniff"};class Hn extends _F{agentCard;taskManager=new jUA;turnSupervisor=new MUA;agentService;jwksResolver=new PUA;app;hasWebserver=!1;constructor(A={}){if(Object.prototype.hasOwnProperty.call(A,"trustedTokens"))throw Error("trustedTokens legacy config is no longer supported");if(Object.prototype.hasOwnProperty.call(A,"outboundTokens"))throw Error("outboundTokens legacy config is no longer supported");super("a2a",fUA,A,Oj2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,dj2(A,this.createClientDeps(A)),this.hasWebserver)A.endpoints.register({label:"A2A",url:"/a2a",priority:25}),A.interactions.register({id:"a2a",label:"A2A",description:"Let other agents discover and talk to this brain.",href:"/a2a",kind:"agent",priority:25}),this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async onReady(A){await this.rebuildAgentCard(A)}async rebuildAgentCard(A){let Q=A.identity.get(),$=A.identity.getProfile(),w=A.tools.listForPermissionLevel("public"),B;if(A.entityService.hasEntityType("skill"))try{let X=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(X.length>0)B=X.map((Y)=>tA0.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=fj2({character:Q,profile:$,version:fUA.version,domain:A.domain,organization:this.config.organization,tools:w,skills:B,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let $=new URL(A.url),w=new URL(`${$.pathname}${$.search}`,FO(A)),B=await jj2({method:A.method,url:w.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await xY()?.getA2APeerTrust(B.domain);return{permissionLevel:X?.keyFingerprint===B.keyFingerprint?X.grantedLevel:"public",callerDomain:B.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[$,w]of Object.entries(RG$))Q.set($,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new Bn;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("/.well-known/agent-directory.json",async(Q)=>{let $=await xj2(this.getContext().entityService);return this.withCors(Q.json($))}),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 $=await Q.req.text(),w;try{w=await this.resolveCaller(Q.req.raw,$)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let B;try{B=JSON.parse($)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let X=Cj2.safeParse(B);if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(X.data.method==="message/stream"){let Z=yj2.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let H=gj2(X.data.id,Z.data.message,{taskManager:this.taskManager,turnSupervisor:this.turnSupervisor,agentService:this.agentService,callerPermissionLevel:w.permissionLevel,callerDomain:w.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:K}=H;return this.withCors(new Response(K,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await hj2(X.data,{taskManager:this.taskManager,turnSupervisor:this.turnSupervisor,agentService:this.agentService,callerPermissionLevel:w.permissionLevel,callerDomain:w.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/.well-known/agent-directory.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=xY();if(!A)return;let Q=A.getIssuer();if(JO(Q)||new URL(Q).protocol!=="https:")return;return async($)=>{let w=await A.getA2ASigningKey();await bj2($,w.privateJwk,w.keyId)}}createClientDeps(A){return{requestSigner:this.createRequestSigner(),requestTimeoutMs:this.config.requestTimeoutMs,streamIdleTimeoutMs:this.config.streamIdleTimeoutMs,maxNetworkAttempts:this.config.maxNetworkAttempts,entityService:A.entityService}}async getTools(){return[ij2(this.createClientDeps(this.getContext()))]}async getInstructions(){return"## Agent-to-agent calls\n- Use `agent_call` for exact domain-like agent ids (for example `yeehaa.io`, `docs.rizom.ai`, or `save-it-regression.example`). A domain-like id is bare text with a dot and no slash/protocol; `.example` test domains are still exact domain-like ids. For saved agents, the tool validates approval before network contact. For unsaved exact domains, it verifies the Agent Card over HTTPS and may perform a one-shot call without saving.\n- Pass only an exact domain-like agent id to `agent_call`. If the user provides an HTTPS URL, pass only its hostname as the agent id (for `https://docs.rizom.ai/a2a`, pass `docs.rizom.ai`). Never pass a full URL, a non-HTTPS URL, or a display name like `Brain`.\n- If the user names an exact domain-like agent id such as `yeehaa.io`, `docs.rizom.ai`, or `refusal-followup.example`, call `agent_call` directly with that id. Do not preflight with `system_list` or `system_get`; the tool reports structured errors such as invalid Agent Card, not approved, or archived.\n- If the user asks you to ask, message, contact, hear what an exact domain-like agent id has to say, or ask that agent for its own skills/capabilities, treat that as an agent call request first and call `agent_call` in the same turn. Do not stop after listing the agent, drafting the question, searching general content locally, or reading saved agent entity metadata.\n- After `agent_call` returns within a turn, answer that turn from its response. Do **not** supplement with `system_get` (or any other read tool) on the agent entity, unless the user explicitly asks for directory/profile details about the agent itself.\n- Do not create, capture, or generate a note containing the user's question in the same turn as an agent contact request. The user asked to ask the agent, not to persist the question.\n- If `agent_call` succeeds for an unsaved one-shot domain, you may offer to save/connect that agent for future calls, but do not auto-save it.\n- If `agent_call` fails because auth, re-authentication, network, invalid Agent Card, or the remote agent is unavailable, report that failure directly. Do not say the agent was saved, connected, or may need to be saved/connected first. If useful, offer to add the agent contact using the word \"add\". Do not answer from memory, local docs, onboarding docs, or general knowledge; the requested agent was the source.\n- Each new turn that asks the same exact domain-like agent id something \u2014 including short follow-ups like \"what skills does it have\", \"and what about X\", \"tell me more\" \u2014 is a **new** contact request and needs its **own** fresh `agent_call`. Do not assume the previous turn's agent response already covers a new question, and do not substitute `system_list`/`system_get` or a no-tool answer for the fresh call. If the previous turn targeted an exact domain-like id such as `yeehaa.io`, use that same id again for the follow-up even if the previous response was a refusal or error; let `agent_call` validate the current directory state again.\n- When the user provides an HTTPS URL for an agent, use its hostname as the exact domain-like id for `agent_call`; the runtime verifies/contact over HTTPS. If the user provides a non-HTTPS URL, ask for the HTTPS agent URL or exact domain-like id instead.\n- If the user refers to an agent by name, first make sure that name resolves to exactly one saved agent id. If multiple saved agents could match, ask a concise clarification question naming the matching saved agent ids and do not call any agent yet. Never choose the first match.\n- After asking that clarification question, end the turn. Do not call `agent_call` later in the same turn.\n- If `agent_call` reports that an exact domain-like agent id cannot be verified, tell the user the agent could not be verified/contacted. Do not create a wish, reminder, todo, note, fallback task, or any new entity.\n- For non-HTTPS URLs and ambiguous display names, do not call `agent_call`; ask the user for the HTTPS agent URL, exact domain-like id, or a clarification first.\n- Use `agent_connect`, not generic entity creation, when the user explicitly asks you to add, save, or connect an agent contact.\n- If the target agent is discovered but not approved yet, do not call it and do not create a wish. Tell the user it must be approved first."}createDaemon(){return{start:async()=>{if(this.hasWebserver)this.logger.info("A2A mounted on shared webserver host");else this.logger.info("A2A running without webserver routes")},stop:async()=>{await this.turnSupervisor.close(),this.logger.info("A2A server stopped")}}}}zA();h0();var nj2={lexicon:1,id:"ai.rizom.brain.card",defs:{main:{type:"record",description:"Public discovery card for a Rizom brain. The operational A2A Agent Card is conventionally served at /.well-known/agent-card.json under siteUrl.",key:"literal:self",record:{type:"object",required:["siteUrl","brain","anchor","skills","model","version","createdAt"],properties:{siteUrl:{type:"string",format:"uri",description:"Public site URL. Consumers derive the A2A Agent Card URL from this base."},brain:{type:"object",description:"Brain identity described by this discovery card.",required:["did","name","role","purpose","values"],properties:{did:{type:"string",description:"Public DID for the brain identity."},name:{type:"string",maxLength:200,description:"Human-readable brain name."},role:{type:"string",maxLength:500,description:"Brain role or persona."},purpose:{type:"string",maxLength:2000,description:"Short public description of what this brain is for."},values:{type:"array",description:"Public values or principles for this brain.",items:{type:"string",maxLength:200},maxLength:50}}},anchor:{type:"object",description:"Minimal owner/operator snapshot for discovery grouping and display.",required:["did","name","kind"],properties:{did:{type:"string",description:"Public DID for the owner/operator anchor identity."},name:{type:"string",maxLength:200,description:"Human-readable anchor name."},kind:{type:"string",knownValues:["professional","team","collective"],description:"Anchor type."}}},skills:{type:"array",description:"User-facing skills this brain advertises for discovery.",items:{type:"object",required:["id","name","description"],properties:{id:{type:"string",maxLength:200},name:{type:"string",maxLength:200},description:{type:"string",maxLength:2000},tags:{type:"array",items:{type:"string"},maxLength:50},examples:{type:"array",items:{type:"string"},maxLength:20}}},maxLength:100},model:{type:"string",description:"Rizom brain model identifier."},version:{type:"string",description:"Brain runtime/model implementation version."},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var rj2={lexicon:1,id:"ai.rizom.brain.deck",defs:{main:{type:"record",description:"Public presentation deck from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},author:{type:"string"},event:{type:"string"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var oj2={lexicon:1,id:"ai.rizom.brain.link",defs:{main:{type:"record",description:"Public curated link from a Rizom brain.",key:"any",record:{type:"object",required:["title","url","createdAt"],properties:{title:{type:"string",maxLength:500},url:{type:"string",format:"uri"},description:{type:"string",maxLength:2000},summary:{type:"string",maxLength:1e5},domain:{type:"string"},capturedAt:{type:"string",format:"datetime"},source:{type:"object",required:["ref","label"],properties:{ref:{type:"string"},label:{type:"string"}}},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var sj2={lexicon:1,id:"ai.rizom.brain.note",defs:{main:{type:"record",description:"Public knowledge note from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var aj2={lexicon:1,id:"ai.rizom.brain.post",defs:{main:{type:"record",description:"Markdown blog post distributed by a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},summary:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},canonicalUrl:{type:"string",format:"uri"},topics:{type:"array",items:{type:"string"},maxLength:50},coverImage:{type:"object",required:["blob"],properties:{blob:{type:"blob"},alt:{type:"string",maxLength:1000},width:{type:"integer"},height:{type:"integer"}}},series:{type:"string",maxLength:200},seriesIndex:{type:"integer"},sourceEntityType:{type:"string",knownValues:["post"]},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},publishedAt:{type:"string",format:"datetime"}}}}}};var tj2={lexicon:1,id:"ai.rizom.brain.project",defs:{main:{type:"record",description:"Public project or case study from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","year","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},year:{type:"integer"},url:{type:"string",format:"uri"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var ej2={lexicon:1,id:"ai.rizom.brain.series",defs:{main:{type:"record",description:"Public content series from a Rizom brain.",key:"any",record:{type:"object",required:["title","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:1e4},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var AM2={lexicon:1,id:"ai.rizom.brain.socialPost",defs:{main:{type:"record",description:"Semantic local social-post entity from a Rizom brain; not a Bluesky feed post.",key:"any",record:{type:"object",required:["title","platform","body","createdAt"],properties:{title:{type:"string",maxLength:300},platform:{type:"string"},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},status:{type:"string"},publishedAt:{type:"string",format:"datetime"},platformPostId:{type:"string"},sourceLocalEntityType:{type:"string"},sourceLocalEntityId:{type:"string"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var QM2={lexicon:1,id:"ai.rizom.brain.topic",defs:{main:{type:"record",description:"Public topic page from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var uG$=W.object({type:W.string()}).catchall(W.unknown()),cG$=W.object({lexicon:W.literal(1),id:W.string(),defs:W.object({main:W.object({type:W.literal("record"),key:W.string().min(1),description:W.string().optional(),record:W.object({type:W.literal("object"),required:W.array(W.string()).optional(),properties:W.record(W.string(),uG$)})})})});function bV(A){return cG$.parse(A)}var i8={"ai.rizom.brain.card":bV(nj2),"ai.rizom.brain.deck":bV(rj2),"ai.rizom.brain.link":bV(oj2),"ai.rizom.brain.note":bV(sj2),"ai.rizom.brain.post":bV(aj2),"ai.rizom.brain.project":bV(tj2),"ai.rizom.brain.series":bV(ej2),"ai.rizom.brain.socialPost":bV(AM2),"ai.rizom.brain.topic":bV(QM2)},pG$="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function sP(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:pG$}}var $M2={"ai.rizom.brain.card":sP("@brains/atproto"),"ai.rizom.brain.deck":sP("@brains/decks"),"ai.rizom.brain.link":sP("@brains/link"),"ai.rizom.brain.note":sP("@brains/note"),"ai.rizom.brain.post":sP("@brains/blog"),"ai.rizom.brain.project":sP("@brains/portfolio"),"ai.rizom.brain.series":sP("@brains/series"),"ai.rizom.brain.socialPost":sP("@brains/social-media"),"ai.rizom.brain.topic":sP("@brains/topics")};function Kn(){return Object.values(i8)}function LP0(A){if(!(A in i8))return;return i8[A]}function IP0(){return Object.entries($M2).map(([A,Q])=>({id:A,...Q}))}h0();function NP0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var lG$=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function iG$(A){let Q=W.string(),$=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)$=$.refine((w)=>A.knownValues?.includes(w),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")$=$.refine((w)=>lG$.test(w)&&!Number.isNaN(Date.parse(w)),{message:"expected datetime"});if(A.format==="uri")$=$.refine((w)=>{try{return new URL(w),!0}catch{return!1}},{message:"expected uri"});return $}function wM2(A){switch(A.type){case"string":return iG$(A);case"integer":return W.number().int();case"boolean":return W.boolean();case"array":{let Q=A.items?wM2(A.items):W.unknown(),$=W.array(Q);if(A.maxLength!==void 0)$=$.max(A.maxLength);return $}case"object":return dG$(A);case"blob":return W.custom(NP0,{message:"expected blob"});default:return W.unknown()}}function BM2(A){let Q=new Set(A.required??[]),$={};for(let[w,B]of Object.entries(A.properties??{})){let X=wM2(B);$[w]=Q.has(w)?X:X.optional()}return $}function dG$(A){return W.object(BM2(A)).passthrough()}function xUA(A,Q,$,w=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;$.addIssue({code:W.ZodIssueCode.custom,path:w,message:`unrecognized field(s): ${B.join(", ")}`})}function nG$(A,Q){if(xUA(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),NP0(A.brain))xUA(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(NP0(A.anchor))xUA(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function jV(A){let Q=W.object({...BM2(A.defs.main.record),$type:W.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(nG$):Q}var RUA={"ai.rizom.brain.card":jV(i8["ai.rizom.brain.card"]),"ai.rizom.brain.deck":jV(i8["ai.rizom.brain.deck"]),"ai.rizom.brain.link":jV(i8["ai.rizom.brain.link"]),"ai.rizom.brain.note":jV(i8["ai.rizom.brain.note"]),"ai.rizom.brain.post":jV(i8["ai.rizom.brain.post"]),"ai.rizom.brain.project":jV(i8["ai.rizom.brain.project"]),"ai.rizom.brain.series":jV(i8["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":jV(i8["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":jV(i8["ai.rizom.brain.topic"])};function rG$(A,Q){let $=A;for(let w of Q){if(typeof w==="symbol")return;if(Array.isArray($)){$=$[Number(w)];continue}if(!NP0($))return;$=$[String(w)]}return $}function oG$(A,Q,$){let w=$.path.join(".");if(w==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if($.code==="invalid_type"&&rG$(Q,$.path)===void 0)return`Missing required AT Protocol record field: ${w}`;if($.code==="invalid_type")return`Invalid AT Protocol record field ${w}: expected ${$.expected}`;if($.code==="too_big")return`Invalid AT Protocol record field ${w}: exceeds maxLength ${$.maximum}`;if($.code==="custom")return`Invalid AT Protocol record field ${w}: ${$.message}`;if($.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${$.keys.join(", ")}`;return`Invalid AT Protocol record field ${w}: ${$.message}`}function aP(A,Q){let $=jV(A).safeParse(Q);if($.success)return;let w=$.error.issues[0];if(!w)throw $.error;throw Error(oG$(A,Q,w))}h0();var Q50="atproto:brain-card-discovered",vUA="atproto:brain-discovered",CUA="atproto:brain-card-refreshed",sG$=W.custom((A)=>RUA["ai.rizom.brain.card"].safeParse(A).success),hUA=W.object({repoDid:W.string().min(1),uri:W.string().min(1),cid:W.string().min(1),record:sG$}).strict(),aG$=W.object({agentId:W.string().min(1),name:W.string().min(1),url:W.string().url(),status:W.enum(["discovered","approved","archived"]),repoDid:W.string().min(1).optional(),brainDid:W.string().min(1).optional(),anchorDid:W.string().min(1).optional(),cardUri:W.string().min(1).optional(),cardCid:W.string().min(1).optional()}).strict();class D9{static instance;projections=new Map;static getInstance(){return this.instance??=new D9,this.instance}static createFresh(){return new D9}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.get(A.entityType);if(Q&&!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);let $=this.projections.get(A.entityType)??[];return $.push(A),this.projections.set(A.entityType,$),this.createUnregister(A.entityType,A)}get(A){let Q=this.projections.get(A);return Q?.[Q.length-1]}has(A){return this.get(A)!==void 0}list(){let A=[];for(let Q of this.projections.keys()){let $=this.get(Q);if($)A.push($)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let $=!0;return()=>{if(!$)return;$=!1;let w=this.projections.get(A);if(!w)return;let B=w.lastIndexOf(Q);if(B!==-1)w.splice(B,1);if(w.length===0)this.projections.delete(A)}}isEquivalentProjection(A,Q){return A.entityType===Q.entityType&&A.collection===Q.collection&&A.lexicon.id===Q.lexicon.id&&A.validate===Q.validate}validateProjection(A){if(A.collection!==A.lexicon.id)throw Error(`AT Protocol projection collection must match lexicon id: ${A.collection} !== ${A.lexicon.id}`);if(!A.lexicon.defs.main.key)throw Error(`AT Protocol projection lexicon must define a record key: ${A.collection}`)}}h0();var XM2={name:"@brains/atproto-registry",version:"0.2.0-alpha.195",description:"Canonical Rizom AT Protocol lexicon registry",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ZM2=W.object({enabled:W.boolean().default(!0)}),EUA="/atproto/lexicons",eG$=W.strictObject({nsid:W.string(),record:W.record(W.string(),W.unknown())});function YM2(A){return new Response(`${JSON.stringify(A,null,2)}
5833
+ `)},Q,{requireSaved:!0});if("success"in Z&&Z.success===!0)return{success:!0,data:Z.data};return{success:!1,error:"error"in Z?Z.error:"Agent call failed"}}),A.messaging.subscribe("a2a:call:agents",async()=>{if(!A.entityService.hasEntityType("agent"))return{success:!0,data:{agents:[]}};return{success:!0,data:{agents:(await A.entityService.listEntities({entityType:"agent",options:{filter:{visibilityScope:p7("operator CMS lists approved A2A contacts at any visibility")}}})).filter((B)=>B.metadata.status==="approved").map((B)=>{let X=B.metadata.name;return{id:B.id,label:typeof X==="string"&&X.length>0?X:B.id}}).sort((B,X)=>B.label.localeCompare(X.label))}}})}var fUA={name:"@brains/a2a",version:"0.2.0-alpha.196",dependencies:{"@a2a-js/sdk":"^0.3.13","@brains/auth-service":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",hono:"^4.12.25"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var RG$={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Signature, Signature-Input, Content-Digest, Date","X-Content-Type-Options":"nosniff"};class Hn extends _F{agentCard;taskManager=new jUA;turnSupervisor=new MUA;agentService;jwksResolver=new PUA;app;hasWebserver=!1;constructor(A={}){if(Object.prototype.hasOwnProperty.call(A,"trustedTokens"))throw Error("trustedTokens legacy config is no longer supported");if(Object.prototype.hasOwnProperty.call(A,"outboundTokens"))throw Error("outboundTokens legacy config is no longer supported");super("a2a",fUA,A,Oj2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,dj2(A,this.createClientDeps(A)),this.hasWebserver)A.endpoints.register({label:"A2A",url:"/a2a",priority:25}),A.interactions.register({id:"a2a",label:"A2A",description:"Let other agents discover and talk to this brain.",href:"/a2a",kind:"agent",priority:25}),this.logger.info("A2A interface registered",{domain:A.domain});else this.logger.info("A2A interface registered in tool-only mode",{domain:A.domain})}async onReady(A){await this.rebuildAgentCard(A)}async rebuildAgentCard(A){let Q=A.identity.get(),$=A.identity.getProfile(),w=A.tools.listForPermissionLevel("public"),B;if(A.entityService.hasEntityType("skill"))try{let X=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(X.length>0)B=X.map((Y)=>tA0.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=fj2({character:Q,profile:$,version:fUA.version,domain:A.domain,organization:this.config.organization,tools:w,skills:B,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let $=new URL(A.url),w=new URL(`${$.pathname}${$.search}`,FO(A)),B=await jj2({method:A.method,url:w.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await xY()?.getA2APeerTrust(B.domain);return{permissionLevel:X?.keyFingerprint===B.keyFingerprint?X.grantedLevel:"public",callerDomain:B.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[$,w]of Object.entries(RG$))Q.set($,w);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new Bn;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("/.well-known/agent-directory.json",async(Q)=>{let $=await xj2(this.getContext().entityService);return this.withCors(Q.json($))}),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 $=await Q.req.text(),w;try{w=await this.resolveCaller(Q.req.raw,$)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let B;try{B=JSON.parse($)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let X=Cj2.safeParse(B);if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(X.data.method==="message/stream"){let Z=yj2.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let H=gj2(X.data.id,Z.data.message,{taskManager:this.taskManager,turnSupervisor:this.turnSupervisor,agentService:this.agentService,callerPermissionLevel:w.permissionLevel,callerDomain:w.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:K}=H;return this.withCors(new Response(K,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await hj2(X.data,{taskManager:this.taskManager,turnSupervisor:this.turnSupervisor,agentService:this.agentService,callerPermissionLevel:w.permissionLevel,callerDomain:w.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/.well-known/agent-directory.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=xY();if(!A)return;let Q=A.getIssuer();if(JO(Q)||new URL(Q).protocol!=="https:")return;return async($)=>{let w=await A.getA2ASigningKey();await bj2($,w.privateJwk,w.keyId)}}createClientDeps(A){return{requestSigner:this.createRequestSigner(),requestTimeoutMs:this.config.requestTimeoutMs,streamIdleTimeoutMs:this.config.streamIdleTimeoutMs,maxNetworkAttempts:this.config.maxNetworkAttempts,entityService:A.entityService}}async getTools(){return[ij2(this.createClientDeps(this.getContext()))]}async getInstructions(){return"## Agent-to-agent calls\n- Use `agent_call` for exact domain-like agent ids (for example `yeehaa.io`, `docs.rizom.ai`, or `save-it-regression.example`). A domain-like id is bare text with a dot and no slash/protocol; `.example` test domains are still exact domain-like ids. For saved agents, the tool validates approval before network contact. For unsaved exact domains, it verifies the Agent Card over HTTPS and may perform a one-shot call without saving.\n- Pass only an exact domain-like agent id to `agent_call`. If the user provides an HTTPS URL, pass only its hostname as the agent id (for `https://docs.rizom.ai/a2a`, pass `docs.rizom.ai`). Never pass a full URL, a non-HTTPS URL, or a display name like `Brain`.\n- If the user names an exact domain-like agent id such as `yeehaa.io`, `docs.rizom.ai`, or `refusal-followup.example`, call `agent_call` directly with that id. Do not preflight with `system_list` or `system_get`; the tool reports structured errors such as invalid Agent Card, not approved, or archived.\n- If the user asks you to ask, message, contact, hear what an exact domain-like agent id has to say, or ask that agent for its own skills/capabilities, treat that as an agent call request first and call `agent_call` in the same turn. Do not stop after listing the agent, drafting the question, searching general content locally, or reading saved agent entity metadata.\n- After `agent_call` returns within a turn, answer that turn from its response. Do **not** supplement with `system_get` (or any other read tool) on the agent entity, unless the user explicitly asks for directory/profile details about the agent itself.\n- Do not create, capture, or generate a note containing the user's question in the same turn as an agent contact request. The user asked to ask the agent, not to persist the question.\n- If `agent_call` succeeds for an unsaved one-shot domain, you may offer to save/connect that agent for future calls, but do not auto-save it.\n- If `agent_call` fails because auth, re-authentication, network, invalid Agent Card, or the remote agent is unavailable, report that failure directly. Do not say the agent was saved, connected, or may need to be saved/connected first. If useful, offer to add the agent contact using the word \"add\". Do not answer from memory, local docs, onboarding docs, or general knowledge; the requested agent was the source.\n- Each new turn that asks the same exact domain-like agent id something \u2014 including short follow-ups like \"what skills does it have\", \"and what about X\", \"tell me more\" \u2014 is a **new** contact request and needs its **own** fresh `agent_call`. Do not assume the previous turn's agent response already covers a new question, and do not substitute `system_list`/`system_get` or a no-tool answer for the fresh call. If the previous turn targeted an exact domain-like id such as `yeehaa.io`, use that same id again for the follow-up even if the previous response was a refusal or error; let `agent_call` validate the current directory state again.\n- When the user provides an HTTPS URL for an agent, use its hostname as the exact domain-like id for `agent_call`; the runtime verifies/contact over HTTPS. If the user provides a non-HTTPS URL, ask for the HTTPS agent URL or exact domain-like id instead.\n- If the user refers to an agent by name, first make sure that name resolves to exactly one saved agent id. If multiple saved agents could match, ask a concise clarification question naming the matching saved agent ids and do not call any agent yet. Never choose the first match.\n- After asking that clarification question, end the turn. Do not call `agent_call` later in the same turn.\n- If `agent_call` reports that an exact domain-like agent id cannot be verified, tell the user the agent could not be verified/contacted. Do not create a wish, reminder, todo, note, fallback task, or any new entity.\n- For non-HTTPS URLs and ambiguous display names, do not call `agent_call`; ask the user for the HTTPS agent URL, exact domain-like id, or a clarification first.\n- Use `agent_connect`, not generic entity creation, when the user explicitly asks you to add, save, or connect an agent contact.\n- If the target agent is discovered but not approved yet, do not call it and do not create a wish. Tell the user it must be approved first."}createDaemon(){return{start:async()=>{if(this.hasWebserver)this.logger.info("A2A mounted on shared webserver host");else this.logger.info("A2A running without webserver routes")},stop:async()=>{await this.turnSupervisor.close(),this.logger.info("A2A server stopped")}}}}zA();h0();var nj2={lexicon:1,id:"ai.rizom.brain.card",defs:{main:{type:"record",description:"Public discovery card for a Rizom brain. The operational A2A Agent Card is conventionally served at /.well-known/agent-card.json under siteUrl.",key:"literal:self",record:{type:"object",required:["siteUrl","brain","anchor","skills","model","version","createdAt"],properties:{siteUrl:{type:"string",format:"uri",description:"Public site URL. Consumers derive the A2A Agent Card URL from this base."},brain:{type:"object",description:"Brain identity described by this discovery card.",required:["did","name","role","purpose","values"],properties:{did:{type:"string",description:"Public DID for the brain identity."},name:{type:"string",maxLength:200,description:"Human-readable brain name."},role:{type:"string",maxLength:500,description:"Brain role or persona."},purpose:{type:"string",maxLength:2000,description:"Short public description of what this brain is for."},values:{type:"array",description:"Public values or principles for this brain.",items:{type:"string",maxLength:200},maxLength:50}}},anchor:{type:"object",description:"Minimal owner/operator snapshot for discovery grouping and display.",required:["did","name","kind"],properties:{did:{type:"string",description:"Public DID for the owner/operator anchor identity."},name:{type:"string",maxLength:200,description:"Human-readable anchor name."},kind:{type:"string",knownValues:["professional","team","collective"],description:"Anchor type."}}},skills:{type:"array",description:"User-facing skills this brain advertises for discovery.",items:{type:"object",required:["id","name","description"],properties:{id:{type:"string",maxLength:200},name:{type:"string",maxLength:200},description:{type:"string",maxLength:2000},tags:{type:"array",items:{type:"string"},maxLength:50},examples:{type:"array",items:{type:"string"},maxLength:20}}},maxLength:100},model:{type:"string",description:"Rizom brain model identifier."},version:{type:"string",description:"Brain runtime/model implementation version."},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var rj2={lexicon:1,id:"ai.rizom.brain.deck",defs:{main:{type:"record",description:"Public presentation deck from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},author:{type:"string"},event:{type:"string"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var oj2={lexicon:1,id:"ai.rizom.brain.link",defs:{main:{type:"record",description:"Public curated link from a Rizom brain.",key:"any",record:{type:"object",required:["title","url","createdAt"],properties:{title:{type:"string",maxLength:500},url:{type:"string",format:"uri"},description:{type:"string",maxLength:2000},summary:{type:"string",maxLength:1e5},domain:{type:"string"},capturedAt:{type:"string",format:"datetime"},source:{type:"object",required:["ref","label"],properties:{ref:{type:"string"},label:{type:"string"}}},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var sj2={lexicon:1,id:"ai.rizom.brain.note",defs:{main:{type:"record",description:"Public knowledge note from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var aj2={lexicon:1,id:"ai.rizom.brain.post",defs:{main:{type:"record",description:"Markdown blog post distributed by a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},summary:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},canonicalUrl:{type:"string",format:"uri"},topics:{type:"array",items:{type:"string"},maxLength:50},coverImage:{type:"object",required:["blob"],properties:{blob:{type:"blob"},alt:{type:"string",maxLength:1000},width:{type:"integer"},height:{type:"integer"}}},series:{type:"string",maxLength:200},seriesIndex:{type:"integer"},sourceEntityType:{type:"string",knownValues:["post"]},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},publishedAt:{type:"string",format:"datetime"}}}}}};var tj2={lexicon:1,id:"ai.rizom.brain.project",defs:{main:{type:"record",description:"Public project or case study from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","year","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:2000},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},year:{type:"integer"},url:{type:"string",format:"uri"},publishedAt:{type:"string",format:"datetime"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var ej2={lexicon:1,id:"ai.rizom.brain.series",defs:{main:{type:"record",description:"Public content series from a Rizom brain.",key:"any",record:{type:"object",required:["title","createdAt"],properties:{title:{type:"string",maxLength:300},slug:{type:"string"},description:{type:"string",maxLength:1e4},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var AM2={lexicon:1,id:"ai.rizom.brain.socialPost",defs:{main:{type:"record",description:"Semantic local social-post entity from a Rizom brain; not a Bluesky feed post.",key:"any",record:{type:"object",required:["title","platform","body","createdAt"],properties:{title:{type:"string",maxLength:300},platform:{type:"string"},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},status:{type:"string"},publishedAt:{type:"string",format:"datetime"},platformPostId:{type:"string"},sourceLocalEntityType:{type:"string"},sourceLocalEntityId:{type:"string"},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var QM2={lexicon:1,id:"ai.rizom.brain.topic",defs:{main:{type:"record",description:"Public topic page from a Rizom brain.",key:"any",record:{type:"object",required:["title","body","createdAt"],properties:{title:{type:"string",maxLength:300},body:{type:"string",maxLength:1e5},format:{type:"string",knownValues:["text/markdown"]},brainDid:{type:"string"},anchorDid:{type:"string"},sourceEntityType:{type:"string"},sourceEntityId:{type:"string"},createdAt:{type:"string",format:"datetime"},updatedAt:{type:"string",format:"datetime"}}}}}};var uG$=W.object({type:W.string()}).catchall(W.unknown()),cG$=W.object({lexicon:W.literal(1),id:W.string(),defs:W.object({main:W.object({type:W.literal("record"),key:W.string().min(1),description:W.string().optional(),record:W.object({type:W.literal("object"),required:W.array(W.string()).optional(),properties:W.record(W.string(),uG$)})})})});function bV(A){return cG$.parse(A)}var i8={"ai.rizom.brain.card":bV(nj2),"ai.rizom.brain.deck":bV(rj2),"ai.rizom.brain.link":bV(oj2),"ai.rizom.brain.note":bV(sj2),"ai.rizom.brain.post":bV(aj2),"ai.rizom.brain.project":bV(tj2),"ai.rizom.brain.series":bV(ej2),"ai.rizom.brain.socialPost":bV(AM2),"ai.rizom.brain.topic":bV(QM2)},pG$="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function sP(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:pG$}}var $M2={"ai.rizom.brain.card":sP("@brains/atproto"),"ai.rizom.brain.deck":sP("@brains/decks"),"ai.rizom.brain.link":sP("@brains/link"),"ai.rizom.brain.note":sP("@brains/note"),"ai.rizom.brain.post":sP("@brains/blog"),"ai.rizom.brain.project":sP("@brains/portfolio"),"ai.rizom.brain.series":sP("@brains/series"),"ai.rizom.brain.socialPost":sP("@brains/social-media"),"ai.rizom.brain.topic":sP("@brains/topics")};function Kn(){return Object.values(i8)}function LP0(A){if(!(A in i8))return;return i8[A]}function IP0(){return Object.entries($M2).map(([A,Q])=>({id:A,...Q}))}h0();function NP0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var lG$=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function iG$(A){let Q=W.string(),$=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)$=$.refine((w)=>A.knownValues?.includes(w),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")$=$.refine((w)=>lG$.test(w)&&!Number.isNaN(Date.parse(w)),{message:"expected datetime"});if(A.format==="uri")$=$.refine((w)=>{try{return new URL(w),!0}catch{return!1}},{message:"expected uri"});return $}function wM2(A){switch(A.type){case"string":return iG$(A);case"integer":return W.number().int();case"boolean":return W.boolean();case"array":{let Q=A.items?wM2(A.items):W.unknown(),$=W.array(Q);if(A.maxLength!==void 0)$=$.max(A.maxLength);return $}case"object":return dG$(A);case"blob":return W.custom(NP0,{message:"expected blob"});default:return W.unknown()}}function BM2(A){let Q=new Set(A.required??[]),$={};for(let[w,B]of Object.entries(A.properties??{})){let X=wM2(B);$[w]=Q.has(w)?X:X.optional()}return $}function dG$(A){return W.object(BM2(A)).passthrough()}function xUA(A,Q,$,w=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;$.addIssue({code:W.ZodIssueCode.custom,path:w,message:`unrecognized field(s): ${B.join(", ")}`})}function nG$(A,Q){if(xUA(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),NP0(A.brain))xUA(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(NP0(A.anchor))xUA(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function jV(A){let Q=W.object({...BM2(A.defs.main.record),$type:W.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(nG$):Q}var RUA={"ai.rizom.brain.card":jV(i8["ai.rizom.brain.card"]),"ai.rizom.brain.deck":jV(i8["ai.rizom.brain.deck"]),"ai.rizom.brain.link":jV(i8["ai.rizom.brain.link"]),"ai.rizom.brain.note":jV(i8["ai.rizom.brain.note"]),"ai.rizom.brain.post":jV(i8["ai.rizom.brain.post"]),"ai.rizom.brain.project":jV(i8["ai.rizom.brain.project"]),"ai.rizom.brain.series":jV(i8["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":jV(i8["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":jV(i8["ai.rizom.brain.topic"])};function rG$(A,Q){let $=A;for(let w of Q){if(typeof w==="symbol")return;if(Array.isArray($)){$=$[Number(w)];continue}if(!NP0($))return;$=$[String(w)]}return $}function oG$(A,Q,$){let w=$.path.join(".");if(w==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if($.code==="invalid_type"&&rG$(Q,$.path)===void 0)return`Missing required AT Protocol record field: ${w}`;if($.code==="invalid_type")return`Invalid AT Protocol record field ${w}: expected ${$.expected}`;if($.code==="too_big")return`Invalid AT Protocol record field ${w}: exceeds maxLength ${$.maximum}`;if($.code==="custom")return`Invalid AT Protocol record field ${w}: ${$.message}`;if($.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${$.keys.join(", ")}`;return`Invalid AT Protocol record field ${w}: ${$.message}`}function aP(A,Q){let $=jV(A).safeParse(Q);if($.success)return;let w=$.error.issues[0];if(!w)throw $.error;throw Error(oG$(A,Q,w))}h0();var Q50="atproto:brain-card-discovered",vUA="atproto:brain-discovered",CUA="atproto:brain-card-refreshed",sG$=W.custom((A)=>RUA["ai.rizom.brain.card"].safeParse(A).success),hUA=W.object({repoDid:W.string().min(1),uri:W.string().min(1),cid:W.string().min(1),record:sG$}).strict(),aG$=W.object({agentId:W.string().min(1),name:W.string().min(1),url:W.string().url(),status:W.enum(["discovered","approved","archived"]),repoDid:W.string().min(1).optional(),brainDid:W.string().min(1).optional(),anchorDid:W.string().min(1).optional(),cardUri:W.string().min(1).optional(),cardCid:W.string().min(1).optional()}).strict();class D9{static instance;projections=new Map;static getInstance(){return this.instance??=new D9,this.instance}static createFresh(){return new D9}static resetInstance(){this.instance=void 0}register(A){this.validateProjection(A);let Q=this.get(A.entityType);if(Q&&!this.isEquivalentProjection(Q,A))throw Error(`AT Protocol projection already registered for entity type ${A.entityType}`);let $=this.projections.get(A.entityType)??[];return $.push(A),this.projections.set(A.entityType,$),this.createUnregister(A.entityType,A)}get(A){let Q=this.projections.get(A);return Q?.[Q.length-1]}has(A){return this.get(A)!==void 0}list(){let A=[];for(let Q of this.projections.keys()){let $=this.get(Q);if($)A.push($)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let $=!0;return()=>{if(!$)return;$=!1;let w=this.projections.get(A);if(!w)return;let B=w.lastIndexOf(Q);if(B!==-1)w.splice(B,1);if(w.length===0)this.projections.delete(A)}}isEquivalentProjection(A,Q){return A.entityType===Q.entityType&&A.collection===Q.collection&&A.lexicon.id===Q.lexicon.id&&A.validate===Q.validate}validateProjection(A){if(A.collection!==A.lexicon.id)throw Error(`AT Protocol projection collection must match lexicon id: ${A.collection} !== ${A.lexicon.id}`);if(!A.lexicon.defs.main.key)throw Error(`AT Protocol projection lexicon must define a record key: ${A.collection}`)}}h0();var XM2={name:"@brains/atproto-registry",version:"0.2.0-alpha.196",description:"Canonical Rizom AT Protocol lexicon registry",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var ZM2=W.object({enabled:W.boolean().default(!0)}),EUA="/atproto/lexicons",eG$=W.strictObject({nsid:W.string(),record:W.record(W.string(),W.unknown())});function YM2(A){return new Response(`${JSON.stringify(A,null,2)}
5834
5834
  `,{headers:{"Content-Type":"application/json"}})}class TUA extends d6{constructor(A={}){super("atproto-registry",XM2,A,ZM2)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${EUA}/index.json`,method:"GET",public:!0,handler:()=>YM2(this.getIndex())},...Kn().map((A)=>({path:`${EUA}/${A.id}.json`,method:"GET",public:!0,handler:()=>YM2(A)}))]}getIndex(){return{lexicons:IP0().map((A)=>({...A,path:`${EUA}/${A.id}.json`}))}}getLexicon(A){return LP0(A)}async getTools(){return[this.createListLexiconsTool(),this.createValidateLexiconTool(),this.createCheckContractsTool()]}createListLexiconsTool(){return{name:`${this.id}_list_lexicons`,description:"List canonical Rizom AT Protocol lexicons.",inputSchema:{},handler:async()=>({success:!0,data:this.getIndex()})}}createValidateLexiconTool(){return{name:`${this.id}_validate_lexicon`,description:"Validate a record payload against a canonical Rizom AT Protocol lexicon.",inputSchema:{nsid:W.string().describe("Canonical lexicon NSID"),record:W.record(W.string(),W.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=eG$.safeParse(A);if(!Q.success)return{success:!1,error:`Invalid input: ${Q.error.message}`};let $=this.getLexicon(Q.data.nsid);if(!$)return{success:!1,error:`Unknown AT Protocol lexicon: ${Q.data.nsid}`};try{return aP($,Q.data.record),{success:!0,data:{valid:!0}}}catch(w){return{success:!0,data:{valid:!1,error:w instanceof Error?w.message:"Invalid record"}}}}}}createCheckContractsTool(){return{name:`${this.id}_check_contracts`,description:"Check that canonical Rizom AT Protocol lexicon contracts are available.",inputSchema:{},handler:async()=>({success:!0,data:{lexiconCount:Kn().length,nsids:Kn().map((A)=>A.id),metadata:IP0()}})}}}function $50(A={}){return new TUA(A)}zA();class yUA{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,$,w,B=!0){if(this.logger=A,this.fileOperations=w,this.deleteOnFileRemoval=B,$)this.handleImport=async(X)=>{let Y=await $({type:"directory-import",data:{paths:[X]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:X})},this.handleDelete=async(X)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:X});return}try{let{entityType:Y,id:Z}=this.fileOperations.parseEntityFromPath(X),H=await $({type:"directory-delete",data:{entityId:Z,entityType:Y,filePath:X}});this.logger.info("Queued delete job for removed file",{jobId:H,path:X,entityId:Z,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:X,error:Y})}};else this.handleImport=async(X)=>{await Q([X])},this.handleDelete=async(X)=>{this.logger.warn("File deleted but no job queue available",{path:X})}}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($){this.logger.error("Failed to handle file change",{event:A,path:Q,error:$})}}}import{EventEmitter as fD$}from"events";import{stat as xD$,Stats as VM5}from"fs";import{readdir as RD$,stat as vD$}from"fs/promises";import*as D8 from"path";import{lstat as WM2,readdir as AD$,realpath as QD$,stat as $D$}from"fs/promises";import{join as wD$,relative as BD$,resolve as HM2,sep as XD$}from"path";import{Readable as YD$}from"stream";var yG={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},gUA={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:yG.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(gUA);var DM2="READDIRP_RECURSIVE_ERROR",ZD$=new Set(["ENOENT","EPERM","EACCES","ELOOP",DM2]),KM2=[yG.DIR_TYPE,yG.EVERYTHING_TYPE,yG.FILE_DIR_TYPE,yG.FILE_TYPE],WD$=new Set([yG.DIR_TYPE,yG.EVERYTHING_TYPE,yG.FILE_DIR_TYPE]),HD$=new Set([yG.EVERYTHING_TYPE,yG.FILE_DIR_TYPE,yG.FILE_TYPE]),KD$=(A)=>ZD$.has(A.code),UD$=process.platform==="win32",UM2=(A)=>!0,GM2=(A)=>{if(A===void 0)return UM2;if(typeof A==="function")return A;if(typeof A==="string"){let Q=A.trim();return($)=>$.basename===Q}if(Array.isArray(A)){let Q=A.map(($)=>$.trim());return($)=>Q.some((w)=>$.basename===w)}return UM2};class SUA extends YD${parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(A={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:A.highWaterMark});let Q={...gUA,...A},{root:$,type:w}=Q;this._fileFilter=GM2(Q.fileFilter),this._directoryFilter=GM2(Q.directoryFilter);let B=Q.lstat?WM2:$D$;if(UD$)this._stat=(X)=>B(X,{bigint:!0});else this._stat=B;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:gUA.depth,this._wantsDir=w?WD$.has(w):!1,this._wantsFile=w?HD$.has(w):!1,this._wantsEverything=w===yG.EVERYTHING_TYPE,this._root=HM2($),this._isDirent=!Q.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir($,1)],this.reading=!1,this.parent=void 0}async _read(A){if(this.reading)return;this.reading=!0;try{while(!this.destroyed&&A>0){let Q=this.parent,$=Q&&Q.files;if($&&$.length>0){let{path:w,depth:B}=Q,X=$.splice(0,A).map((Z)=>this._formatEntry(Z,w)),Y=await Promise.all(X);for(let Z of Y){if(!Z)continue;if(this.destroyed)return;let H=await this._getEntryType(Z);if(H==="directory"&&this._directoryFilter(Z)){if(B<=this._maxDepth)this.parents.push(this._exploreDir(Z.fullPath,B+1));if(this._wantsDir)this.push(Z),A--}else if((H==="file"||this._includeAsFile(Z))&&this._fileFilter(Z)){if(this._wantsFile)this.push(Z),A--}}}else{let w=this.parents.pop();if(!w){this.push(null);break}if(this.parent=await w,this.destroyed)return}}}catch(Q){this.destroy(Q)}finally{this.reading=!1}}async _exploreDir(A,Q){let $;try{$=await AD$(A,this._rdOptions)}catch(w){this._onError(w)}return{files:$,depth:Q,path:A}}async _formatEntry(A,Q){let $,w=this._isDirent?A.name:A;try{let B=HM2(wD$(Q,w));$={path:BD$(this._root,B),fullPath:B,basename:w},$[this._statsProp]=this._isDirent?A:await this._stat(B)}catch(B){this._onError(B);return}return $}_onError(A){if(KD$(A)&&!this.destroyed)this.emit("warn",A);else this.destroy(A)}async _getEntryType(A){if(!A&&this._statsProp in A)return"";let Q=A[this._statsProp];if(Q.isFile())return"file";if(Q.isDirectory())return"directory";if(Q&&Q.isSymbolicLink()){let $=A.fullPath;try{let w=await QD$($),B=await WM2(w);if(B.isFile())return"file";if(B.isDirectory()){let X=w.length;if($.startsWith(w)&&$.substr(X,1)===XD$){let Y=Error(`Circular symlink detected: "${$}" points to "${w}"`);return Y.code=DM2,this._onError(Y)}return"directory"}}catch(w){return this._onError(w),""}}}_includeAsFile(A){let Q=A&&A[this._statsProp];return Q&&this._wantsEverything&&!Q.isDirectory()}}function qM2(A,Q={}){let $=Q.entryType||Q.type;if($==="both")$=yG.FILE_DIR_TYPE;if($)Q.type=$;if(!A)throw Error("readdirp: root argument is required. Usage: readdirp(root, options)");else if(typeof A!=="string")throw TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");else if($&&!KM2.includes($))throw Error(`readdirp: Invalid type passed. Use one of ${KM2.join(", ")}`);return Q.root=A,new SUA(Q)}import{watch as GD$,unwatchFile as zM2,watchFile as DD$}from"fs";import{realpath as mUA,lstat as qD$,open as zD$,stat as JM2}from"fs/promises";import{type as VD$}from"os";import*as TB from"path";var JD$="data",pUA="end",FM2="close",jP0=()=>{};var MP0=process.platform,lUA=MP0==="win32",FD$=MP0==="darwin",LD$=MP0==="linux",ID$=MP0==="freebsd",LM2=VD$()==="OS400",ZB={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},MV=ZB,ND$="watch",_D$={lstat:qD$,stat:JM2},jT="listeners",_P0="errHandlers",Un="rawEmitters",PD$=[jT,_P0,Un],bD$=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),jD$=(A)=>bD$.has(TB.extname(A).slice(1).toLowerCase()),cUA=(A,Q)=>{if(A instanceof Set)A.forEach(Q);else Q(A)},w50=(A,Q,$)=>{let w=A[Q];if(!(w instanceof Set))A[Q]=w=new Set([w]);w.add($)},MD$=(A)=>(Q)=>{let $=A[Q];if($ instanceof Set)$.clear();else delete A[Q]},B50=(A,Q,$)=>{let w=A[Q];if(w instanceof Set)w.delete($);else if(w===$)delete A[Q]},IM2=(A)=>A instanceof Set?A.size===0:!A,PP0=new Map;function VM2(A,Q,$,w,B){let X=(Y,Z)=>{if($(A),B(Y,Z,{watchedPath:A}),Z&&A!==Z)bP0(TB.resolve(A,Z),jT,TB.join(A,Z))};try{return GD$(A,{persistent:Q.persistent},X)}catch(Y){w(Y);return}}var bP0=(A,Q,$,w,B)=>{let X=PP0.get(A);if(!X)return;cUA(X[Q],(Y)=>{Y($,w,B)})},kD$=(A,Q,$,w)=>{let{listener:B,errHandler:X,rawEmitter:Y}=w,Z=PP0.get(Q),H;if(!$.persistent){if(H=VM2(A,$,B,X,Y),!H)return;return H.close.bind(H)}if(Z)w50(Z,jT,B),w50(Z,_P0,X),w50(Z,Un,Y);else{if(H=VM2(A,$,bP0.bind(null,Q,jT),X,bP0.bind(null,Q,Un)),!H)return;H.on(MV.ERROR,async(K)=>{let U=bP0.bind(null,Q,_P0);if(Z)Z.watcherUnusable=!0;if(lUA&&K.code==="EPERM")try{await(await zD$(A,"r")).close(),U(K)}catch(G){}else U(K)}),Z={listeners:B,errHandlers:X,rawEmitters:Y,watcher:H},PP0.set(Q,Z)}return()=>{if(B50(Z,jT,B),B50(Z,_P0,X),B50(Z,Un,Y),IM2(Z.listeners))Z.watcher.close(),PP0.delete(Q),PD$.forEach(MD$(Z)),Z.watcher=void 0,Object.freeze(Z)}},uUA=new Map,OD$=(A,Q,$,w)=>{let{listener:B,rawEmitter:X}=w,Y=uUA.get(Q),Z=Y&&Y.options;if(Z&&(Z.persistent<$.persistent||Z.interval>$.interval))zM2(Q),Y=void 0;if(Y)w50(Y,jT,B),w50(Y,Un,X);else Y={listeners:B,rawEmitters:X,options:$,watcher:DD$(Q,$,(H,K)=>{cUA(Y.rawEmitters,(G)=>{G(MV.CHANGE,Q,{curr:H,prev:K})});let U=H.mtimeMs;if(H.size!==K.size||U>K.mtimeMs||U===0)cUA(Y.listeners,(G)=>G(A,H))})},uUA.set(Q,Y);return()=>{if(B50(Y,jT,B),B50(Y,Un,X),IM2(Y.listeners))uUA.delete(Q),zM2(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class iUA{fsw;_boundHandleError;constructor(A){this.fsw=A,this._boundHandleError=(Q)=>A._handleError(Q)}_watchWithNodeFs(A,Q){let $=this.fsw.options,w=TB.dirname(A),B=TB.basename(A);this.fsw._getWatchedDir(w).add(B);let Y=TB.resolve(A),Z={persistent:$.persistent};if(!Q)Q=jP0;let H;if($.usePolling){let K=$.interval!==$.binaryInterval;Z.interval=K&&jD$(B)?$.binaryInterval:$.interval,H=OD$(A,Y,Z,{listener:Q,rawEmitter:this.fsw._emitRaw})}else H=kD$(A,Y,Z,{listener:Q,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return H}_handleFile(A,Q,$){if(this.fsw.closed)return;let w=TB.dirname(A),B=TB.basename(A),X=this.fsw._getWatchedDir(w),Y=Q;if(X.has(B))return;let Z=async(K,U)=>{if(!this.fsw._throttle(ND$,A,5))return;if(!U||U.mtimeMs===0)try{let G=await JM2(A);if(this.fsw.closed)return;let{atimeMs:D,mtimeMs:q}=G;if(!D||D<=q||q!==Y.mtimeMs)this.fsw._emit(MV.CHANGE,A,G);if((FD$||LD$||ID$)&&Y.ino!==G.ino){this.fsw._closeFile(K),Y=G;let J=this._watchWithNodeFs(A,Z);if(J)this.fsw._addPathCloser(K,J)}else Y=G}catch(G){this.fsw._remove(w,B)}else if(X.has(B)){let{atimeMs:G,mtimeMs:D}=U;if(!G||G<=D||D!==Y.mtimeMs)this.fsw._emit(MV.CHANGE,A,U);Y=U}},H=this._watchWithNodeFs(A,Z);if(!($&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(MV.ADD,A,0))return;this.fsw._emit(MV.ADD,A,Q)}return H}async _handleSymlink(A,Q,$,w){if(this.fsw.closed)return;let B=A.fullPath,X=this.fsw._getWatchedDir(Q);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let Y;try{Y=await mUA($)}catch(Z){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(X.has(w)){if(this.fsw._symlinkPaths.get(B)!==Y)this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(MV.CHANGE,$,A.stats)}else X.add(w),this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(MV.ADD,$,A.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has(B))return!0;this.fsw._symlinkPaths.set(B,!0)}_handleRead(A,Q,$,w,B,X,Y){A=TB.join(A,"");let Z=w?`${A}:${w}`:A;if(Y=this.fsw._throttle("readdir",Z,1000),!Y)return;let H=this.fsw._getWatchedDir($.path),K=new Set,U=this.fsw._readdirp(A,{fileFilter:(G)=>$.filterPath(G),directoryFilter:(G)=>$.filterDir(G)});if(!U)return;return U.on(JD$,async(G)=>{if(this.fsw.closed){U=void 0;return}let D=G.path,q=TB.join(A,D);if(K.add(D),G.stats.isSymbolicLink()&&await this._handleSymlink(G,A,q,D))return;if(this.fsw.closed){U=void 0;return}if(D===w||!w&&!H.has(D))this.fsw._incrReadyCount(),q=TB.join(B,TB.relative(B,q)),this._addToNodeFs(q,Q,$,X+1)}).on(MV.ERROR,this._boundHandleError),new Promise((G,D)=>{if(!U)return D();U.once(pUA,()=>{if(this.fsw.closed){U=void 0;return}let q=Y?Y.clear():!1;if(G(void 0),H.getChildren().filter((J)=>{return J!==A&&!K.has(J)}).forEach((J)=>{this.fsw._remove(A,J)}),U=void 0,q)this._handleRead(A,!1,$,w,B,X,Y)})})}async _handleDir(A,Q,$,w,B,X,Y){let Z=this.fsw._getWatchedDir(TB.dirname(A)),H=Z.has(TB.basename(A));if(!($&&this.fsw.options.ignoreInitial)&&!B&&!H)this.fsw._emit(MV.ADD_DIR,A,Q);Z.add(TB.basename(A)),this.fsw._getWatchedDir(A);let K,U,G=this.fsw.options.depth;if((G==null||w<=G)&&!this.fsw._symlinkPaths.has(Y)){if(!B){if(await this._handleRead(A,$,X,B,A,w,K),this.fsw.closed)return}U=this._watchWithNodeFs(A,(D,q)=>{if(q&&q.mtimeMs===0)return;this._handleRead(D,!1,X,B,A,w,K)})}return U}async _addToNodeFs(A,Q,$,w,B){let X=this.fsw._emitReady;if(this.fsw._isIgnored(A)||this.fsw.closed)return X(),!1;let Y=this.fsw._getWatchHelpers(A);if($)Y.filterPath=(Z)=>$.filterPath(Z),Y.filterDir=(Z)=>$.filterDir(Z);try{let Z=await _D$[Y.statMethod](Y.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(Y.watchPath,Z))return X(),!1;let H=this.fsw.options.followSymlinks,K;if(Z.isDirectory()){let U=TB.resolve(A),G=H?await mUA(A):A;if(this.fsw.closed)return;if(K=await this._handleDir(Y.watchPath,Z,Q,w,B,Y,G),this.fsw.closed)return;if(U!==G&&G!==void 0)this.fsw._symlinkPaths.set(U,G)}else if(Z.isSymbolicLink()){let U=H?await mUA(A):A;if(this.fsw.closed)return;let G=TB.dirname(Y.watchPath);if(this.fsw._getWatchedDir(G).add(Y.watchPath),this.fsw._emit(MV.ADD,Y.watchPath,Z),K=await this._handleDir(G,Z,Q,w,A,Y,U),this.fsw.closed)return;if(U!==void 0)this.fsw._symlinkPaths.set(TB.resolve(A),U)}else K=this._handleFile(Y.watchPath,Z,Q);if(X(),K)this.fsw._addPathCloser(A,K);return!1}catch(Z){if(this.fsw._handleError(Z))return X(),A}}}/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */var dUA="/",CD$="//",jM2=".",hD$="..",ED$="string",TD$=/\\/g,MM2=/\/\//g,yD$=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,gD$=/^\.[/\\]/;function kP0(A){return Array.isArray(A)?A:[A]}var nUA=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function SD$(A){if(typeof A==="function")return A;if(typeof A==="string")return(Q)=>A===Q;if(A instanceof RegExp)return(Q)=>A.test(Q);if(typeof A==="object"&&A!==null)return(Q)=>{if(A.path===Q)return!0;if(A.recursive){let $=D8.relative(A.path,Q);if(!$)return!1;return!$.startsWith("..")&&!D8.isAbsolute($)}return!1};return()=>!1}function mD$(A){if(typeof A!=="string")throw Error("string expected");A=D8.normalize(A),A=A.replace(/\\/g,"/");let Q=!1;if(A.startsWith("//"))Q=!0;if(A=A.replace(MM2,"/"),Q)A="/"+A;return A}function NM2(A,Q,$){let w=mD$(Q);for(let B=0;B<A.length;B++){let X=A[B];if(X(w,$))return!0}return!1}function uD$(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let w=kP0(A).map((B)=>SD$(B));if(Q==null)return(B,X)=>{return NM2(w,B,X)};return NM2(w,Q)}var _M2=(A)=>{let Q=kP0(A).flat();if(!Q.every(($)=>typeof $===ED$))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(kM2)},PM2=(A)=>{let Q=A.replace(TD$,dUA),$=!1;if(Q.startsWith(CD$))$=!0;if(Q=Q.replace(MM2,dUA),$)Q=dUA+Q;return Q},kM2=(A)=>PM2(D8.normalize(PM2(A))),bM2=(A="")=>(Q)=>{if(typeof Q==="string")return kM2(D8.isAbsolute(Q)?Q:D8.join(A,Q));else return Q},cD$=(A,Q)=>{if(D8.isAbsolute(A))return A;return D8.join(Q,A)},pD$=Object.freeze(new Set);class OM2{path;_removeWatcher;items;constructor(A,Q){this.path=A,this._removeWatcher=Q,this.items=new Set}add(A){let{items:Q}=this;if(!Q)return;if(A!==jM2&&A!==hD$)Q.add(A)}async remove(A){let{items:Q}=this;if(!Q)return;if(Q.delete(A),Q.size>0)return;let $=this.path;try{await RD$($)}catch(w){if(this._removeWatcher)this._removeWatcher(D8.dirname($),D8.basename($))}}has(A){let{items:Q}=this;if(!Q)return;return Q.has(A)}getChildren(){let{items:A}=this;if(!A)return[];return[...A.values()]}dispose(){this.items.clear(),this.path="",this._removeWatcher=jP0,this.items=pD$,Object.freeze(this)}}var lD$="stat",iD$="lstat";class fM2{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,$){this.fsw=$;let w=A;this.path=A=A.replace(gD$,""),this.watchPath=w,this.fullWatchPath=D8.resolve(w),this.dirParts=[],this.dirParts.forEach((B)=>{if(B.length>1)B.pop()}),this.followSymlinks=Q,this.statMethod=Q?lD$:iD$}entryPath(A){return D8.join(this.watchPath,D8.relative(this.watchPath,A.fullPath))}filterPath(A){let{stats:Q}=A;if(Q&&Q.isSymbolicLink())return this.filterDir(A);let $=this.entryPath(A);return this.fsw._isntIgnored($,Q)&&this.fsw._hasReadPermissions(Q)}filterDir(A){return this.fsw._isntIgnored(this.entryPath(A),A.stats)}}class rUA extends fD${closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(A={}){super();this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let Q=A.awaitWriteFinish,$={stabilityThreshold:2000,pollInterval:100},w={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...A,ignored:A.ignored?kP0(A.ignored):kP0([]),awaitWriteFinish:Q===!0?$:typeof Q==="object"?{...$,...Q}:!1};if(LM2)w.usePolling=!0;if(w.atomic===void 0)w.atomic=!w.usePolling;let B=process.env.CHOKIDAR_USEPOLLING;if(B!==void 0){let Z=B.toLowerCase();if(Z==="false"||Z==="0")w.usePolling=!1;else if(Z==="true"||Z==="1")w.usePolling=!0;else w.usePolling=!!Z}let X=process.env.CHOKIDAR_INTERVAL;if(X)w.interval=Number.parseInt(X,10);let Y=0;this._emitReady=()=>{if(Y++,Y>=this._readyCount)this._emitReady=jP0,this._readyEmitted=!0,process.nextTick(()=>this.emit(ZB.READY))},this._emitRaw=(...Z)=>this.emit(ZB.RAW,...Z),this._boundRemove=this._remove.bind(this),this.options=w,this._nodeFsHandler=new iUA(this),Object.freeze(w)}_addIgnoredPath(A){if(nUA(A)){for(let Q of this._ignoredPaths)if(nUA(Q)&&Q.path===A.path&&Q.recursive===A.recursive)return}this._ignoredPaths.add(A)}_removeIgnoredPath(A){if(this._ignoredPaths.delete(A),typeof A==="string"){for(let Q of this._ignoredPaths)if(nUA(Q)&&Q.path===A)this._ignoredPaths.delete(Q)}}add(A,Q,$){let{cwd:w}=this.options;this.closed=!1,this._closePromise=void 0;let B=_M2(A);if(w)B=B.map((X)=>{return cD$(X,w)});if(B.forEach((X)=>{this._removeIgnoredPath(X)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=B.length,Promise.all(B.map(async(X)=>{let Y=await this._nodeFsHandler._addToNodeFs(X,!$,void 0,0,Q);if(Y)this._emitReady();return Y})).then((X)=>{if(this.closed)return;X.forEach((Y)=>{if(Y)this.add(D8.dirname(Y),D8.basename(Q||Y))})}),this}unwatch(A){if(this.closed)return this;let Q=_M2(A),{cwd:$}=this.options;return Q.forEach((w)=>{if(!D8.isAbsolute(w)&&!this._closers.has(w)){if($)w=D8.join($,w);w=D8.resolve(w)}if(this._closePath(w),this._addIgnoredPath(w),this._watched.has(w))this._addIgnoredPath({path:w,recursive:!0});this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let A=[];return this._closers.forEach((Q)=>Q.forEach(($)=>{let w=$();if(w instanceof Promise)A.push(w)})),this._streams.forEach((Q)=>Q.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach((Q)=>Q.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=A.length?Promise.all(A).then(()=>{return}):Promise.resolve(),this._closePromise}getWatched(){let A={};return this._watched.forEach((Q,$)=>{let B=(this.options.cwd?D8.relative(this.options.cwd,$):$)||jM2;A[B]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==ZB.ERROR)this.emit(ZB.ALL,A,...Q)}async _emit(A,Q,$){if(this.closed)return;let w=this.options;if(lUA)Q=D8.normalize(Q);if(w.cwd)Q=D8.relative(w.cwd,Q);let B=[Q];if($!=null)B.push($);let X=w.awaitWriteFinish,Y;if(X&&(Y=this._pendingWrites.get(Q)))return Y.lastChange=new Date,this;if(w.atomic){if(A===ZB.UNLINK)return this._pendingUnlinks.set(Q,[A,...B]),setTimeout(()=>{this._pendingUnlinks.forEach((Z,H)=>{this.emit(...Z),this.emit(ZB.ALL,...Z),this._pendingUnlinks.delete(H)})},typeof w.atomic==="number"?w.atomic:100),this;if(A===ZB.ADD&&this._pendingUnlinks.has(Q))A=ZB.CHANGE,this._pendingUnlinks.delete(Q)}if(X&&(A===ZB.ADD||A===ZB.CHANGE)&&this._readyEmitted){let Z=(H,K)=>{if(H)A=ZB.ERROR,B[0]=H,this.emitWithAll(A,B);else if(K){if(B.length>1)B[1]=K;else B.push(K);this.emitWithAll(A,B)}};return this._awaitWriteFinish(Q,X.stabilityThreshold,A,Z),this}if(A===ZB.CHANGE){if(!this._throttle(ZB.CHANGE,Q,50))return this}if(w.alwaysStat&&$===void 0&&(A===ZB.ADD||A===ZB.ADD_DIR||A===ZB.CHANGE)){let Z=w.cwd?D8.join(w.cwd,Q):Q,H;try{H=await vD$(Z)}catch(K){}if(!H||this.closed)return;B.push(H)}return this.emitWithAll(A,B),this}_handleError(A){let Q=A&&A.code;if(A&&Q!=="ENOENT"&&Q!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||Q!=="EPERM"&&Q!=="EACCES"))this.emit(ZB.ERROR,A);return A||this.closed}_throttle(A,Q,$){if(!this._throttled.has(A))this._throttled.set(A,new Map);let w=this._throttled.get(A);if(!w)throw Error("invalid throttle");let B=w.get(Q);if(B)return B.count++,!1;let X,Y=()=>{let H=w.get(Q),K=H?H.count:0;if(w.delete(Q),clearTimeout(X),H)clearTimeout(H.timeoutObject);return K};X=setTimeout(Y,$);let Z={timeoutObject:X,clear:Y,count:0};return w.set(Q,Z),Z}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(A,Q,$,w){let B=this.options.awaitWriteFinish;if(typeof B!=="object")return;let X=B.pollInterval,Y,Z=A;if(this.options.cwd&&!D8.isAbsolute(A))Z=D8.join(this.options.cwd,A);let H=new Date,K=this._pendingWrites;function U(G){xD$(Z,(D,q)=>{if(D||!K.has(A)){if(D&&D.code!=="ENOENT")w(D);return}let J=Number(new Date);if(G&&q.size!==G.size)K.get(A).lastChange=J;let F=K.get(A);if(J-F.lastChange>=Q)K.delete(A),w(void 0,q);else Y=setTimeout(U,X,q)})}if(!K.has(A))K.set(A,{lastChange:H,cancelWait:()=>{return K.delete(A),clearTimeout(Y),$}}),Y=setTimeout(U,X)}_isIgnored(A,Q){if(this.options.atomic&&yD$.test(A))return!0;if(!this._userIgnored){let{cwd:$}=this.options,B=(this.options.ignored||[]).map(bM2($)),Y=[...[...this._ignoredPaths].map(bM2($)),...B];this._userIgnored=uD$(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new fM2(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=D8.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new OM2(Q,this._boundRemove));return this._watched.get(Q)}_hasReadPermissions(A){if(this.options.ignorePermissionErrors)return!0;return Boolean(Number(A.mode)&256)}_remove(A,Q,$){let w=D8.join(A,Q),B=D8.resolve(w);if($=$!=null?$:this._watched.has(w)||this._watched.has(B),!this._throttle("remove",w,100))return;if(!$&&this._watched.size===1)this.add(A,Q,!0);this._getWatchedDir(w).getChildren().forEach((G)=>this._remove(w,G));let Z=this._getWatchedDir(A),H=Z.has(Q);if(Z.remove(Q),this._symlinkPaths.has(B))this._symlinkPaths.delete(B);let K=w;if(this.options.cwd)K=D8.relative(this.options.cwd,w);if(this.options.awaitWriteFinish&&this._pendingWrites.has(K)){if(this._pendingWrites.get(K).cancelWait()===ZB.ADD)return}this._watched.delete(w),this._watched.delete(B);let U=$?ZB.UNLINK_DIR:ZB.UNLINK;if(H&&!this._isIgnored(w))this._emit(U,w);this._closePath(w)}_closePath(A){this._closeFile(A);let Q=D8.dirname(A);this._getWatchedDir(Q).remove(D8.basename(A))}_closeFile(A){let Q=this._closers.get(A);if(!Q)return;Q.forEach(($)=>$()),this._closers.delete(A)}_addPathCloser(A,Q){if(!Q)return;let $=this._closers.get(A);if(!$)$=[],this._closers.set(A,$);$.push(Q)}_readdirp(A,Q){if(this.closed)return;let $={type:ZB.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},w=qM2(A,$);return this._streams.add(w),w.once(FM2,()=>{w=void 0}),w.once(pUA,()=>{if(w)this._streams.delete(w),w=void 0}),w}}function dD$(A,Q={}){let $=new rUA(Q);return $.add(A),$}var xM2={watch:dD$,FSWatcher:rUA};c8();import{extname as nD$}from"path";var OP0=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function MT(A){let Q=nD$(A).toLowerCase();return OP0.includes(Q)}function RM2(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 oUA(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as rD$,relative as oD$,sep as vM2,join as sD$}from"path";function Kz(A,Q){return rD$(Q)?Q:sD$(A,Q)}function Gn(A,Q){let $=Kz(A,Q),w=oD$(A,$);return vM2==="/"?w:w.split(vM2).join("/")}function aD$(A,Q){if(!Gn(Q,A).startsWith("image/"))return!1;return MT(A)}function tD$(A,Q){if(Gn(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return aD$(A,Q)}class sUA{watcher;watchCallback;pendingChanges=new Map;delayScope;delayedBatches;clock;activeCallbacks=new Set;stopPromise=null;stopping=!1;syncPath;watchInterval;logger;onFileChange;constructor(A){this.syncPath=A.syncPath,this.watchInterval=A.watchInterval,this.logger=A.logger,this.onFileChange=A.onFileChange,this.clock=A.clock,this.delayScope=t0.runSync(j2.make()),this.delayedBatches=t0.runSync(j2.extend(Vw.make(),this.delayScope))}async start(){if(this.watcher){this.logger.debug("Already watching directory");return}if(this.stopping)throw Error("Cannot restart a stopped file watcher");this.logger.debug("Starting directory watch",{path:this.syncPath,interval:this.watchInterval});let A=xM2.watch(this.syncPath,{ignored:/(^|[/\\])\../,persistent:!0,interval:this.watchInterval,awaitWriteFinish:{stabilityThreshold:2000,pollInterval:100}});if(this.watcher=A,A.on("add",(Q)=>void this.handleFileChange("add",Q)).on("change",(Q)=>void this.handleFileChange("change",Q)).on("unlink",(Q)=>void this.handleFileChange("delete",Q)).on("error",(Q)=>this.logger.error("Watcher error",Q)),this.watchCallback)A.on("all",this.watchCallback);try{await this.awaitReady(A)}catch(Q){this.watcher=void 0;try{await A.close()}catch{}throw Q}}stop(){return this.stopping=!0,this.stopPromise??=this.stopWatcher(),this.stopPromise}async stopWatcher(){let A=this.watcher;this.watcher=void 0;let Q=this.closeDelayScope();this.pendingChanges.clear();let $=[Q,...A?[A.close()]:[],...this.activeCallbacks],B=(await Promise.allSettled($)).find((X)=>X.status==="rejected");if(A)this.logger.info("Stopped directory watch");if(B)throw B.reason}awaitReady(A){return new Promise((Q,$)=>{let w=()=>{A.off("error",B),Q()},B=(X)=>{A.off("ready",w),$(X)};A.once("ready",w),A.once("error",B)})}setCallback(A){if(this.watchCallback=A,this.watcher)this.watcher.on("all",A)}async handleFileChange(A,Q){if(this.stopping||!tD$(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let $=Gn(this.syncPath,Q);this.pendingChanges.set($,A);let w=t0.sleep(500).pipe(t0.andThen(t0.sync(()=>this.startPendingProcessing()))),B=this.clock?t0.withClock(w,this.clock):w;Vw.unsafeSet(this.delayedBatches,"file-change-batch",t0.runFork(B))}async processPendingChanges(){if(this.pendingChanges.size===0)return;let A=new Map(this.pendingChanges);this.pendingChanges.clear(),this.logger.debug("Processing batched file changes",{changeCount:A.size});for(let[Q,$]of A){let w=Kz(this.syncPath,Q);try{if(this.onFileChange)await this.onFileChange($,w)}catch(B){this.logger.error("Error processing file change",{path:Q,event:$,error:B})}}}startPendingProcessing(){if(this.stopping)return;let A=this.processPendingChanges();this.activeCallbacks.add(A),A.then(()=>this.activeCallbacks.delete(A),()=>this.activeCallbacks.delete(A))}async closeDelayScope(){let A=await t0.runPromiseExit(j2.close(this.delayScope,y2.void));if(y2.isFailure(A))throw a$.squash(A.cause)}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}async function CM2(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return eD$(Q)}async function hM2(A){await A?.stop()}function EM2(A,Q){if(A)A.setCallback(Q)}async function eD$(A){let{logger:Q,syncPath:$,watchInterval:w,importEntities:B,jobQueueCallback:X,fileOperations:Y,deleteOnFileRemoval:Z}=A,H=new yUA(Q,B,X,Y,Z),K=new sUA({syncPath:$,watchInterval:w,logger:Q,onFileChange:async(U,G)=>{await H.handleFileChange(U,G)}});return await K.start(),K}async function TM2(A){let Q=Date.now();A.logger.debug("Starting sync (import only)");let $=await A.importEntities(),w=await A.removeOrphanedEntities(),B=Date.now()-Q;return A.markSynced(new Date),A.logger.debug("Sync completed",{duration:B,imported:$.imported,orphansDeleted:w.deleted}),{export:{exported:0,failed:0,errors:[]},import:$,duration:B}}zA();class aUA{logger;syncPath;deleteOnFileRemoval;constructor(A){this.logger=A.logger,this.syncPath=A.syncPath,this.deleteOnFileRemoval=A.deleteOnFileRemoval}prepareBatchOperations(A){let Q=[],$=this.createImportOperations(A);Q.push(...$);let w=$.length;if(this.deleteOnFileRemoval)Q.push({type:"directory-cleanup",data:{}});let B=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:w,totalFiles:B}),{operations:Q,exportOperationsCount:0,importOperationsCount:w,totalFiles:B}}async queueSyncBatch(A,Q,$,w){let B=this.prepareBatchOperations($);if(B.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch(B.operations,{source:Q,rootJobId:w?.rootJobId??O4(),metadata:{progressToken:w?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:w?.pluginId??"directory-sync",interfaceType:w?.interfaceType,channelId:w?.channelId}}),operationCount:B.operations.length,exportOperationsCount:B.exportOperationsCount,importOperationsCount:B.importOperationsCount,totalFiles:B.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,$=[];for(let w=0;w<A.length;w+=Q){let B=A.slice(w,w+Q);$.push({type:"directory-import",data:{batchIndex:Math.floor(w/Q),paths:B,batchSize:B.length}})}return $}}class tUA{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new aUA({logger:A.logger,syncPath:A.syncPath,deleteOnFileRemoval:A.deleteOnFileRemoval})}async queueSyncBatch(A,Q,$){if(this.syncInProgress)return this.logger.debug("Sync already in progress, skipping",{source:Q}),null;this.syncInProgress=!0;try{let w=await this.fileOperations.getAllSyncFiles();return await this.batchOperationsManager.queueSyncBatch(A,Q,w,$)}finally{this.syncInProgress=!1}}}class eUA{options;constructor(A){this.options=A}createExportDeps(A,Q){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,deleteOnFileRemoval:A,entityTypes:Q}}createImportDeps(A){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,quarantine:this.options.quarantine,imageJobQueue:this.createImageJobQueueDeps(),entityTypes:A}}createCleanupDeps(A,Q){return{entityService:this.options.entityService,logger:this.options.logger,fileOperations:this.options.fileOperations,deleteOnFileRemoval:A,entityTypes:Q}}createImageJobQueueDeps(){return{logger:this.options.logger,syncPath:this.options.syncPath,jobQueueCallback:this.options.getJobQueueCallback(),coverImageConverter:this.options.coverImageConverter,inlineImageConverter:this.options.inlineImageConverter}}}import{basename as Xq$,dirname as Yq$,extname as Zq$}from"path";import{extname as Aq$}from"path";var fP0=[".pdf"],yM2=".meta.json";function kT(A){let Q=Aq$(A).toLowerCase();return fP0.includes(Q)}function gM2(A){return A.toLowerCase().endsWith(yM2)}function AGA(A){return`${A}${yM2}`}function SM2(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as Qq$,join as xP0}from"path";function RP0(A,Q){let w=Gn(A,Q).split("/"),B,X;if(w.length===1)B="note",X=w;else if(w.length>1&&w[0])B=w[0],X=w.slice(1);else B="note",X=w;let Y;if(X.length>1){let Z=X[X.length-1];if(Z)X[X.length-1]=mM2(Z);Y=X.join(":")}else Y=mM2(X[0]??"");return{entityType:B,id:Y}}function uM2(A,Q,$,w=".md"){let B=Q.split(":").filter((K)=>K.length>0),X=$==="note";if(B.length===1)return X?xP0(A,`${B[0]}${w}`):xP0(A,$,`${B[0]}${w}`);let Y=B;if(B[0]===$)Y=B.slice(1);let Z=Y[Y.length-1],H=Y.slice(0,-1);if(X)return xP0(A,...H,`${Z}${w}`);return xP0(A,$,...H,`${Z}${w}`)}function cM2(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return oUA(Q);let $=A.content.match(/^data:image\/([a-z+]+);base64,/i);return $?.[1]?oUA($[1]):".md"}function mM2(A){let Q=Qq$(A).toLowerCase();return Q===".md"||OP0.includes(Q)||fP0.includes(Q)?A.slice(0,-Q.length):A}h0();EZ();import{mkdir as Wq$,readFile as Dn,writeFile as $GA,stat as Hq$,utimes as Kq$}from"fs/promises";import{join as vP0}from"path";import{mkdir as pM2,readdir as wq$,stat as Bq$}from"fs/promises";import{access as $q$}from"fs/promises";async function D7(A){try{return await $q$(A),!0}catch{return!1}}async function QGA(A,Q){return nM2(A,Q,{includeDocuments:!1,includeImages:!1})}async function lM2(A,Q){return nM2(A,Q,{includeDocuments:!0,includeImages:!0})}async function iM2(A,Q){if(!await D7(A))await pM2(A,{recursive:!0});for(let $ of Q)if($!=="note")await pM2(vP0(A,$),{recursive:!0})}async function dM2(A,Q){let $=[],w={totalFiles:0,byEntityType:{}};if(!await D7(A))return{files:$,stats:w};let B=await QGA(A,Q);for(let X of B)try{let Y=vP0(A,X),Z=await Bq$(Y),{entityType:H}=RP0(A,X);$.push({path:X,entityType:H,modified:Z.mtime}),w.totalFiles++,w.byEntityType[H]=(w.byEntityType[H]??0)+1}catch{continue}return{files:$,stats:w}}async function nM2(A,Q,$){let w=[];if(!await D7(A))return w;let B=async(X,Y="",Z=!1,H=!1)=>{let K=await wq$(X,{withFileTypes:!0});for(let U of K){let G=Y?vP0(Y,U.name):U.name;if(U.isFile()&&!U.name.endsWith(".invalid")&&!gM2(U.name)){if(U.name.endsWith(".md"))w.push(G);else if($.includeImages&&Z&&MT(U.name))w.push(G);else if($.includeDocuments&&H&&kT(U.name))w.push(G)}else if(U.isDirectory()&&!U.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(U.name))continue;let D=vP0(X,U.name),q=U.name==="image"&&Y==="",J=U.name==="document"&&Y==="";await B(D,G,Z||q,H||J)}}};return await B(A),w}var Uq$=W.record(W.string(),W.unknown());class wGA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return RP0(this.syncPath,A)}async readEntity(A){let Q=Kz(this.syncPath,A),$=await Hq$(Q),{entityType:w,id:B}=this.parseEntityFromPath(A),X=$.birthtime.getTime()>0?$.birthtime:$.mtime,Y=$.mtime,Z,H;if(MT(A)||kT(A)){let G=(await Dn(Q)).toString("base64"),D=Zq$(A);if(Z=`data:${kT(A)?SM2(D):RM2(D)};base64,${G}`,kT(A))H=await this.readDocumentSidecar(Q,A)}else Z=await Dn(Q,"utf-8");let K={entityType:w,id:B,content:Z,created:X,updated:Y};if(H)K.metadata=H;return K}async readDocumentSidecar(A,Q){let $={mimeType:"application/pdf",filename:Xq$(Q)},w=AGA(A);if(!await D7(w))return $;try{let B=await Dn(w,"utf-8"),X=Uq$.safeParse(JSON.parse(B));return{...$,...X.success?X.data:{}}}catch{return $}}async writeEntity(A){let Q=this.getEntityFilePath(A),$=A.entityType==="image",w=A.entityType==="document";if($||w){let X=$?/^data:image\/[a-z+]+;base64,(.+)$/i:/^data:application\/pdf;base64,(.+)$/i,Y=A.content.match(X),Z=Y?.[1]?Buffer.from(Y[1],"base64"):Buffer.from(A.content,"base64"),H=!1;if(await D7(Q)){let K=await Dn(Q),U=u6(K.toString("base64")),G=u6(Z.toString("base64"));if(U===G)H=!0}if(!H)await this.ensureEntityDirectory(A,Q),await $GA(Q,Z);if(w)await this.writeDocumentSidecar(A,Q);if(H)return}else{let X=this.entityService.serializeEntity(A);if(await D7(Q)){let Y=await Dn(Q,"utf-8"),Z=u6(Y),H=u6(X);if(Z===H)return}await this.ensureEntityDirectory(A,Q),await $GA(Q,X,"utf-8")}let B=new Date(A.updated);await Kq$(Q,B,B)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await Wq$(Yq$(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let $=A.metadata,w={};for(let[Y,Z]of Object.entries($)){if(Y==="mimeType")continue;if(Z===void 0)continue;w[Y]=Z}let B=AGA(Q),X=`${JSON.stringify(w,null,2)}
5835
5835
  `;if(await D7(B)){if(await Dn(B,"utf-8")===X)return}await this.ensureEntityDirectory(A,B),await $GA(B,X,"utf-8")}getFilePath(A,Q,$=".md"){return uM2(this.syncPath,A,Q,$)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,cM2(A))}async getAllMarkdownFiles(){return QGA(this.syncPath,this.entityService)}async getAllSyncFiles(){return lM2(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await iM2(this.syncPath,A)}shouldUpdateEntity(A,Q){let $=u6(Q.content);return A.contentHash!==$}async gatherFileStatus(){return dM2(this.syncPath,this.entityService)}async syncDirectoryExists(){return D7(this.syncPath)}async fileExists(A){return D7(A)}}cZ();h0();u4();p2();cZ();async function CP0(A,Q,$,w){let{sourceUrl:B}=A,X=await Q.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}});if(X[0])return w.debug("Reusing existing image entity",{sourceUrl:B,imageId:X[0].id}),X[0].id;let Y=await $(B),{base64:Z}=Pk(Y),H=Yh(Z),K=bk(Z);if(!H||!K)throw Error("Could not detect image format or dimensions");let U=await Q.createEntity({entity:{id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:H,width:K.width,height:K.height,sourceUrl:B}}});return w.debug("Created image entity from URL",{sourceUrl:B,imageId:U.entityId}),U.entityId}var rM2=W.object({title:W.string(),slug:W.string().optional(),coverImageUrl:W.url(),coverImageId:W.string().optional(),coverImageAlt:W.string().optional()});class BGA{entityService;fetcher;logger;constructor(A,Q,$=Eq){this.entityService=A,this.fetcher=$,this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=t8(A)}catch{return null}let{frontmatter:$}=Q,w=rM2.safeParse($);if(!w.success)return null;if(w.data.coverImageId)return null;let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=w.data;if(!Xh(Y))return null;return{sourceUrl:Y,postTitle:B,postSlug:X??O1(B),customAlt:Z}}async convert(A){let Q;try{Q=t8(A)}catch(K){return this.logger.debug("Parse failed",{error:K}),{content:A,converted:!1}}let{frontmatter:$}=Q,w=rM2.safeParse($);if(!w.success)return{content:A,converted:!1};if(w.data.coverImageId)return{content:A,converted:!1};let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=w.data;if(!Xh(Y))return{content:A,converted:!1};let H={postTitle:B,postSlug:X??O1(B),sourceUrl:Y,customAlt:Z};try{let K=await this.createImageEntity(H),U={...$};return delete U.coverImageUrl,delete U.coverImageAlt,U.coverImageId=K,{content:MC(U,Q.content),converted:!0,imageId:K}}catch(K){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:eA(K)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:$,sourceUrl:w,customAlt:B}=A,X=`Cover image for ${Q}`;return CP0({id:`${$}-cover`,title:X,alt:B??X,sourceUrl:w},this.entityService,this.fetcher,this.logger)}}cZ();class X50{entityService;fetcher;logger;constructor(A,Q,$=Eq){this.entityService=A,this.fetcher=$,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let $=[],w=EAA(A);for(let B of w){if(!Xh(B.url))continue;if(B.url.startsWith("entity://"))continue;let X=this.reconstructMarkdown(B);$.push({sourceUrl:B.url,alt:B.alt,originalMarkdown:X,postSlug:Q})}return $}reconstructMarkdown(A){if(A.title)return`![${A.alt}](${A.url} "${A.title}")`;return`![${A.alt}](${A.url})`}async convert(A,Q){let $=this.detectInlineImages(A,Q);if($.length===0)return{content:A,converted:!1,convertedCount:0};let w=A,B=0,X=0;for(let Y of $)try{let Z=await this.createImageEntity(Y,X++),H=`![${Y.alt}](entity://image/${Z})`;w=w.replace(Y.originalMarkdown,H),B++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:Z})}catch(Z){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:eA(Z)})}return{content:w,converted:B>0,convertedCount:B}}async createImageEntity(A,Q){let{sourceUrl:$,alt:w,postSlug:B}=A;return CP0({id:`${B}-inline-${Q}`,title:w||`Inline image ${Q+1} for ${B}`,alt:w||"",sourceUrl:$},this.entityService,this.fetcher,this.logger)}}class XGA{logger;entityService;fileOperations;constructor(A,Q,$){this.logger=A,this.entityService=Q,this.fileOperations=$}async importEntitiesWithProgress(A,Q,$,w){this.logger.debug("Importing entities with progress reporting");let B={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},X=A??await this.fileOperations.getAllSyncFiles(),Y=X.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let Z=0;Z<Y;Z+=$){let H=X.slice(Z,Z+$),K=await w(H);B.imported+=K.imported,B.skipped+=K.skipped,B.failed+=K.failed,B.quarantined+=K.quarantined,B.errors.push(...K.errors),B.quarantinedFiles.push(...K.quarantinedFiles),B.jobIds.push(...K.jobIds);let U=Math.min(Z+$,Y),G=Math.round(U/Y*40);await Q.report({progress:G,message:`Imported ${U}/${Y} files`})}return B}async exportEntitiesWithProgress(A,Q,$,w){this.logger.debug("Exporting entities with progress reporting");let B=A??this.entityService.getEntityTypes();await Q.report({progress:50,message:`Starting export of ${B.length} entity types`});let X=await w(A);return await Q.report({progress:100,message:`Exported ${X.exported} entities`}),this.logger.debug("Export completed",X),X}}zA();import{rename as Gq$,appendFile as Dq$,readFile as qq$,writeFile as zq$,access as Vq$}from"fs/promises";import{join as oM2}from"path";class YGA{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return gD0(A)}async quarantineInvalidFile(A,Q,$,w){let B=w(A),X=`${B}.invalid`;try{await Gq$(B,X),$.quarantined++,$.quarantinedFiles.push(A);let Y=oM2(this.syncPath,".import-errors.log"),Z=new Date().toISOString(),H=eA(Q),K=`${Z} - ${A}: ${H}
5836
5836
  \u2192 ${A}.invalid
@@ -5859,7 +5859,7 @@ ${Uj2}</style></head><body>${aw0(A)}<main id="root" data-web-chat-root>Brain Cha
5859
5859
  *...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
5860
5860
  ## Getting Started
5861
5861
  `),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(`
5862
- `)}}zA();class Xb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:WDA,jobTypeName:"directory-export"});this.directorySync=$,this.operationStatus=w}async process(A,Q,$){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let w=Date.now();try{let B=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,$,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:B.exported,failed:B.failed,duration:Date.now()-w}),await this.operationStatus?.addExportResult(B),B}catch(B){throw this.logger.error("Directory export job failed",{jobId:Q,error:B}),await this.operationStatus?.recordIssue({kind:"export",message:B instanceof Error?B.message:"Directory export failed"}),B}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}zA();class Yb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:ZDA,jobTypeName:"directory-import"});this.directorySync=$,this.operationStatus=w}async process(A,Q,$){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let w=Date.now();try{let B=await this.directorySync.importEntitiesWithProgress(A.paths,$,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:B.imported,skipped:B.skipped,failed:B.failed,quarantined:B.quarantined,duration:Date.now()-w}),await this.operationStatus?.addImportResult(B),B}catch(B){throw this.logger.error("Directory import job failed",{jobId:Q,error:B}),await this.operationStatus?.recordIssue({kind:"import",message:B instanceof Error?B.message:"Directory import failed"}),B}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}zA();c8();var EJ$=300000,TJ$=500;async function Cx2(A){if(A.jobIds.length===0)return;let Q=A.maxWaitMs??EJ$,$=A.pollIntervalMs??TJ$;A.logger.debug(`Waiting for ${A.jobIds.length} import jobs to complete`);let w=t0.gen(function*(){let Y=yield*eW.currentTimeMillis;yield*t0.gen(function*(){let K=(yield*t0.tryPromise({try:()=>Promise.all(A.jobIds.map((D)=>A.entityService.getAsyncJobStatus(D))),catch:(D)=>D})).filter((D)=>D&&(D.status==="completed"||D.status==="failed")).length;if(K===A.jobIds.length)return A.logger.debug("All import jobs completed"),!0;if((yield*eW.currentTimeMillis)-Y>Q)return A.logger.warn(`Timeout waiting for import jobs (${K}/${A.jobIds.length} completed)`),!0;let G=Math.round(K/A.jobIds.length*100);return yield*t0.tryPromise({try:()=>A.reporter.report({progress:50+Math.round(G*0.05),message:`Processing ${K}/${A.jobIds.length} entities`}),catch:(D)=>D}),!1}).pipe(t0.repeat({schedule:Lq.spaced($),until:(H)=>H}))}),B=A.clock?t0.withClock(w,A.clock):w,X=await t0.runPromiseExit(B);if(y2.isFailure(X))throw a$.squash(X.cause)}class Zb0 extends H8{getDirectorySync;context;constructor(A,Q,$){super(A,{schema:XDA,jobTypeName:"directory-sync"});this.context=Q,this.getDirectorySync=$}async process(A,Q,$){let w=Date.now(),B=A.syncDirection??"both",X=this.getDirectorySync();this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:B});let Y={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Z={exported:0,failed:0,errors:[]};if(B!=="export")if(await $.report({progress:10,message:"Scanning directory for changes"}),Y=await this.importWithProgress(X,A.paths,$),B==="import")await this.waitForImportJobs(Y.jobIds,$),await $.report({progress:100,message:`Import complete: ${Y.imported} imported`});else await $.report({progress:50,message:`Imported ${Y.imported} entities`}),await this.waitForImportJobs(Y.jobIds,$),await $.report({progress:56,message:"Processing complete, starting export"});if(B!=="import"){let K=B==="export"?10:60;await $.report({progress:K,message:"Exporting entities to directory"}),Z=await this.exportWithProgress(X,A.entityTypes,$),await $.report({progress:100,message:B==="export"?`Export complete: ${Z.exported} exported`:`Sync complete: ${Y.imported} imported, ${Z.exported} exported`})}let H=Date.now()-w;return this.logger.info("Directory sync job completed",{jobId:Q,duration:H,imported:Y.imported,exported:Z.exported}),{import:Y,export:Z,duration:H}}async importWithProgress(A,Q,$){try{return await A.importEntitiesWithProgress(Q,$,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q,$){try{return await A.exportEntitiesWithProgress(Q,$,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}waitForImportJobs(A,Q){return Cx2({jobIds:A,entityService:this.context.entityService,reporter:Q,logger:this.logger})}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}zA();class Wb0 extends H8{context;getDirectorySync;getGitSync;constructor(A,Q,$,w){super(A,{schema:YDA,jobTypeName:"sync-request"});this.context=Q,this.getDirectorySync=$,this.getGitSync=w}async process(A,Q,$){await $.report({progress:5,message:"Pulling latest content from git"});let w=this.getDirectorySync(),B=this.getGitSync(),X=await B.withLock(async()=>{return await B.pull(),await $.report({progress:35,message:"Scanning pulled content for sync changes"}),w.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!X)return await $.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await $.report({progress:100,message:`Sync queued: ${X.importOperationsCount} import jobs for ${X.totalFiles} files`}),yJ$(X)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function yJ$(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}zA();class Hb0 extends H8{context;constructor(A,Q,$){super(A,{schema:wb0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,$){let w=wb0.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}),await $.report({progress:0,total:1,message:`Deleting ${w.entityType}:${w.entityId}`});try{let B=await this.context.entityService.deleteEntity({entityType:w.entityType,id:w.entityId});if(B)this.logger.info("Successfully deleted entity for removed file",{entityId:w.entityId,entityType:w.entityType});else this.logger.warn("Entity not found in database",{entityId:w.entityId,entityType:w.entityType});return await $.report({progress:1,total:1,message:`Deleted ${w.entityType}:${w.entityId}`}),{deleted:B,entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}}catch(B){throw this.logger.error("Failed to delete entity",{entityId:w.entityId,entityType:w.entityType,error:B}),B}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}zA();h0();var gJ$=W.object({});class Kb0 extends H8{directorySync;constructor(A,Q){super(A,{schema:gJ$,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,$){await $.report({progress:0,message:"Removing orphaned entities"});let w=await this.directorySync.removeOrphanedEntities();return await $.report({progress:100,message:`Cleanup complete: ${w.deleted} orphans removed`}),w}}zA();cZ();u4();Uw();h0();cZ();import{readFile as SJ$,writeFile as mJ$}from"fs/promises";var uJ$=HDA,cJ$=W.record(W.string(),W.unknown());class Ub0 extends H8{context;fetcher;constructor(A,Q,$=Eq){super(Q,{schema:uJ$,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=$}async process(A,Q,$){let{filePath:w,sourceUrl:B,postTitle:X,postSlug:Y,customAlt:Z}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:w,sourceUrl:B,postSlug:Y});try{await this.reportProgress($,{progress:g6.INIT,message:`Reading file: ${w}`});let H;try{H=await SJ$(w,"utf-8")}catch(L){return this.logger.error("Failed to read file",{filePath:w,error:eA(L)}),o5.failure(L)}let K;try{K=t8(H)}catch(L){return this.logger.warn("Failed to parse markdown",{filePath:w,error:eA(L)}),o5.failure(L)}let U=cJ$.safeParse(K.frontmatter),G=U.success?U.data:{};if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress($,{progress:g6.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),q;if(D[0])q=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:q}),await this.reportProgress($,{progress:g6.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress($,{progress:g6.PROCESS,message:`Fetching image from ${B}`});let L;try{L=await this.fetcher(B)}catch(R){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:eA(R)}),o5.failure(R)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let{base64:_}=Pk(L),j=Yh(_),b=bk(_);if(!j||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),o5.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let f=`Cover image for ${X}`,v=Z??f;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:L,metadata:{title:f,alt:v,format:j,width:b.width,height:b.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:B}),await this.reportProgress($,{progress:g6.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress($,{progress:g6.SAVE,message:"Updating file"});let J={...G};delete J.coverImageUrl,delete J.coverImageAlt,J.coverImageId=q;let F=MC(J,K.content);try{await mJ$(w,F,"utf-8")}catch(L){return this.logger.error("Failed to write file",{filePath:w,error:eA(L)}),o5.failure(L)}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:w,imageId:q,sourceUrl:B}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:w,error:eA(H)}),o5.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}zA();cZ();Uw();import{readFile as pJ$,writeFile as lJ$}from"fs/promises";class Gb0 extends H8{converter;constructor(A,Q,$=Eq){super(Q,{schema:KDA,jobTypeName:"inline-image-convert"});this.converter=new X50(A.entityService,Q,$)}async process(A,Q,$){let{filePath:w,postSlug:B}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:w,postSlug:B});try{await this.reportProgress($,{progress:g6.INIT,message:`Reading file: ${w}`});let X;try{X=await pJ$(w,"utf-8")}catch(H){let K=eA(H);return this.logger.error("Failed to read file",{filePath:w,error:K}),{success:!1,error:K}}await this.reportProgress($,{progress:g6.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(X,B);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:w,count:Y.length}),await this.reportProgress($,{progress:g6.PROCESS,message:`Converting ${Y.length} images`});let Z=await this.converter.convert(X,B);if(!Z.converted)return this.logger.debug("No images were converted",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress($,{progress:g6.SAVE,message:"Writing updated file"});try{await lJ$(w,Z.content,"utf-8")}catch(H){let K=eA(H);return this.logger.error("Failed to write file",{filePath:w,error:K}),{success:!1,error:K}}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:w,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=eA(X);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:w,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function hx2(A,Q,$,w=()=>Q,B){let X=(Y)=>$.child(Y);A.jobs.registerHandler("directory-sync",new Zb0(X("DirectorySyncJobHandler"),A,w)),A.jobs.registerHandler("directory-export",new Xb0(X("DirectoryExportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-import",new Yb0(X("DirectoryImportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-delete",new Hb0(X("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new Kb0(X("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Ub0(A,X("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Gb0(A,X("InlineImageConversionJobHandler"))),$.debug("Registered async job handlers")}zA();h0();import{unlink as iJ$,access as dJ$}from"fs/promises";var nJ$=W.record(W.string(),W.unknown());function Ex2(A,Q,$,w,B){let{subscribe:X}=A.messaging,{entityService:Y}=A;X("entity:created",async(Z)=>{let{entity:H}=Z.payload;try{await Q().fileOps.writeEntity(H),$.debug("Auto-exported created entity",{id:H.id,entityType:H.entityType}),await B?.clearIssues(["export"])}catch(K){$.error("Auto-export FAILED for created entity",{id:H.id,entityType:H.entityType,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0}),await B?.recordIssue({kind:"export",path:`${H.entityType}/${H.id}.md`,message:K instanceof Error?K.message:"Entity export failed"})}return{success:!0}}),X("entity:updated",async(Z)=>{let{entityType:H,entityId:K}=Z.payload;try{let U=await Y.getEntity({entityType:H,id:K});if(!U)return $.debug("Entity not found in DB, skipping export",{entityType:H,entityId:K}),{success:!1};await Q().fileOps.writeEntity(U),$.debug("Auto-exported updated entity",{id:U.id,entityType:U.entityType}),await B?.clearIssues(["export"])}catch(U){$.error("Auto-export FAILED for updated entity",{entityType:H,entityId:K,error:U instanceof Error?U.message:String(U),stack:U instanceof Error?U.stack:void 0}),await B?.recordIssue({kind:"export",path:`${H}/${K}.md`,message:U instanceof Error?U.message:"Entity export failed"})}return{success:!0}}),X("entity:deleted",async(Z)=>{let{entityId:H,entityType:K}=Z.payload,U=Q().fileOps.getFilePath(H,K);if(await dJ$(U).then(()=>!0,()=>!1))await iJ$(U),$.debug("Auto-deleted entity file",{id:H,entityType:K,path:U});return{success:!0}}),$.debug("Setup auto-sync for entity events",{entityTypes:w})}function UDA(A,Q,$,w){Q.setJobQueueCallback(async(B)=>{let X=await w?.startRun("watcher","importing"),Y=[{type:B.type,data:nJ$.parse(B.data)}];try{let Z=await A.jobs.enqueueBatch(Y,{priority:5,source:"directory-sync-watcher",rootJobId:O4(),metadata:{operationType:"file_operations",operationTarget:$,pluginId:"directory-sync"}});if(X)await w?.attachBatch(X,Z);return Z}catch(Z){if(X)await w?.failRun(X,Z instanceof Error?Z.message:"Watcher import failed","import");throw Z}})}zA();import{readdir as gx2,mkdir as oJ$,copyFile as sJ$}from"fs/promises";import{join as yx2,resolve as GDA}from"path";import{join as rJ$}from"path";async function Tx2(A){if(!await D7(rJ$(A,".git")))return!1;try{return await kV(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function aJ$(A,Q){if(!await D7(A))return!0;if((await gx2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await Tx2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function Sx2(A,Q){let $=await gx2(A,{withFileTypes:!0});for(let w of $){let B=yx2(A,w.name),X=yx2(Q,w.name);if(w.isDirectory()){if(!await D7(X))await oJ$(X,{recursive:!0});await Sx2(B,X)}else await sJ$(B,X)}}async function mx2(A,Q,$){let w=GDA(process.cwd(),A);$=$?GDA($):GDA(process.cwd(),"seed-content");let B=await aJ$(w,Q);if(B&&await D7($))Q.debug("Copying seed content to brain-data directory"),await Sx2($,w),Q.debug("Seed content copied successfully");else if(B)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function ux2(A,Q,$,w,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if($.seedContent){let H=$.syncPath??A.dataDir;await mx2(H,w,$.seedContentPath)}try{if(B){w.debug("Git enabled \u2014 pulling before import");let K=await B.pull();if(K.files.length>0)w.info("Pulled changes from remote",{filesChanged:K.files.length})}w.debug("Starting initial sync");let H=await Z.sync();w.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:xC.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){w.error("Initial sync failed",H),await A.messaging.send({type:xC.initialSyncCompleted,payload:{success:!1,error:eA(H)},...{broadcast:!0}})}};A.messaging.subscribe(xC.pluginsRegistered,async()=>{return w.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}function cx2(A,Q,$,w,B,X){let Y=typeof Q==="function"?Q:()=>Q,Z=async()=>{let K=Y();try{await K.withLock(async()=>{await K.commit(),await K.push()}),await X?.clearIssues(["git"]),await X?.recordTerminal("save","succeeded","Local content committed and pushed")}catch(U){w.error("Git auto-commit failed",{error:U});let G=U instanceof Error?U.message:"Git auto-commit failed";await X?.recordIssue({kind:"git",message:G}),await X?.recordTerminal("save","failed",G)}},H=["entity:created","entity:updated","entity:deleted"];for(let K of H)A.subscribe(K,async()=>{return B.scheduleTrailing("git-auto-commit",$,Z),{success:!0}})}function px2(A,Q,$,w,B,X,Y){if(w<=0)return;let Z=w*60*1000,H=async(K)=>{let U=await Y?.startRun("periodic","pulling");try{let{files:G,result:D}=await A.withLock(async()=>{let q=await A.pull(K);if(K.throwIfAborted(),q.files.length===0)return{files:[],result:null};let J=await Q.queueSyncBatch($,"periodic-sync");return{files:q.files,result:J}},K);if(G.length>0)B.info("Periodic sync: pulled changes",{filesChanged:G.length});if(D){if(B.debug("Periodic sync: queued imports",{importOperations:D.importOperationsCount,totalFiles:D.totalFiles}),U)await Y?.attachBatch(U,D.batchId)}else if(U)await Y?.completeRun(U,G.length===0?"Remote checked; no changes found":"Remote changes required no imports")}catch(G){if(K.aborted){if(U)await Y?.clearRun(U)}else if(B.error("Periodic git sync failed",{error:G}),U)await Y?.failRun(U,G instanceof Error?G.message:"Periodic Git sync failed")}};X.schedulePeriodic(Z,H),B.info("Started periodic git sync",{intervalMinutes:w})}import{spawnSync as ix2}from"child_process";import{cpSync as tJ$,existsSync as lx2,mkdirSync as eJ$,mkdtempSync as AF$,rmSync as QF$}from"fs";import{tmpdir as $F$}from"os";import{fileURLToPath as wF$}from"url";import{join as BF$,resolve as XF$}from"path";function Pf(A,Q){let $=ix2("git",Q,{cwd:A,stdio:"pipe"});if($.status!==0){let w=$.stderr.toString().trim(),B=$.stdout.toString().trim();throw Error(w||B||`git ${Q.join(" ")} failed`)}}function YF$(A){return A.startsWith("file://")}function ZF$(A){return wF$(A)}function WF$(A,Q){return ix2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function dx2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!YF$(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",$=ZF$(A.gitUrl),w=XF$(A.seedContentPath);if(!lx2(w))throw Error(`Seed content path not found: ${w}`);if(!lx2($))A.logger.debug("Creating local bare content remote",{remotePath:$,branch:Q}),eJ$($,{recursive:!0}),Pf(process.cwd(),["init","--bare",`--initial-branch=${Q}`,$]);if(WF$($,Q)){A.logger.debug("Content remote already initialized",{remotePath:$,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:$,seedPath:w,branch:Q});let B=AF$(BF$($F$(),"directory-sync-seed-"));try{Pf(B,["init",`--initial-branch=${Q}`]),Pf(B,["config","user.name",A.authorName??"Brain"]),Pf(B,["config","user.email",A.authorEmail??"brain@localhost"]),tJ$(w,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),Pf(B,["add","."]),Pf(B,["commit","-m","seed content remote"]),Pf(B,["remote","add","origin",A.gitUrl]),Pf(B,["push","-u","origin",Q])}finally{QF$(B,{recursive:!0,force:!0})}}function nx2(A,Q,$,w,B,X,Y){let{subscribe:Z}=A.messaging;Z("entity:export:request",async(H)=>{try{return{success:!0,data:await Q().exportEntities(H.payload.entityTypes)}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Export failed"}}}),Z("entity:import:request",async(H)=>{try{let K=Q(),U=H.payload.paths,G=await K.importEntities(U);if(U&&U.length>0)await K.removeOrphanedEntities();return{success:!0,data:G}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Import failed"}}}),Z("sync:status:request",async()=>{try{let K=await Q().getStatus(),U=Y?.();return{success:!0,data:{syncPath:K.syncPath,isInitialized:K.exists,watchEnabled:K.watching,lastSync:K.lastSync?.toISOString()??null,totalFiles:K.stats.totalFiles,byEntityType:K.stats.byEntityType,git:await HF$(X?.(),w),...U?{managementUrl:U}:{}}}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Status check failed"}}}),Z("sync:configure:request",async(H)=>{try{return await $({syncPath:H.payload.syncPath}),{success:!0,data:{syncPath:H.payload.syncPath,configured:!0}}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Configuration failed"}}}),Z("git-sync:get-repo-info",async()=>{if(!B?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:B.repo,branch:B.branch??"main"}}}),w.debug("Registered message handlers")}async function HF$(A,Q){if(!A)return null;try{let $=await A.getStatus();return{branch:$.branch,hasChanges:$.hasChanges,ahead:$.ahead,behind:$.behind,lastCommit:$.lastCommit??null,remote:$.remote??null}}catch($){return Q.debug("Git status unavailable for sync:status:request",{error:$}),null}}zA();h0();async function Db0(A){let Q=await A.operationStatus?.startRun("manual",A.gitSync?"pulling":"scanning");try{if(A.gitSync){let w=await A.context.jobs.enqueue({type:"sync-request",data:{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId},...A.toolContext?{toolContext:A.toolContext}:{}});if(Q)await A.operationStatus?.attachJob(Q,w);return{...Q?{runId:Q}:{},gitPulled:!0,jobId:w,status:"queued"}}let $=await A.directorySync.queueSyncBatch(A.context,A.source,{interfaceType:A.interfaceType,channelId:A.channelId});if(!$){if(Q)await A.operationStatus?.completeRun(Q,"No files to sync");return{...Q?{runId:Q}:{},gitPulled:!1,status:"settled"}}if(Q)await A.operationStatus?.attachBatch(Q,$.batchId);return{...Q?{runId:Q}:{},...$,gitPulled:!1,status:"queued"}}catch($){if(Q)await A.operationStatus?.failRun(Q,$ instanceof Error?$.message:"Sync request failed",A.gitSync?"git":"source");throw $}}zA();h0();function rx2(A,Q){return e8(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",W.object({entityType:W.string().describe("Entity type (e.g. post, note, link)"),id:W.string().describe("Entity ID"),sha:W.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:W.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async($)=>{let w=`${$.entityType}/${$.id}.md`;try{if($.sha){let X=await Q.show($.sha,w);return d7({sha:$.sha,entityType:$.entityType,id:$.id,content:X},`Content at ${$.sha.slice(0,7)}`)}let B=await Q.log(w,$.limit);if(B.length===0)return d7({commits:[]},`No history found for ${$.entityType}/${$.id}`);return d7({commits:B,entityType:$.entityType,id:$.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return jY(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function ox2(A,Q,$,w,B){let X=[e8($,"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.",W.object({}),async(Y,Z)=>{try{let H=Z.channelId?`${Z.interfaceType}:${Z.channelId}`:`plugin:${$}`,K=await Db0({context:Q,directorySync:A,source:H,interfaceType:Z.interfaceType,channelId:Z.channelId,toolContext:Z,gitSync:w,operationStatus:B});if(K.gitPulled)return d7({jobId:K.jobId,status:K.status,gitPulled:!0,...K.runId?{runId:K.runId}:{}},"Sync queued: git pull and filesystem scan will run in the background");if(K.status==="settled")return d7({gitPulled:!1,...K.runId?{runId:K.runId}:{}},"No files to sync");return d7({batchId:K.batchId,importOperations:K.importOperationsCount,totalFiles:K.totalFiles,gitPulled:!1,...K.runId?{runId:K.runId}:{}},`Sync started: ${K.importOperationsCount} import jobs queued for ${K.totalFiles} files`)}catch(H){return jY(H instanceof Error?H.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),e8($,"status","Read directory and git sync status: last sync, watcher state, and pending git changes. Use this for every status follow-up after directory-sync_sync, even when that call returned a jobId; a sync jobId is not a system_job_status batchId.",W.object({}),async()=>{try{let Y=await A.getStatus(),Z={syncPath:Y.syncPath,lastSync:Y.lastSync?.toISOString(),watching:Y.watching};if(w){let H=await w.getStatus();Z.git={isRepo:H.isRepo,branch:H.branch,hasChanges:H.hasChanges,ahead:H.ahead,behind:H.behind,remote:H.remote}}return d7(Z)}catch(Y){return jY(Y instanceof Error?Y.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(w)X.push(rx2($,w));return X}zA();h0();import{isAbsolute as sx2,relative as KF$}from"path";var QR2=W.enum(["manual","periodic","watcher","save"]),UF$=W.enum(["pulling","scanning","importing","settling"]),$R2={imported:W.number().int().nonnegative(),skipped:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),quarantined:W.number().int().nonnegative(),exported:W.number().int().nonnegative()},GF$=W.object({id:W.string().min(1),source:QR2,state:UF$,startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...$R2}),DF$=W.object({id:W.string().min(1),source:QR2,outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1).max(240),...$R2}),qF$=W.object({id:W.string().min(1),kind:W.enum(["quarantined","import","export","git","source"]),path:W.string().min(1).max(300).optional(),message:W.string().min(1).max(400),occurredAt:W.string().datetime()}),ax2=W.object({activeRun:GF$.optional(),recentRuns:W.array(DF$).max(5),issues:W.array(qF$).max(8)}),zF$=W.object({gitPulled:W.literal(!0),batchQueued:W.boolean(),batchId:W.string().optional(),importOperations:W.number().int().nonnegative().optional(),totalFiles:W.number().int().nonnegative().optional()}),tx2={imported:0,skipped:0,failed:0,quarantined:0,exported:0},VF$={recentRuns:[],issues:[]},JF$="directory-sync.operation-status",ex2="current";class DDA{store;jobs;logger;syncPath;statePromise;writeQueue=Promise.resolve();constructor(A,Q,$,w){this.store=A.scoped({namespace:JF$,schema:ax2}),this.jobs=Q,this.logger=$,this.syncPath=w}setSyncPath(A){this.syncPath=A}async initialize(){let A=await this.load();if(A.activeRun&&!A.activeRun.jobId&&!A.activeRun.batchId){await this.clearRun(A.activeRun.id);return}await this.reconcile()}startRun(A,Q){let $=O4();return this.mutate((w)=>{if(w.activeRun)return;return w.activeRun={id:$,source:A,state:Q,startedAt:new Date().toISOString(),...tx2},$})}markPhase(A,Q){return this.mutate(($)=>{if($.activeRun?.id===A)$.activeRun.state=Q})}attachJob(A,Q){return this.mutate(($)=>{if($.activeRun?.id!==A)return;$.activeRun.jobId=Q,$.activeRun.state="pulling"})}attachBatch(A,Q){return this.mutate(($)=>{if($.activeRun?.id!==A)return;delete $.activeRun.jobId,$.activeRun.batchId=Q,$.activeRun.state="importing"})}addImportResult(A){return this.mutate((Q)=>{if(Q.activeRun)Q.activeRun.imported+=A.imported,Q.activeRun.skipped+=A.skipped,Q.activeRun.failed+=A.failed,Q.activeRun.quarantined+=A.quarantined;let $=[...A.errors.map((w)=>({kind:"import",path:this.safePath(w.path),message:w.error})),...A.quarantinedFiles.map((w)=>({kind:"quarantined",path:this.safePath(w),message:"File was quarantined because it could not be imported"}))];if($.length===0)Q.issues=Q.issues.filter((w)=>w.kind!=="import"&&w.kind!=="quarantined");else for(let w of $)this.prependIssue(Q,w)})}addExportResult(A){return this.mutate((Q)=>{if(Q.activeRun)Q.activeRun.exported+=A.exported,Q.activeRun.failed+=A.failed;if(A.errors.length===0){Q.issues=Q.issues.filter(($)=>$.kind!=="export");return}for(let $ of A.errors)this.prependIssue(Q,{kind:"export",path:`${$.entityType}/${$.entityId}.md`,message:$.error})})}recordIssue(A){return this.mutate((Q)=>this.prependIssue(Q,A))}clearIssues(A){return this.mutate((Q)=>{Q.issues=Q.issues.filter(($)=>!A.includes($.kind))})}completeRun(A,Q){return this.finishRun(A,"succeeded",Q)}clearRun(A){return this.mutate((Q)=>{if(Q.activeRun?.id===A)delete Q.activeRun})}failRun(A,Q,$="git"){return this.mutate((w)=>{let B=w.activeRun;if(B?.id!==A)return;let X=qb0(Q);this.prependRecent(w,B,"failed",X),this.prependIssue(w,{kind:$,message:X}),delete w.activeRun})}recordTerminal(A,Q,$,w={}){return this.mutate((B)=>{let X=new Date().toISOString();this.prependRecent(B,{id:O4(),source:A,state:"settling",startedAt:X,...tx2,...w},Q,$)})}async reconcile(){await this.writeQueue;let A=await this.load(),Q=A.activeRun?{...A.activeRun}:void 0;if(!Q)return;try{if(Q.jobId){let $=await this.jobs.getStatus(Q.jobId);if(!$){await this.failRun(Q.id,"The active sync job could not be found after restart","source");return}if($.status==="pending"||$.status==="processing"){await this.markPhase(Q.id,"pulling");return}if($.status==="failed"){await this.failRun(Q.id,$.lastError??"Git-backed sync failed");return}let w=zF$.safeParse(FF$($.result));if(!w.success){await this.failRun(Q.id,"Sync job completed without a readable result","source");return}if(w.data.batchQueued&&w.data.batchId)return await this.attachBatch(Q.id,w.data.batchId),await this.reconcile();await this.completeRun(Q.id,"Remote checked; no files to import");return}if(Q.batchId){let $=await this.jobs.getBatchStatus(Q.batchId);if(!$){await this.failRun(Q.id,"The active sync batch could not be recovered after restart","source");return}if($.status==="pending"||$.status==="processing"){await this.markPhase(Q.id,"importing");return}if($.status==="failed"){await this.failRun(Q.id,$.errors.join("; ")||"Directory import batch failed","import");return}await this.completeRun(Q.id,`${$.completedOperations} sync operations completed`)}}catch($){this.logger.debug("Unable to reconcile directory sync operation",{error:$})}}async getSnapshot(){await this.reconcile(),await this.writeQueue;let A=await this.load();return structuredClone(A)}finishRun(A,Q,$){return this.mutate((w)=>{let B=w.activeRun;if(B?.id!==A)return;let X=B.failed>0||B.quarantined>0?"attention":Q;if(this.prependRecent(w,B,X,$),delete w.activeRun,X==="succeeded")w.issues=w.issues.filter((Y)=>Y.kind!=="git"&&Y.kind!=="source")})}load(){return this.statePromise??=this.store.get(ex2).then((A)=>A??structuredClone(VF$)),this.statePromise}mutate(A){let Q=this.writeQueue.then(async()=>{let $=await this.load(),w=A($);return await this.persist($),w});return this.writeQueue=Q.then(()=>{return},()=>{return}),Q}persist(A){return this.store.set(ex2,ax2.parse(A))}prependRecent(A,Q,$,w){let B={id:Q.id,source:Q.source,outcome:$,startedAt:Q.startedAt,completedAt:new Date().toISOString(),summary:qb0(w,240),imported:Q.imported,skipped:Q.skipped,failed:Q.failed,quarantined:Q.quarantined,exported:Q.exported};A.recentRuns=[B,...A.recentRuns.filter((X)=>X.id!==B.id)].slice(0,5)}prependIssue(A,Q){let $=Q.path?this.safePath(Q.path):void 0,w={id:`${Q.kind}:${$??qb0(Q.message,80)}`,kind:Q.kind,...$?{path:$}:{},message:qb0(Q.message),occurredAt:new Date().toISOString()};A.issues=[w,...A.issues.filter((B)=>B.id!==w.id)].slice(0,8)}safePath(A){if(!sx2(A))return AR2(A);let Q=KF$(this.syncPath,A);if(Q.startsWith("..")||sx2(Q))return"content file";return AR2(Q)}}function FF$(A){if(typeof A!=="string")return A;try{return JSON.parse(A)}catch{return A}}function AR2(A){return A.replaceAll("\\","/").replace(/^\.\//,"").slice(0,300)||"content file"}function qb0(A,Q=400){return A.replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,"$1[redacted]@").replace(/(token|password|authorization)=([^\s&]+)/gi,"$1=[redacted]").replace(/\s+/g," ").trim().slice(0,Q)||"Directory sync operation failed"}zA();h0();import{basename as LF$}from"path";var IF$=W.object({workspaceUrl:W.string()}),NF$=W.object({type:W.literal("sync-now")}),wR2={imported:W.number().int().nonnegative(),skipped:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),quarantined:W.number().int().nonnegative(),exported:W.number().int().nonnegative()},_F$=W.object({health:W.enum(["healthy","active","attention"]),directory:W.object({displayPath:W.string().min(1),exists:W.boolean(),watching:W.boolean(),totalFiles:W.number().int().nonnegative(),byEntityType:W.record(W.string(),W.number().int().nonnegative()),lastSettledAt:W.string().datetime().optional()}),git:W.object({branch:W.string().min(1),remoteLabel:W.string().min(1).optional(),hasChanges:W.boolean(),ahead:W.number().int().nonnegative(),behind:W.number().int().nonnegative(),lastCommit:W.string().min(1).optional(),changedFiles:W.array(W.object({path:W.string().min(1),status:W.string().min(1)})),changedFilesTruncated:W.boolean()}).nullable(),automation:W.object({autoSync:W.boolean(),watchIntervalMs:W.number().int().nonnegative(),remoteIntervalMinutes:W.number().nonnegative().optional(),commitDebounceMs:W.number().int().nonnegative().optional(),deleteOnFileRemoval:W.boolean()}),activeRun:W.object({id:W.string().min(1),source:W.enum(["manual","periodic","watcher","save"]),state:W.enum(["pulling","scanning","importing","settling"]),startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...wR2}).optional(),recentRuns:W.array(W.object({id:W.string().min(1),source:W.enum(["manual","periodic","watcher","save"]),outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1),...wR2})),issues:W.array(W.object({id:W.string().min(1),kind:W.enum(["quarantined","import","export","git","source"]),path:W.string().min(1).optional(),message:W.string().min(1),occurredAt:W.string().datetime()}))});class qDA{options;constructor(A){this.options=A}async getSnapshot(){let A=await this.options.getDirectorySync().getStatus();this.options.operationStatus.setSyncPath(A.syncPath);let Q,$=this.options.getGitSync();if($)try{if(Q=await $.getStatus(),!Q.hasChanges&&Q.ahead===0&&Q.behind===0)await this.options.operationStatus.clearIssues(["git"])}catch(Y){await this.options.operationStatus.recordIssue({kind:"git",message:Y instanceof Error?Y.message:"Git status unavailable"})}if(!A.exists)await this.options.operationStatus.recordIssue({kind:"source",message:"The configured sync directory is unavailable"});else await this.options.operationStatus.clearIssues(["source"]);let w=await this.options.operationStatus.getSnapshot(),B=w.recentRuns[0]?.completedAt??A.lastSync?.toISOString(),X=w.activeRun?"active":w.issues.length>0?"attention":"healthy";return _F$.parse({health:X,directory:{displayPath:LF$(A.syncPath)||"brain-data",exists:A.exists,watching:A.watching,totalFiles:A.stats.totalFiles,byEntityType:A.stats.byEntityType,...B?{lastSettledAt:B}:{}},git:Q?this.toSafeGitStatus(Q):null,automation:{autoSync:this.options.config.autoSync,watchIntervalMs:this.options.config.watchInterval,...$?{remoteIntervalMinutes:this.options.config.syncInterval,commitDebounceMs:this.options.config.commitDebounce}:{},deleteOnFileRemoval:this.options.config.deleteOnFileRemoval},...w.activeRun?{activeRun:w.activeRun}:{},recentRuns:w.recentRuns,issues:w.issues})}async registerCmsWorkspace(){let A={id:"sync",pluginId:this.options.pluginId,label:"Sync",rendererName:"DirectorySyncWorkspace",priority:60,dataProvider:()=>this.getSnapshot(),actionHandler:async(w,B)=>{if(!$9.hasPermission(B.userPermissionLevel,"anchor"))throw Error("Directory sync requires anchor permission");if(!NF$.safeParse(w).success)throw Error("Invalid directory sync workspace action");let Y={interfaceType:"cms",userId:B.userId,userPermissionLevel:B.userPermissionLevel},Z=await Db0({context:this.options.context,directorySync:this.options.getDirectorySync(),source:`cms:${B.userId}`,interfaceType:"cms",toolContext:Y,gitSync:this.options.getGitSync(),operationStatus:this.options.operationStatus});return{accepted:Z.status==="queued",status:Z.status,...Z.runId?{runId:Z.runId}:{},...Z.gitPulled?{jobId:Z.jobId}:{},...!Z.gitPulled&&Z.status==="queued"?{batchId:Z.batchId}:{}}}},Q=await this.options.context.messaging.send({type:v_,payload:A});if(!("success"in Q)||!Q.success)return;let $=IF$.safeParse(Q.data);return $.success?$.data.workspaceUrl:void 0}toSafeGitStatus(A){let Q=A.files.slice(0,20).map((w)=>({path:PF$(w.path),status:w.status.trim()||"changed"})),$=bF$(this.options.config);return{branch:A.branch,...$?{remoteLabel:$}:{},hasChanges:A.hasChanges,ahead:A.ahead,behind:A.behind,...A.lastCommit?{lastCommit:A.lastCommit}:{},changedFiles:Q,changedFilesTruncated:A.files.length>Q.length}}}function PF$(A){let Q=A.replaceAll("\\","/").replace(/^\.\//,"");if(Q.startsWith("../")||Q.startsWith("/"))return"content file";return Q.slice(0,300)||"content file"}function bF$(A){if(A.git?.repo)return A.git.repo;let Q=A.git?.gitUrl;if(!Q)return;if(Q.startsWith("file:"))return"local remote";try{let $=new URL(Q),w=$.pathname.replace(/^\//,"").replace(/\.git$/,"");return w?`${$.hostname}/${w}`:$.hostname}catch{let $=/^(?:[^@]+@)?([^:]+):(.+?)(?:\.git)?$/.exec(Q);if(!$?.[1]||!$[2])return"configured remote";return`${$[1]}/${$[2].replace(/\.git$/,"")}`}}c8();class zb0{resourceScope;scheduleScope;periodicScope;delayScope;scheduleFibers;periodicFibers;delayedFibers;clock;activeOperations=new Set;activeFailures=[];nextPeriodicId=0;closePromise=null;closed=!1;constructor(A={}){this.resourceScope=t0.runSync(j2.make()),this.scheduleScope=t0.runSync(j2.make()),this.periodicScope=t0.runSync(j2.make()),this.delayScope=t0.runSync(j2.make()),this.scheduleFibers=t0.runSync(j2.extend(RZ.make(),this.scheduleScope)),this.periodicFibers=t0.runSync(j2.extend(Vw.make(),this.periodicScope)),this.delayedFibers=t0.runSync(j2.extend(Vw.make(),this.delayScope)),this.clock=A.clock}async acquire(A,Q){if(this.closed)throw Error("Directory sync runtime is closed");let $=t0.acquireRelease(t0.promise(A),(B)=>t0.promise(()=>Q(B))),w=await t0.runPromiseExit(j2.extend($,this.resourceScope));if(y2.isFailure(w))throw a$.squash(w.cause);return w.value}schedulePeriodic(A,Q){if(this.closed)return;if(!Number.isFinite(A)||A<=0)throw Error("Periodic interval must be a positive finite number");let $=this.nextPeriodicId++,w=()=>{if(this.closed||Vw.unsafeHas(this.periodicFibers,$))return;let Y=t0.tryPromise({try:Q,catch:(Z)=>Z}).pipe(t0.catchAll((Z)=>t0.sync(()=>{this.activeFailures.push(Z)})));Vw.unsafeSet(this.periodicFibers,$,t0.runFork(Y),{onlyIfMissing:!0})},B=t0.sleep(A).pipe(t0.andThen(t0.sync(w)),t0.forever),X=this.clock?t0.withClock(B,this.clock):B;RZ.unsafeAdd(this.scheduleFibers,t0.runFork(X))}scheduleTrailing(A,Q,$){if(this.closed)return;let w=t0.sleep(Q).pipe(t0.andThen(t0.sync(()=>{this.trackActive($)}))),B=this.clock?t0.withClock(w,this.clock):w,X=t0.runFork(B);Vw.unsafeSet(this.delayedFibers,A,X)}close(){return this.closed=!0,this.closePromise??=this.closeRuntime(),this.closePromise}trackActive(A){if(this.closed)return;let Q;try{Q=A()}catch(w){Q=Promise.reject(w)}let $=Q.catch((w)=>{this.activeFailures.push(w)}).finally(()=>{this.activeOperations.delete($)});this.activeOperations.add($)}async closeRuntime(){let A=[],Q=async($)=>{try{await $()}catch(w){A.push(w)}};await Q(()=>this.closeScope(this.scheduleScope)),await Q(()=>this.closeScope(this.periodicScope)),await Q(()=>this.closeScope(this.delayScope)),await Q(()=>this.closeScope(this.resourceScope));while(this.activeOperations.size>0)await Promise.all([...this.activeOperations]);if(A.push(...this.activeFailures),A.length>0)throw A[0]}async closeScope(A){let Q=await t0.runPromiseExit(j2.close(A,y2.void));if(y2.isFailure(Q))throw a$.squash(Q.cause)}}function BR2(A){return{initialize:()=>A().initialize(),initializeDirectory:()=>A().initializeDirectory(),setJobQueueCallback:(Q)=>A().setJobQueueCallback(Q),sync:()=>A().sync(),processEntityExport:(Q)=>A().processEntityExport(Q),exportEntities:(Q)=>A().exportEntities(Q),importEntitiesWithProgress:(Q,$,w)=>A().importEntitiesWithProgress(Q,$,w),exportEntitiesWithProgress:(Q,$,w)=>A().exportEntitiesWithProgress(Q,$,w),importEntities:(Q)=>A().importEntities(Q),removeOrphanedEntities:()=>A().removeOrphanedEntities(),get fileOps(){return A().fileOps},get shouldDeleteOnFileRemoval(){return A().shouldDeleteOnFileRemoval},getAllMarkdownFiles:()=>A().getAllMarkdownFiles(),ensureDirectoryStructure:()=>A().ensureDirectoryStructure(),getStatus:()=>A().getStatus(),queueSyncBatch:(Q,$,w)=>A().queueSyncBatch(Q,$,w),startWatching:()=>A().startWatching(),stopWatching:()=>A().stopWatching(),setWatchCallback:(Q)=>A().setWatchCallback(Q)}}function XR2(A){return{withLock:(Q,$)=>A().withLock(Q,$),initialize:()=>A().initialize(),hasRemote:()=>A().hasRemote(),getStatus:()=>A().getStatus(),hasLocalChanges:()=>A().hasLocalChanges(),commit:(Q)=>A().commit(Q),push:(Q)=>A().push(Q),pull:(Q)=>A().pull(Q),cleanup:()=>A().cleanup(),log:(Q,$)=>A().log(Q,$),show:(Q,$)=>A().show(Q,$)}}var YR2={name:"@brains/directory-sync",version:"0.2.0-alpha.195",description:"Directory-based entity synchronization plugin for Brains",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^5.0.0","simple-git":"^3.36.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./env-schema":"./src/env-schema.ts"},main:"./src/index.ts",peerDependencies:{},private:!0,scripts:{clean:"rm -rf .turbo",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class zDA extends d6{directorySync;gitSync;operationStatus;workspaceProvider;cmsWorkspaceUrl;runtime=new zb0;directorySyncFacade=BR2(()=>this.requireDirectorySync());gitSyncFacade=XR2(()=>this.requireGitSync());runtimeScheduler={scheduleTrailing:(A,Q,$)=>{this.runtime.scheduleTrailing(A,Q,$)}};watcherOwned=!1;gitBackgroundStarted=!1;gitAutoCommitRegistered=!1;readyState=!1;shutdownStarted=!1;configurationQueue=Promise.resolve();constructor(A={}){super("directory-sync",YR2,A,J50)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}requireGitSync(){if(!this.gitSync)throw Error("GitSync service not initialized");return this.gitSync}requireOperationStatus(){if(!this.operationStatus)throw Error("Directory sync operation status not initialized");return this.operationStatus}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:F50,basePrompt:"",formatter:new Bb0,requiredPermission:"anchor"}});let Q=this.config.syncPath??A.dataDir;this.directorySync=this.createDirectorySync(A,Q);try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:Q})}catch($){throw this.logger.error("Failed to initialize directory",$),$}if(this.operationStatus=new DDA(A.runtimeState,A.jobs,this.logger.child("OperationStatus"),Q),await this.operationStatus.initialize(),this.config.autoSync)UDA(A,this.directorySync,Q,this.operationStatus);if(await this.registerJobHandlers(A),Ex2(A,()=>this.requireDirectorySync(),this.logger,this.config.entityTypes,this.operationStatus),this.config.git&&!this.isGitConfigured())this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(this.isGitConfigured())await this.bootstrapContentRemote(),this.gitSync=await this.initializeGitSync(Q),A.jobs.registerHandler("sync-request",new Wb0(this.logger.child("DirectorySyncRequestJobHandler"),A,()=>this.requireDirectorySync(),()=>this.requireGitSync()));if(this.config.initialSync)ux2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync?this.gitSyncFacade:void 0);this.workspaceProvider=new qDA({context:A,pluginId:this.id,config:this.config,getDirectorySync:()=>this.requireDirectorySync(),getGitSync:()=>this.gitSync,operationStatus:this.operationStatus}),nx2(A,()=>this.requireDirectorySync(),($)=>this.configure($),this.logger,this.config.git,()=>this.gitSync,()=>this.cmsWorkspaceUrl)}async onReady(){await this.startBackgroundWork(),this.readyState=!0,this.cmsWorkspaceUrl=await this.workspaceProvider?.registerCmsWorkspace()}async getTools(){return ox2(this.directorySyncFacade,this.getContext(),this.id,this.gitSync?this.gitSyncFacade:void 0,this.operationStatus)}async onShutdown(){this.shutdownStarted=!0,await this.configurationQueue,await this.stopGeneration(this.runtime,this.directorySync,this.gitSync),this.readyState=!1,this.watcherOwned=!1,this.gitBackgroundStarted=!1}getDirectorySync(){return this.directorySync}configure(A){let Q=this.configurationQueue.then(()=>this.replaceGeneration(A.syncPath));return this.configurationQueue=Q.catch(()=>{}),Q}async replaceGeneration(A){if(this.shutdownStarted)throw Error("Directory sync plugin is shutting down");let Q=this.getContext(),$=new zb0,w=this.createDirectorySync(Q,A),B;try{if(await w.initializeDirectory(),this.config.autoSync)UDA(Q,w,A,this.operationStatus);if(this.isGitConfigured())B=await this.initializeGitSync(A)}catch(H){throw await this.abandonCandidate($,w,B),H}let X=this.runtime,Y=this.directorySync,Z=this.gitSync;try{await this.stopGeneration(X,Y,Z)}catch(H){throw await this.abandonCandidate($,w,B),H}if(this.runtime=$,this.directorySync=w,this.gitSync=B,this.operationStatus?.setSyncPath(A),this.watcherOwned=!1,this.gitBackgroundStarted=!1,this.readyState)await this.startBackgroundWork();this.logger.info("Directory sync reconfigured",{path:A})}createDirectorySync(A,Q){return new EP0({syncPath:Q,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:A.entityService,logger:A.logger})}isGitConfigured(){return this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0)}async bootstrapContentRemote(){let A=this.config.git;if(!A)return;await dx2({gitUrl:A.gitUrl,branch:A.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:A.bootstrapFromSeed,authorName:A.authorName,authorEmail:A.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")})}async initializeGitSync(A){let Q=this.config.git;if(!Q)throw Error("Git configuration is unavailable");let $=new BDA({logger:this.logger.child("GitSync"),dataDir:A,repo:Q.repo,gitUrl:Q.gitUrl,branch:Q.branch,authToken:Q.authToken,authorName:Q.authorName,authorEmail:Q.authorEmail});return await $.initialize(),this.logger.info("Git integration enabled",{repo:Q.repo}),$}async startBackgroundWork(){let A=this.requireDirectorySync();if(this.config.autoSync&&!this.watcherOwned)await this.runtime.acquire(()=>A.startWatching(),()=>A.stopWatching()),this.watcherOwned=!0;let Q=this.gitSync;if(!Q||this.gitBackgroundStarted)return;let $=this.getContext();if(!this.gitAutoCommitRegistered)cx2($.messaging,()=>this.requireGitSync(),this.config.commitDebounce,this.logger.child("GitAutoCommit"),this.runtimeScheduler,this.operationStatus),this.gitAutoCommitRegistered=!0;if(this.config.autoSync)px2(Q,A,$,this.config.syncInterval,this.logger.child("GitPeriodicSync"),this.runtime,this.operationStatus);this.gitBackgroundStarted=!0}async stopGeneration(A,Q,$){let w=[];try{await A.close()}catch(B){w.push(B)}try{await Q?.stopWatching()}catch(B){w.push(B)}try{$?.cleanup()}catch(B){w.push(B)}if(w.length>0)throw w[0]}async abandonCandidate(A,Q,$){try{await A.close()}catch{}try{await Q.stopWatching()}catch{}try{$?.cleanup()}catch{}}async registerJobHandlers(A){hx2(A,this.directorySyncFacade,this.logger,()=>this.requireDirectorySync(),this.requireOperationStatus())}}function RT(A={}){return new zDA(A)}h0();var Vb0="email:send",ZR2=W.strictObject({to:W.string().email(),subject:W.string().min(1),text:W.string().min(1),html:W.string().min(1).optional(),sensitivity:W.enum(["normal","secret"]).default("normal")});zA();h0();var WR2={name:"@brains/email-resend",version:"0.2.0-alpha.195",description:"Generic email delivery adapter for Resend",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var kF$=W.object({apiKey:W.string().min(1).optional(),from:W.string().min(1).optional()}),OF$=W.looseObject({id:W.string().optional()});class HR2 extends d6{fetchImpl;constructor(A={},Q={}){super("email-resend",WR2,A,kF$);this.fetchImpl=Q.fetchImpl??fetch}async onRegister(A){if(!this.config.apiKey||!this.config.from){this.logger.warn("Email Resend adapter is disabled because apiKey or from is missing");return}let Q=this.logger;A.messaging.subscribe(Vb0,async($)=>{let w=ZR2.parse($.payload);try{return{success:!0,data:await this.sendWithResend(w)}}catch(B){if(w.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:w.to,subject:w.subject,error:B instanceof Error?B.message:String(B)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,$=this.config.from;if(!Q||!$)return{status:"failed"};let w=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:$,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!w.ok)throw Error("Resend email request failed");let B=OF$.parse(await w.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function Jb0(A={}){return new HR2(A)}zA();import{render as od2}from"preact-render-to-string";import{h as Dy}from"preact";function KR2(A){var Q,$,w="";if(typeof A=="string"||typeof A=="number")w+=A;else if(typeof A=="object")if(Array.isArray(A)){var B=A.length;for(Q=0;Q<B;Q++)A[Q]&&($=KR2(A[Q]))&&(w&&(w+=" "),w+=$)}else for($ in A)A[$]&&(w&&(w+=" "),w+=$);return w}function bn(){for(var A,Q,$=0,w="",B=arguments.length;$<B;$++)(A=arguments[$])&&(Q=KR2(A))&&(w&&(w+=" "),w+=Q);return w}var fF$=(A,Q)=>{let $=Array(A.length+Q.length);for(let w=0;w<A.length;w++)$[w]=A[w];for(let w=0;w<Q.length;w++)$[A.length+w]=Q[w];return $},xF$=(A,Q)=>({classGroupId:A,validator:Q}),FR2=(A=new Map,Q=null,$)=>({nextPart:A,validators:Q,classGroupId:$});var UR2=[];var RF$=(A)=>{let Q=CF$(A),{conflictingClassGroups:$,conflictingClassGroupModifiers:w}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return vF$(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return LR2(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=w[Y],K=$[Y];if(H){if(K)return fF$(K,H);return H}return K||UR2}return $[Y]||UR2}}},LR2=(A,Q,$)=>{if(A.length-Q===0)return $.classGroupId;let B=A[Q],X=$.nextPart.get(B);if(X){let K=LR2(A,Q+1,X);if(K)return K}let Y=$.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let K=0;K<H;K++){let U=Y[K];if(U.validator(Z))return U.classGroupId}return},vF$=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),$=Q.indexOf(":"),w=Q.slice(0,$);return w?"arbitrary.."+w:void 0})(),CF$=(A)=>{let{theme:Q,classGroups:$}=A;return hF$($,Q)},hF$=(A,Q)=>{let $=FR2();for(let w in A){let B=A[w];FDA(B,$,w,Q)}return $},FDA=(A,Q,$,w)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];EF$(Y,Q,$,w)}},EF$=(A,Q,$,w)=>{if(typeof A==="string"){TF$(A,Q,$);return}if(typeof A==="function"){yF$(A,Q,$,w);return}gF$(A,Q,$,w)},TF$=(A,Q,$)=>{let w=A===""?Q:IR2(Q,A);w.classGroupId=$},yF$=(A,Q,$,w)=>{if(SF$(A)){FDA(A(w),Q,$,w);return}if(Q.validators===null)Q.validators=[];Q.validators.push(xF$($,A))},gF$=(A,Q,$,w)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];FDA(H,IR2(Q,Z),$,w)}},IR2=(A,Q)=>{let $=A,w=Q.split("-"),B=w.length;for(let X=0;X<B;X++){let Y=w[X],Z=$.nextPart.get(Y);if(!Z)Z=FR2(),$.nextPart.set(Y,Z);$=Z}return $},SF$=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,mF$=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,$=Object.create(null),w=Object.create(null),B=(X,Y)=>{if($[X]=Y,Q++,Q>A)Q=0,w=$,$=Object.create(null)};return{get(X){let Y=$[X];if(Y!==void 0)return Y;if((Y=w[X])!==void 0)return B(X,Y),Y},set(X,Y){if(X in $)$[X]=Y;else B(X,Y)}}};var uF$=[],GR2=(A,Q,$,w,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:$,maybePostfixModifierPosition:w,isExternal:B}),cF$=(A)=>{let{prefix:Q,experimentalParseClassName:$}=A,w=(B)=>{let X=[],Y=0,Z=0,H=0,K,U=B.length;for(let F=0;F<U;F++){let L=B[F];if(Y===0&&Z===0){if(L===":"){X.push(B.slice(H,F)),H=F+1;continue}if(L==="/"){K=F;continue}}if(L==="[")Y++;else if(L==="]")Y--;else if(L==="(")Z++;else if(L===")")Z--}let G=X.length===0?B:B.slice(H),D=G,q=!1;if(G.endsWith("!"))D=G.slice(0,-1),q=!0;else if(G.startsWith("!"))D=G.slice(1),q=!0;let J=K&&K>H?K-H:void 0;return GR2(X,q,D,J)};if(Q){let B=Q+":",X=w;w=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):GR2(uF$,!1,Y,void 0,!0)}if($){let B=w;w=(X)=>$({className:X,parseClassName:B})}return w},pF$=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach(($,w)=>{Q.set($,1e6+w)}),($)=>{let w=[],B=[];for(let X=0;X<$.length;X++){let Y=$[X],Z=Y[0]==="[",H=Q.has(Y);if(Z||H){if(B.length>0)B.sort(),w.push(...B),B=[];w.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),w.push(...B);return w}},lF$=(A)=>({cache:mF$(A.cacheSize),parseClassName:cF$(A),sortModifiers:pF$(A),postfixLookupClassGroupIds:iF$(A),...RF$(A)}),iF$=(A)=>{let Q=Object.create(null),$=A.postfixLookupClassGroups;if($)for(let w=0;w<$.length;w++)Q[$[w]]=!0;return Q},dF$=/\s+/,nF$=(A,Q)=>{let{parseClassName:$,getClassGroupId:w,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(dF$),K="";for(let U=H.length-1;U>=0;U-=1){let G=H[U],{isExternal:D,modifiers:q,hasImportantModifier:J,baseClassName:F,maybePostfixModifierPosition:L}=$(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!L,j;if(_){let O=F.substring(0,L);j=w(O);let S=j&&Y[j]?w(F):void 0;if(S&&S!==j)j=S,_=!1}else j=w(F);if(!j){if(!_){K=G+(K.length>0?" "+K:K);continue}if(j=w(F),!j){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=q.length===0?"":q.length===1?q[0]:X(q).join(":"),f=J?b+"!":b,v=f+j;if(Z.indexOf(v)>-1)continue;Z.push(v);let R=B(j,_);for(let O=0;O<R.length;++O){let S=R[O];Z.push(f+S)}K=G+(K.length>0?" "+K:K)}return K},rF$=(...A)=>{let Q=0,$,w,B="";while(Q<A.length)if($=A[Q++]){if(w=NR2($))B&&(B+=" "),B+=w}return B},NR2=(A)=>{if(typeof A==="string")return A;let Q,$="";for(let w=0;w<A.length;w++)if(A[w]){if(Q=NR2(A[w]))$&&($+=" "),$+=Q}return $},DR2=(A,...Q)=>{let $,w,B,X,Y=(H)=>{let K=Q.reduce((U,G)=>G(U),A());return $=lF$(K),w=$.cache.get,B=$.cache.set,X=Z,Z(H)},Z=(H)=>{let K=w(H);if(K)return K;let U=nF$(H,$);return B(H,U),U};return X=Y,(...H)=>X(rF$(...H))},oF$=[],wX=(A)=>{let Q=($)=>$[A]||oF$;return Q.isThemeGetter=!0,Q},_R2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,PR2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,sF$=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,aF$=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,tF$=/\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$/,eF$=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,AL$=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,QL$=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,bf=(A)=>sF$.test(A),y$=(A)=>!!A&&!Number.isNaN(Number(A)),fL=(A)=>!!A&&Number.isInteger(Number(A)),VDA=(A)=>A.endsWith("%")&&y$(A.slice(0,-1)),eP=(A)=>aF$.test(A),bR2=()=>!0,$L$=(A)=>tF$.test(A)&&!eF$.test(A),LDA=()=>!1,wL$=(A)=>AL$.test(A),BL$=(A)=>QL$.test(A),XL$=(A)=>!a2(A)&&!$Q(A),YL$=(A)=>A.startsWith("@container")&&(A[10]==="/"&&A[11]!==void 0||A[11]==="s"&&A[16]!==void 0&&A.startsWith("-size/",10)||A[11]==="n"&&A[18]!==void 0&&A.startsWith("-normal/",10)),ZL$=(A)=>jf(A,kR2,LDA),a2=(A)=>_R2.test(A),vT=(A)=>jf(A,OR2,$L$),qR2=(A)=>jf(A,zL$,y$),WL$=(A)=>jf(A,xR2,bR2),HL$=(A)=>jf(A,fR2,LDA),zR2=(A)=>jf(A,jR2,LDA),KL$=(A)=>jf(A,MR2,BL$),Fb0=(A)=>jf(A,RR2,wL$),$Q=(A)=>PR2.test(A),L50=(A)=>CT(A,OR2),UL$=(A)=>CT(A,fR2),VR2=(A)=>CT(A,jR2),GL$=(A)=>CT(A,kR2),DL$=(A)=>CT(A,MR2),Lb0=(A)=>CT(A,RR2,!0),qL$=(A)=>CT(A,xR2,!0),jf=(A,Q,$)=>{let w=_R2.exec(A);if(w){if(w[1])return Q(w[1]);return $(w[2])}return!1},CT=(A,Q,$=!1)=>{let w=PR2.exec(A);if(w){if(w[1])return Q(w[1]);return $}return!1},jR2=(A)=>A==="position"||A==="percentage",MR2=(A)=>A==="image"||A==="url",kR2=(A)=>A==="length"||A==="size"||A==="bg-size",OR2=(A)=>A==="length",zL$=(A)=>A==="number",fR2=(A)=>A==="family-name",xR2=(A)=>A==="number"||A==="weight",RR2=(A)=>A==="shadow";var JR2=()=>{let A=wX("color"),Q=wX("font"),$=wX("text"),w=wX("font-weight"),B=wX("tracking"),X=wX("leading"),Y=wX("breakpoint"),Z=wX("container"),H=wX("spacing"),K=wX("radius"),U=wX("shadow"),G=wX("inset-shadow"),D=wX("text-shadow"),q=wX("drop-shadow"),J=wX("blur"),F=wX("perspective"),L=wX("aspect"),_=wX("ease"),j=wX("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],f=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...f(),$Q,a2],R=()=>["auto","hidden","clip","visible","scroll"],O=()=>["auto","contain","none"],S=()=>[$Q,a2,H],u=()=>[bf,"full","auto",...S()],i=()=>[fL,"none","subgrid",$Q,a2],a=()=>["auto",{span:["full",fL,$Q,a2]},fL,$Q,a2],B0=()=>[fL,"auto",$Q,a2],p=()=>["auto","min","max","fr",$Q,a2],k=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],T=()=>["start","end","center","stretch","center-safe","end-safe"],E=()=>["auto",...S()],o=()=>[bf,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...S()],t=()=>[bf,"screen","full","dvw","lvw","svw","min","max","fit",...S()],q0=()=>[bf,"screen","full","lh","dvh","lvh","svh","min","max","fit",...S()],g=()=>[A,$Q,a2],Y0=()=>[...f(),VR2,zR2,{position:[$Q,a2]}],F0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],d=()=>["auto","cover","contain",GL$,ZL$,{size:[$Q,a2]}],c0=()=>[VDA,L50,vT],i0=()=>["","none","full",K,$Q,a2],N0=()=>["",y$,L50,vT],b0=()=>["solid","dashed","dotted","double"],v0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[y$,VDA,VR2,zR2],k0=()=>["","none",J,$Q,a2],O0=()=>["none",y$,$Q,a2],f0=()=>["none",y$,$Q,a2],m0=()=>[y$,$Q,a2],o0=()=>[bf,"full",...S()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[eP],breakpoint:[eP],color:[bR2],container:[eP],"drop-shadow":[eP],ease:["in","out","in-out"],font:[XL$],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[eP],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[eP],shadow:[eP],spacing:["px",y$],text:[eP],"text-shadow":[eP],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",bf,a2,$Q,L]}],container:["container"],"container-type":[{"@container":["","normal","size",$Q,a2]}],"container-named":[YL$],columns:[{columns:[y$,a2,$Q,Z]}],"break-after":[{"break-after":b()}],"break-before":[{"break-before":b()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:v()}],overflow:[{overflow:R()}],"overflow-x":[{"overflow-x":R()}],"overflow-y":[{"overflow-y":R()}],overscroll:[{overscroll:O()}],"overscroll-x":[{"overscroll-x":O()}],"overscroll-y":[{"overscroll-y":O()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:u()}],"inset-x":[{"inset-x":u()}],"inset-y":[{"inset-y":u()}],start:[{"inset-s":u(),start:u()}],end:[{"inset-e":u(),end:u()}],"inset-bs":[{"inset-bs":u()}],"inset-be":[{"inset-be":u()}],top:[{top:u()}],right:[{right:u()}],bottom:[{bottom:u()}],left:[{left:u()}],visibility:["visible","invisible","collapse"],z:[{z:[fL,"auto",$Q,a2]}],basis:[{basis:[bf,"full","auto",Z,...S()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[y$,bf,"auto","initial","none",a2]}],grow:[{grow:["",y$,$Q,a2]}],shrink:[{shrink:["",y$,$Q,a2]}],order:[{order:[fL,"first","last","none",$Q,a2]}],"grid-cols":[{"grid-cols":i()}],"col-start-end":[{col:a()}],"col-start":[{"col-start":B0()}],"col-end":[{"col-end":B0()}],"grid-rows":[{"grid-rows":i()}],"row-start-end":[{row:a()}],"row-start":[{"row-start":B0()}],"row-end":[{"row-end":B0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":p()}],"auto-rows":[{"auto-rows":p()}],gap:[{gap:S()}],"gap-x":[{"gap-x":S()}],"gap-y":[{"gap-y":S()}],"justify-content":[{justify:[...k(),"normal"]}],"justify-items":[{"justify-items":[...T(),"normal"]}],"justify-self":[{"justify-self":["auto",...T()]}],"align-content":[{content:["normal",...k()]}],"align-items":[{items:[...T(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...T(),{baseline:["","last"]}]}],"place-content":[{"place-content":k()}],"place-items":[{"place-items":[...T(),"baseline"]}],"place-self":[{"place-self":["auto",...T()]}],p:[{p:S()}],px:[{px:S()}],py:[{py:S()}],ps:[{ps:S()}],pe:[{pe:S()}],pbs:[{pbs:S()}],pbe:[{pbe:S()}],pt:[{pt:S()}],pr:[{pr:S()}],pb:[{pb:S()}],pl:[{pl:S()}],m:[{m:E()}],mx:[{mx:E()}],my:[{my:E()}],ms:[{ms:E()}],me:[{me:E()}],mbs:[{mbs:E()}],mbe:[{mbe:E()}],mt:[{mt:E()}],mr:[{mr:E()}],mb:[{mb:E()}],ml:[{ml:E()}],"space-x":[{"space-x":S()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":S()}],"space-y-reverse":["space-y-reverse"],size:[{size:o()}],"inline-size":[{inline:["auto",...t()]}],"min-inline-size":[{"min-inline":["auto",...t()]}],"max-inline-size":[{"max-inline":["none",...t()]}],"block-size":[{block:["auto",...q0()]}],"min-block-size":[{"min-block":["auto",...q0()]}],"max-block-size":[{"max-block":["none",...q0()]}],w:[{w:[Z,"screen",...o()]}],"min-w":[{"min-w":[Z,"screen","none",...o()]}],"max-w":[{"max-w":[Z,"screen","none","prose",{screen:[Y]},...o()]}],h:[{h:["screen","lh",...o()]}],"min-h":[{"min-h":["screen","lh","none",...o()]}],"max-h":[{"max-h":["screen","lh",...o()]}],"font-size":[{text:["base",$,L50,vT]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[w,qL$,WL$]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",VDA,a2]}],"font-family":[{font:[UL$,HL$,Q]}],"font-features":[{"font-features":[a2]}],"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:[B,$Q,a2]}],"line-clamp":[{"line-clamp":[y$,"none",$Q,qR2]}],leading:[{leading:[X,...S()]}],"list-image":[{"list-image":["none",$Q,a2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",$Q,a2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:g()}],"text-color":[{text:g()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...b0(),"wavy"]}],"text-decoration-thickness":[{decoration:[y$,"from-font","auto",$Q,vT]}],"text-decoration-color":[{decoration:g()}],"underline-offset":[{"underline-offset":[y$,"auto",$Q,a2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:S()}],"tab-size":[{tab:[fL,$Q,a2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",$Q,a2]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",$Q,a2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:Y0()}],"bg-repeat":[{bg:F0()}],"bg-size":[{bg:d()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},fL,$Q,a2],radial:["",$Q,a2],conic:[fL,$Q,a2]},DL$,KL$]}],"bg-color":[{bg:g()}],"gradient-from-pos":[{from:c0()}],"gradient-via-pos":[{via:c0()}],"gradient-to-pos":[{to:c0()}],"gradient-from":[{from:g()}],"gradient-via":[{via:g()}],"gradient-to":[{to:g()}],rounded:[{rounded:i0()}],"rounded-s":[{"rounded-s":i0()}],"rounded-e":[{"rounded-e":i0()}],"rounded-t":[{"rounded-t":i0()}],"rounded-r":[{"rounded-r":i0()}],"rounded-b":[{"rounded-b":i0()}],"rounded-l":[{"rounded-l":i0()}],"rounded-ss":[{"rounded-ss":i0()}],"rounded-se":[{"rounded-se":i0()}],"rounded-ee":[{"rounded-ee":i0()}],"rounded-es":[{"rounded-es":i0()}],"rounded-tl":[{"rounded-tl":i0()}],"rounded-tr":[{"rounded-tr":i0()}],"rounded-br":[{"rounded-br":i0()}],"rounded-bl":[{"rounded-bl":i0()}],"border-w":[{border:N0()}],"border-w-x":[{"border-x":N0()}],"border-w-y":[{"border-y":N0()}],"border-w-s":[{"border-s":N0()}],"border-w-e":[{"border-e":N0()}],"border-w-bs":[{"border-bs":N0()}],"border-w-be":[{"border-be":N0()}],"border-w-t":[{"border-t":N0()}],"border-w-r":[{"border-r":N0()}],"border-w-b":[{"border-b":N0()}],"border-w-l":[{"border-l":N0()}],"divide-x":[{"divide-x":N0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":N0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...b0(),"hidden","none"]}],"divide-style":[{divide:[...b0(),"hidden","none"]}],"border-color":[{border:g()}],"border-color-x":[{"border-x":g()}],"border-color-y":[{"border-y":g()}],"border-color-s":[{"border-s":g()}],"border-color-e":[{"border-e":g()}],"border-color-bs":[{"border-bs":g()}],"border-color-be":[{"border-be":g()}],"border-color-t":[{"border-t":g()}],"border-color-r":[{"border-r":g()}],"border-color-b":[{"border-b":g()}],"border-color-l":[{"border-l":g()}],"divide-color":[{divide:g()}],"outline-style":[{outline:[...b0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[y$,$Q,a2]}],"outline-w":[{outline:["",y$,L50,vT]}],"outline-color":[{outline:g()}],shadow:[{shadow:["","none",U,Lb0,Fb0]}],"shadow-color":[{shadow:g()}],"inset-shadow":[{"inset-shadow":["none",G,Lb0,Fb0]}],"inset-shadow-color":[{"inset-shadow":g()}],"ring-w":[{ring:N0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:g()}],"ring-offset-w":[{"ring-offset":[y$,vT]}],"ring-offset-color":[{"ring-offset":g()}],"inset-ring-w":[{"inset-ring":N0()}],"inset-ring-color":[{"inset-ring":g()}],"text-shadow":[{"text-shadow":["none",D,Lb0,Fb0]}],"text-shadow-color":[{"text-shadow":g()}],opacity:[{opacity:[y$,$Q,a2]}],"mix-blend":[{"mix-blend":[...v0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":v0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[y$]}],"mask-image-linear-from-pos":[{"mask-linear-from":S0()}],"mask-image-linear-to-pos":[{"mask-linear-to":S0()}],"mask-image-linear-from-color":[{"mask-linear-from":g()}],"mask-image-linear-to-color":[{"mask-linear-to":g()}],"mask-image-t-from-pos":[{"mask-t-from":S0()}],"mask-image-t-to-pos":[{"mask-t-to":S0()}],"mask-image-t-from-color":[{"mask-t-from":g()}],"mask-image-t-to-color":[{"mask-t-to":g()}],"mask-image-r-from-pos":[{"mask-r-from":S0()}],"mask-image-r-to-pos":[{"mask-r-to":S0()}],"mask-image-r-from-color":[{"mask-r-from":g()}],"mask-image-r-to-color":[{"mask-r-to":g()}],"mask-image-b-from-pos":[{"mask-b-from":S0()}],"mask-image-b-to-pos":[{"mask-b-to":S0()}],"mask-image-b-from-color":[{"mask-b-from":g()}],"mask-image-b-to-color":[{"mask-b-to":g()}],"mask-image-l-from-pos":[{"mask-l-from":S0()}],"mask-image-l-to-pos":[{"mask-l-to":S0()}],"mask-image-l-from-color":[{"mask-l-from":g()}],"mask-image-l-to-color":[{"mask-l-to":g()}],"mask-image-x-from-pos":[{"mask-x-from":S0()}],"mask-image-x-to-pos":[{"mask-x-to":S0()}],"mask-image-x-from-color":[{"mask-x-from":g()}],"mask-image-x-to-color":[{"mask-x-to":g()}],"mask-image-y-from-pos":[{"mask-y-from":S0()}],"mask-image-y-to-pos":[{"mask-y-to":S0()}],"mask-image-y-from-color":[{"mask-y-from":g()}],"mask-image-y-to-color":[{"mask-y-to":g()}],"mask-image-radial":[{"mask-radial":[$Q,a2]}],"mask-image-radial-from-pos":[{"mask-radial-from":S0()}],"mask-image-radial-to-pos":[{"mask-radial-to":S0()}],"mask-image-radial-from-color":[{"mask-radial-from":g()}],"mask-image-radial-to-color":[{"mask-radial-to":g()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":f()}],"mask-image-conic-pos":[{"mask-conic":[y$]}],"mask-image-conic-from-pos":[{"mask-conic-from":S0()}],"mask-image-conic-to-pos":[{"mask-conic-to":S0()}],"mask-image-conic-from-color":[{"mask-conic-from":g()}],"mask-image-conic-to-color":[{"mask-conic-to":g()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:Y0()}],"mask-repeat":[{mask:F0()}],"mask-size":[{mask:d()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",$Q,a2]}],filter:[{filter:["","none",$Q,a2]}],blur:[{blur:k0()}],brightness:[{brightness:[y$,$Q,a2]}],contrast:[{contrast:[y$,$Q,a2]}],"drop-shadow":[{"drop-shadow":["","none",q,Lb0,Fb0]}],"drop-shadow-color":[{"drop-shadow":g()}],grayscale:[{grayscale:["",y$,$Q,a2]}],"hue-rotate":[{"hue-rotate":[y$,$Q,a2]}],invert:[{invert:["",y$,$Q,a2]}],saturate:[{saturate:[y$,$Q,a2]}],sepia:[{sepia:["",y$,$Q,a2]}],"backdrop-filter":[{"backdrop-filter":["","none",$Q,a2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[y$,$Q,a2]}],"backdrop-contrast":[{"backdrop-contrast":[y$,$Q,a2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",y$,$Q,a2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[y$,$Q,a2]}],"backdrop-invert":[{"backdrop-invert":["",y$,$Q,a2]}],"backdrop-opacity":[{"backdrop-opacity":[y$,$Q,a2]}],"backdrop-saturate":[{"backdrop-saturate":[y$,$Q,a2]}],"backdrop-sepia":[{"backdrop-sepia":["",y$,$Q,a2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":S()}],"border-spacing-x":[{"border-spacing-x":S()}],"border-spacing-y":[{"border-spacing-y":S()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",$Q,a2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[y$,"initial",$Q,a2]}],ease:[{ease:["linear","initial",_,$Q,a2]}],delay:[{delay:[y$,$Q,a2]}],animate:[{animate:["none",j,$Q,a2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[F,$Q,a2]}],"perspective-origin":[{"perspective-origin":v()}],rotate:[{rotate:O0()}],"rotate-x":[{"rotate-x":O0()}],"rotate-y":[{"rotate-y":O0()}],"rotate-z":[{"rotate-z":O0()}],scale:[{scale:f0()}],"scale-x":[{"scale-x":f0()}],"scale-y":[{"scale-y":f0()}],"scale-z":[{"scale-z":f0()}],"scale-3d":["scale-3d"],skew:[{skew:m0()}],"skew-x":[{"skew-x":m0()}],"skew-y":[{"skew-y":m0()}],transform:[{transform:[$Q,a2,"","none","gpu","cpu"]}],"transform-origin":[{origin:v()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:o0()}],"translate-x":[{"translate-x":o0()}],"translate-y":[{"translate-y":o0()}],"translate-z":[{"translate-z":o0()}],"translate-none":["translate-none"],zoom:[{zoom:[fL,$Q,a2]}],accent:[{accent:g()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:g()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",$Q,a2]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":g()}],"scrollbar-track-color":[{"scrollbar-track":g()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":S()}],"scroll-mx":[{"scroll-mx":S()}],"scroll-my":[{"scroll-my":S()}],"scroll-ms":[{"scroll-ms":S()}],"scroll-me":[{"scroll-me":S()}],"scroll-mbs":[{"scroll-mbs":S()}],"scroll-mbe":[{"scroll-mbe":S()}],"scroll-mt":[{"scroll-mt":S()}],"scroll-mr":[{"scroll-mr":S()}],"scroll-mb":[{"scroll-mb":S()}],"scroll-ml":[{"scroll-ml":S()}],"scroll-p":[{"scroll-p":S()}],"scroll-px":[{"scroll-px":S()}],"scroll-py":[{"scroll-py":S()}],"scroll-ps":[{"scroll-ps":S()}],"scroll-pe":[{"scroll-pe":S()}],"scroll-pbs":[{"scroll-pbs":S()}],"scroll-pbe":[{"scroll-pbe":S()}],"scroll-pt":[{"scroll-pt":S()}],"scroll-pr":[{"scroll-pr":S()}],"scroll-pb":[{"scroll-pb":S()}],"scroll-pl":[{"scroll-pl":S()}],"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",$Q,a2]}],fill:[{fill:["none",...g()]}],"stroke-w":[{stroke:[y$,L50,vT,qR2]}],stroke:[{stroke:["none",...g()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},VL$=(A,{cacheSize:Q,prefix:$,experimentalParseClassName:w,extend:B={},override:X={}})=>{return jn(A,"cacheSize",Q),jn(A,"prefix",$),jn(A,"experimentalParseClassName",w),Ib0(A.theme,X.theme),Ib0(A.classGroups,X.classGroups),Ib0(A.conflictingClassGroups,X.conflictingClassGroups),Ib0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),jn(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),jn(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),Nb0(A.theme,B.theme),Nb0(A.classGroups,B.classGroups),Nb0(A.conflictingClassGroups,B.conflictingClassGroups),Nb0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),JDA(A,B,"postfixLookupClassGroups"),JDA(A,B,"orderSensitiveModifiers"),A},jn=(A,Q,$)=>{if($!==void 0)A[Q]=$},Ib0=(A,Q)=>{if(Q)for(let $ in Q)jn(A,$,Q[$])},Nb0=(A,Q)=>{if(Q)for(let $ in Q)JDA(A,Q,$)},JDA=(A,Q,$)=>{let w=Q[$];if(w!==void 0)A[$]=A[$]?A[$].concat(w):w},_b0=(A,...Q)=>typeof A==="function"?DR2(JR2,A,...Q):DR2(()=>VL$(JR2(),A),...Q);var JL$=_b0({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 wQ(...A){return JL$(bn(A))}var vR2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,CR2=bn,B5=(A,Q)=>($)=>{var w;if((Q===null||Q===void 0?void 0:Q.variants)==null)return CR2(A,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className);let{variants:B,defaultVariants:X}=Q,Y=Object.keys(B).map((K)=>{let U=$===null||$===void 0?void 0:$[K],G=X===null||X===void 0?void 0:X[K];if(U===null)return null;let D=vR2(U)||vR2(G);return B[K][D]}),Z=$&&Object.entries($).reduce((K,U)=>{let[G,D]=U;if(D===void 0)return K;return K[G]=D,K},{}),H=Q===null||Q===void 0?void 0:(w=Q.compoundVariants)===null||w===void 0?void 0:w.reduce((K,U)=>{let{class:G,className:D,...q}=U;return Object.entries(q).every((J)=>{let[F,L]=J;return Array.isArray(L)?L.includes({...X,...Z}[F]):{...X,...Z}[F]===L})?[...K,G,D]:K},[]);return CR2(A,Y,H,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className)};import{jsxDEV as IDA}from"preact/jsx-dev-runtime";var hR2=B5("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 NDA({variant:A,title:Q,children:$,className:w}){return IDA("div",{className:wQ(hR2({variant:A}),w),role:"alert",children:[Q&&IDA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),IDA("div",{className:wQ(Q&&"mt-1","text-sm text-current opacity-75"),children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as FL$}from"preact/jsx-dev-runtime";var ER2=B5("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 hT({variant:A,size:Q,className:$,children:w,ssrOnClick:B,type:X="button",...Y}){return FL$("button",{type:X,className:wQ(ER2({variant:A,size:Q}),$),...Y,...B&&{onclick:B},children:w},void 0,!1,void 0,this)}import{jsxDEV as LL$}from"preact/jsx-dev-runtime";var TR2=B5("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 BX({href:A,children:Q,variant:$,size:w,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return LL$("a",{href:A,className:wQ(TR2({variant:$,size:w}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as Pb0}from"preact/jsx-dev-runtime";var yR2=B5("transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2",{variants:{variant:{default:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent hover:border-brand/40",light:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent",dark:"rounded-[10px] bg-theme-dark hover:bg-theme-muted text-theme-inverse",footer:"rounded-full bg-theme-toggle hover:bg-theme-toggle-hover text-theme-toggle-icon"},size:{sm:"p-1.5",md:"p-2",lg:"p-3"}},defaultVariants:{variant:"default",size:"md"}}),IL$={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Mn({variant:A,size:Q,className:$}){let w=IL$[Q??"md"];return Pb0("button",{onclick:"toggleTheme()",type:"button",className:wQ(yR2({variant:A,size:Q}),$),"aria-label":"Toggle dark mode",children:Pb0("svg",{className:wQ(w,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[Pb0("path",{className:"sun-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"},void 0,!1,void 0,this),Pb0("path",{className:"moon-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M20.354 15.354A9 9 0 018.646 3.646 9 9 0 1020.354 15.354z"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as _DA}from"preact/jsx-dev-runtime";var gR2=B5("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function bb0({items:A,className:Q,linkClassName:$="hover:text-accent transition-colors",orientation:w,children:B}){if(A.length===0&&!B)return null;let X=[...A].sort((Y,Z)=>Y.priority-Z.priority);return _DA("ul",{className:wQ(gR2({orientation:w}),Q),children:[X.map((Y)=>_DA("li",{children:_DA("a",{href:Y.href,className:$,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),B]},void 0,!0,void 0,this)}import{jsxDEV as CC5}from"preact/jsx-dev-runtime";import{jsxDEV as TC5}from"preact/jsx-dev-runtime";import{createContext as NL$,h as _L$}from"preact";import{useContext as PL$}from"preact/hooks";var PDA=NL$(null);function kn({headCollector:A,children:Q}){return _L$(PDA.Provider,{value:A},Q)}function SR2(){return PL$(PDA)}function E6(A){let Q=SR2();if(Q)Q.setHeadProps(A);return null}import{createContext as AM$,h as QM$}from"preact";import{useContext as $M$}from"preact/hooks";d2A();var oE2=k1(rE2(),1),tj$=new bV0({gfm:!0,breaks:!0}),ej$={allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","ul","ol","li","blockquote","cite","code","pre","em","strong","del","ins","sub","sup","a","img","span","table","thead","tbody","tr","th","td","div"],allowedAttributes:{a:["href","title","name"],img:["src","srcset","sizes","alt","title","width","height","class","loading","decoding"],code:["class"],pre:["class"],span:["class"],cite:["class"],div:["class"],th:["align","colspan","rowspan","scope"],td:["align","colspan","rowspan"]},allowedSchemes:["http","https","mailto","tel"],allowedSchemesByTag:{img:["http","https","entity"]},allowProtocolRelative:!1,disallowedTagsMode:"discard"};function rqA(A,Q){let{imageRenderer:$}=Q??{},B=($?new bV0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return $(X,Y,Z)??!1}}}):tj$).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
5862
+ `)}}zA();class Xb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:WDA,jobTypeName:"directory-export"});this.directorySync=$,this.operationStatus=w}async process(A,Q,$){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let w=Date.now();try{let B=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,$,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:B.exported,failed:B.failed,duration:Date.now()-w}),await this.operationStatus?.addExportResult(B),B}catch(B){throw this.logger.error("Directory export job failed",{jobId:Q,error:B}),await this.operationStatus?.recordIssue({kind:"export",message:B instanceof Error?B.message:"Directory export failed"}),B}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}zA();class Yb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:ZDA,jobTypeName:"directory-import"});this.directorySync=$,this.operationStatus=w}async process(A,Q,$){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let w=Date.now();try{let B=await this.directorySync.importEntitiesWithProgress(A.paths,$,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:B.imported,skipped:B.skipped,failed:B.failed,quarantined:B.quarantined,duration:Date.now()-w}),await this.operationStatus?.addImportResult(B),B}catch(B){throw this.logger.error("Directory import job failed",{jobId:Q,error:B}),await this.operationStatus?.recordIssue({kind:"import",message:B instanceof Error?B.message:"Directory import failed"}),B}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}zA();c8();var EJ$=300000,TJ$=500;async function Cx2(A){if(A.jobIds.length===0)return;let Q=A.maxWaitMs??EJ$,$=A.pollIntervalMs??TJ$;A.logger.debug(`Waiting for ${A.jobIds.length} import jobs to complete`);let w=t0.gen(function*(){let Y=yield*eW.currentTimeMillis;yield*t0.gen(function*(){let K=(yield*t0.tryPromise({try:()=>Promise.all(A.jobIds.map((D)=>A.entityService.getAsyncJobStatus(D))),catch:(D)=>D})).filter((D)=>D&&(D.status==="completed"||D.status==="failed")).length;if(K===A.jobIds.length)return A.logger.debug("All import jobs completed"),!0;if((yield*eW.currentTimeMillis)-Y>Q)return A.logger.warn(`Timeout waiting for import jobs (${K}/${A.jobIds.length} completed)`),!0;let G=Math.round(K/A.jobIds.length*100);return yield*t0.tryPromise({try:()=>A.reporter.report({progress:50+Math.round(G*0.05),message:`Processing ${K}/${A.jobIds.length} entities`}),catch:(D)=>D}),!1}).pipe(t0.repeat({schedule:Lq.spaced($),until:(H)=>H}))}),B=A.clock?t0.withClock(w,A.clock):w,X=await t0.runPromiseExit(B);if(y2.isFailure(X))throw a$.squash(X.cause)}class Zb0 extends H8{getDirectorySync;context;constructor(A,Q,$){super(A,{schema:XDA,jobTypeName:"directory-sync"});this.context=Q,this.getDirectorySync=$}async process(A,Q,$){let w=Date.now(),B=A.syncDirection??"both",X=this.getDirectorySync();this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:B});let Y={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Z={exported:0,failed:0,errors:[]};if(B!=="export")if(await $.report({progress:10,message:"Scanning directory for changes"}),Y=await this.importWithProgress(X,A.paths,$),B==="import")await this.waitForImportJobs(Y.jobIds,$),await $.report({progress:100,message:`Import complete: ${Y.imported} imported`});else await $.report({progress:50,message:`Imported ${Y.imported} entities`}),await this.waitForImportJobs(Y.jobIds,$),await $.report({progress:56,message:"Processing complete, starting export"});if(B!=="import"){let K=B==="export"?10:60;await $.report({progress:K,message:"Exporting entities to directory"}),Z=await this.exportWithProgress(X,A.entityTypes,$),await $.report({progress:100,message:B==="export"?`Export complete: ${Z.exported} exported`:`Sync complete: ${Y.imported} imported, ${Z.exported} exported`})}let H=Date.now()-w;return this.logger.info("Directory sync job completed",{jobId:Q,duration:H,imported:Y.imported,exported:Z.exported}),{import:Y,export:Z,duration:H}}async importWithProgress(A,Q,$){try{return await A.importEntitiesWithProgress(Q,$,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q,$){try{return await A.exportEntitiesWithProgress(Q,$,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}waitForImportJobs(A,Q){return Cx2({jobIds:A,entityService:this.context.entityService,reporter:Q,logger:this.logger})}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}zA();class Wb0 extends H8{context;getDirectorySync;getGitSync;constructor(A,Q,$,w){super(A,{schema:YDA,jobTypeName:"sync-request"});this.context=Q,this.getDirectorySync=$,this.getGitSync=w}async process(A,Q,$){await $.report({progress:5,message:"Pulling latest content from git"});let w=this.getDirectorySync(),B=this.getGitSync(),X=await B.withLock(async()=>{return await B.pull(),await $.report({progress:35,message:"Scanning pulled content for sync changes"}),w.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!X)return await $.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await $.report({progress:100,message:`Sync queued: ${X.importOperationsCount} import jobs for ${X.totalFiles} files`}),yJ$(X)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function yJ$(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}zA();class Hb0 extends H8{context;constructor(A,Q,$){super(A,{schema:wb0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,$){let w=wb0.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}),await $.report({progress:0,total:1,message:`Deleting ${w.entityType}:${w.entityId}`});try{let B=await this.context.entityService.deleteEntity({entityType:w.entityType,id:w.entityId});if(B)this.logger.info("Successfully deleted entity for removed file",{entityId:w.entityId,entityType:w.entityType});else this.logger.warn("Entity not found in database",{entityId:w.entityId,entityType:w.entityType});return await $.report({progress:1,total:1,message:`Deleted ${w.entityType}:${w.entityId}`}),{deleted:B,entityId:w.entityId,entityType:w.entityType,filePath:w.filePath}}catch(B){throw this.logger.error("Failed to delete entity",{entityId:w.entityId,entityType:w.entityType,error:B}),B}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}zA();h0();var gJ$=W.object({});class Kb0 extends H8{directorySync;constructor(A,Q){super(A,{schema:gJ$,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,$){await $.report({progress:0,message:"Removing orphaned entities"});let w=await this.directorySync.removeOrphanedEntities();return await $.report({progress:100,message:`Cleanup complete: ${w.deleted} orphans removed`}),w}}zA();cZ();u4();Uw();h0();cZ();import{readFile as SJ$,writeFile as mJ$}from"fs/promises";var uJ$=HDA,cJ$=W.record(W.string(),W.unknown());class Ub0 extends H8{context;fetcher;constructor(A,Q,$=Eq){super(Q,{schema:uJ$,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=$}async process(A,Q,$){let{filePath:w,sourceUrl:B,postTitle:X,postSlug:Y,customAlt:Z}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:w,sourceUrl:B,postSlug:Y});try{await this.reportProgress($,{progress:g6.INIT,message:`Reading file: ${w}`});let H;try{H=await SJ$(w,"utf-8")}catch(L){return this.logger.error("Failed to read file",{filePath:w,error:eA(L)}),o5.failure(L)}let K;try{K=t8(H)}catch(L){return this.logger.warn("Failed to parse markdown",{filePath:w,error:eA(L)}),o5.failure(L)}let U=cJ$.safeParse(K.frontmatter),G=U.success?U.data:{};if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress($,{progress:g6.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),q;if(D[0])q=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:q}),await this.reportProgress($,{progress:g6.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress($,{progress:g6.PROCESS,message:`Fetching image from ${B}`});let L;try{L=await this.fetcher(B)}catch(R){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:eA(R)}),o5.failure(R)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let{base64:_}=Pk(L),j=Yh(_),b=bk(_);if(!j||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),o5.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let f=`Cover image for ${X}`,v=Z??f;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:L,metadata:{title:f,alt:v,format:j,width:b.width,height:b.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:B}),await this.reportProgress($,{progress:g6.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress($,{progress:g6.SAVE,message:"Updating file"});let J={...G};delete J.coverImageUrl,delete J.coverImageAlt,J.coverImageId=q;let F=MC(J,K.content);try{await mJ$(w,F,"utf-8")}catch(L){return this.logger.error("Failed to write file",{filePath:w,error:eA(L)}),o5.failure(L)}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:w,imageId:q,sourceUrl:B}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:w,error:eA(H)}),o5.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}zA();cZ();Uw();import{readFile as pJ$,writeFile as lJ$}from"fs/promises";class Gb0 extends H8{converter;constructor(A,Q,$=Eq){super(Q,{schema:KDA,jobTypeName:"inline-image-convert"});this.converter=new X50(A.entityService,Q,$)}async process(A,Q,$){let{filePath:w,postSlug:B}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:w,postSlug:B});try{await this.reportProgress($,{progress:g6.INIT,message:`Reading file: ${w}`});let X;try{X=await pJ$(w,"utf-8")}catch(H){let K=eA(H);return this.logger.error("Failed to read file",{filePath:w,error:K}),{success:!1,error:K}}await this.reportProgress($,{progress:g6.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(X,B);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:w,count:Y.length}),await this.reportProgress($,{progress:g6.PROCESS,message:`Converting ${Y.length} images`});let Z=await this.converter.convert(X,B);if(!Z.converted)return this.logger.debug("No images were converted",{filePath:w}),await this.reportProgress($,{progress:g6.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress($,{progress:g6.SAVE,message:"Writing updated file"});try{await lJ$(w,Z.content,"utf-8")}catch(H){let K=eA(H);return this.logger.error("Failed to write file",{filePath:w,error:K}),{success:!1,error:K}}return await this.reportProgress($,{progress:g6.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:w,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=eA(X);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:w,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function hx2(A,Q,$,w=()=>Q,B){let X=(Y)=>$.child(Y);A.jobs.registerHandler("directory-sync",new Zb0(X("DirectorySyncJobHandler"),A,w)),A.jobs.registerHandler("directory-export",new Xb0(X("DirectoryExportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-import",new Yb0(X("DirectoryImportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-delete",new Hb0(X("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new Kb0(X("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Ub0(A,X("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Gb0(A,X("InlineImageConversionJobHandler"))),$.debug("Registered async job handlers")}zA();h0();import{unlink as iJ$,access as dJ$}from"fs/promises";var nJ$=W.record(W.string(),W.unknown());function Ex2(A,Q,$,w,B){let{subscribe:X}=A.messaging,{entityService:Y}=A;X("entity:created",async(Z)=>{let{entity:H}=Z.payload;try{await Q().fileOps.writeEntity(H),$.debug("Auto-exported created entity",{id:H.id,entityType:H.entityType}),await B?.clearIssues(["export"])}catch(K){$.error("Auto-export FAILED for created entity",{id:H.id,entityType:H.entityType,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0}),await B?.recordIssue({kind:"export",path:`${H.entityType}/${H.id}.md`,message:K instanceof Error?K.message:"Entity export failed"})}return{success:!0}}),X("entity:updated",async(Z)=>{let{entityType:H,entityId:K}=Z.payload;try{let U=await Y.getEntity({entityType:H,id:K});if(!U)return $.debug("Entity not found in DB, skipping export",{entityType:H,entityId:K}),{success:!1};await Q().fileOps.writeEntity(U),$.debug("Auto-exported updated entity",{id:U.id,entityType:U.entityType}),await B?.clearIssues(["export"])}catch(U){$.error("Auto-export FAILED for updated entity",{entityType:H,entityId:K,error:U instanceof Error?U.message:String(U),stack:U instanceof Error?U.stack:void 0}),await B?.recordIssue({kind:"export",path:`${H}/${K}.md`,message:U instanceof Error?U.message:"Entity export failed"})}return{success:!0}}),X("entity:deleted",async(Z)=>{let{entityId:H,entityType:K}=Z.payload,U=Q().fileOps.getFilePath(H,K);if(await dJ$(U).then(()=>!0,()=>!1))await iJ$(U),$.debug("Auto-deleted entity file",{id:H,entityType:K,path:U});return{success:!0}}),$.debug("Setup auto-sync for entity events",{entityTypes:w})}function UDA(A,Q,$,w){Q.setJobQueueCallback(async(B)=>{let X=await w?.startRun("watcher","importing"),Y=[{type:B.type,data:nJ$.parse(B.data)}];try{let Z=await A.jobs.enqueueBatch(Y,{priority:5,source:"directory-sync-watcher",rootJobId:O4(),metadata:{operationType:"file_operations",operationTarget:$,pluginId:"directory-sync"}});if(X)await w?.attachBatch(X,Z);return Z}catch(Z){if(X)await w?.failRun(X,Z instanceof Error?Z.message:"Watcher import failed","import");throw Z}})}zA();import{readdir as gx2,mkdir as oJ$,copyFile as sJ$}from"fs/promises";import{join as yx2,resolve as GDA}from"path";import{join as rJ$}from"path";async function Tx2(A){if(!await D7(rJ$(A,".git")))return!1;try{return await kV(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function aJ$(A,Q){if(!await D7(A))return!0;if((await gx2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await Tx2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function Sx2(A,Q){let $=await gx2(A,{withFileTypes:!0});for(let w of $){let B=yx2(A,w.name),X=yx2(Q,w.name);if(w.isDirectory()){if(!await D7(X))await oJ$(X,{recursive:!0});await Sx2(B,X)}else await sJ$(B,X)}}async function mx2(A,Q,$){let w=GDA(process.cwd(),A);$=$?GDA($):GDA(process.cwd(),"seed-content");let B=await aJ$(w,Q);if(B&&await D7($))Q.debug("Copying seed content to brain-data directory"),await Sx2($,w),Q.debug("Seed content copied successfully");else if(B)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function ux2(A,Q,$,w,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if($.seedContent){let H=$.syncPath??A.dataDir;await mx2(H,w,$.seedContentPath)}try{if(B){w.debug("Git enabled \u2014 pulling before import");let K=await B.pull();if(K.files.length>0)w.info("Pulled changes from remote",{filesChanged:K.files.length})}w.debug("Starting initial sync");let H=await Z.sync();w.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:xC.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){w.error("Initial sync failed",H),await A.messaging.send({type:xC.initialSyncCompleted,payload:{success:!1,error:eA(H)},...{broadcast:!0}})}};A.messaging.subscribe(xC.pluginsRegistered,async()=>{return w.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}function cx2(A,Q,$,w,B,X){let Y=typeof Q==="function"?Q:()=>Q,Z=async()=>{let K=Y();try{await K.withLock(async()=>{await K.commit(),await K.push()}),await X?.clearIssues(["git"]),await X?.recordTerminal("save","succeeded","Local content committed and pushed")}catch(U){w.error("Git auto-commit failed",{error:U});let G=U instanceof Error?U.message:"Git auto-commit failed";await X?.recordIssue({kind:"git",message:G}),await X?.recordTerminal("save","failed",G)}},H=["entity:created","entity:updated","entity:deleted"];for(let K of H)A.subscribe(K,async()=>{return B.scheduleTrailing("git-auto-commit",$,Z),{success:!0}})}function px2(A,Q,$,w,B,X,Y){if(w<=0)return;let Z=w*60*1000,H=async(K)=>{let U=await Y?.startRun("periodic","pulling");try{let{files:G,result:D}=await A.withLock(async()=>{let q=await A.pull(K);if(K.throwIfAborted(),q.files.length===0)return{files:[],result:null};let J=await Q.queueSyncBatch($,"periodic-sync");return{files:q.files,result:J}},K);if(G.length>0)B.info("Periodic sync: pulled changes",{filesChanged:G.length});if(D){if(B.debug("Periodic sync: queued imports",{importOperations:D.importOperationsCount,totalFiles:D.totalFiles}),U)await Y?.attachBatch(U,D.batchId)}else if(U)await Y?.completeRun(U,G.length===0?"Remote checked; no changes found":"Remote changes required no imports")}catch(G){if(K.aborted){if(U)await Y?.clearRun(U)}else if(B.error("Periodic git sync failed",{error:G}),U)await Y?.failRun(U,G instanceof Error?G.message:"Periodic Git sync failed")}};X.schedulePeriodic(Z,H),B.info("Started periodic git sync",{intervalMinutes:w})}import{spawnSync as ix2}from"child_process";import{cpSync as tJ$,existsSync as lx2,mkdirSync as eJ$,mkdtempSync as AF$,rmSync as QF$}from"fs";import{tmpdir as $F$}from"os";import{fileURLToPath as wF$}from"url";import{join as BF$,resolve as XF$}from"path";function Pf(A,Q){let $=ix2("git",Q,{cwd:A,stdio:"pipe"});if($.status!==0){let w=$.stderr.toString().trim(),B=$.stdout.toString().trim();throw Error(w||B||`git ${Q.join(" ")} failed`)}}function YF$(A){return A.startsWith("file://")}function ZF$(A){return wF$(A)}function WF$(A,Q){return ix2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function dx2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!YF$(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",$=ZF$(A.gitUrl),w=XF$(A.seedContentPath);if(!lx2(w))throw Error(`Seed content path not found: ${w}`);if(!lx2($))A.logger.debug("Creating local bare content remote",{remotePath:$,branch:Q}),eJ$($,{recursive:!0}),Pf(process.cwd(),["init","--bare",`--initial-branch=${Q}`,$]);if(WF$($,Q)){A.logger.debug("Content remote already initialized",{remotePath:$,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:$,seedPath:w,branch:Q});let B=AF$(BF$($F$(),"directory-sync-seed-"));try{Pf(B,["init",`--initial-branch=${Q}`]),Pf(B,["config","user.name",A.authorName??"Brain"]),Pf(B,["config","user.email",A.authorEmail??"brain@localhost"]),tJ$(w,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),Pf(B,["add","."]),Pf(B,["commit","-m","seed content remote"]),Pf(B,["remote","add","origin",A.gitUrl]),Pf(B,["push","-u","origin",Q])}finally{QF$(B,{recursive:!0,force:!0})}}function nx2(A,Q,$,w,B,X,Y){let{subscribe:Z}=A.messaging;Z("entity:export:request",async(H)=>{try{return{success:!0,data:await Q().exportEntities(H.payload.entityTypes)}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Export failed"}}}),Z("entity:import:request",async(H)=>{try{let K=Q(),U=H.payload.paths,G=await K.importEntities(U);if(U&&U.length>0)await K.removeOrphanedEntities();return{success:!0,data:G}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Import failed"}}}),Z("sync:status:request",async()=>{try{let K=await Q().getStatus(),U=Y?.();return{success:!0,data:{syncPath:K.syncPath,isInitialized:K.exists,watchEnabled:K.watching,lastSync:K.lastSync?.toISOString()??null,totalFiles:K.stats.totalFiles,byEntityType:K.stats.byEntityType,git:await HF$(X?.(),w),...U?{managementUrl:U}:{}}}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Status check failed"}}}),Z("sync:configure:request",async(H)=>{try{return await $({syncPath:H.payload.syncPath}),{success:!0,data:{syncPath:H.payload.syncPath,configured:!0}}}catch(K){return{success:!1,error:K instanceof Error?K.message:"Configuration failed"}}}),Z("git-sync:get-repo-info",async()=>{if(!B?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:B.repo,branch:B.branch??"main"}}}),w.debug("Registered message handlers")}async function HF$(A,Q){if(!A)return null;try{let $=await A.getStatus();return{branch:$.branch,hasChanges:$.hasChanges,ahead:$.ahead,behind:$.behind,lastCommit:$.lastCommit??null,remote:$.remote??null}}catch($){return Q.debug("Git status unavailable for sync:status:request",{error:$}),null}}zA();h0();async function Db0(A){let Q=await A.operationStatus?.startRun("manual",A.gitSync?"pulling":"scanning");try{if(A.gitSync){let w=await A.context.jobs.enqueue({type:"sync-request",data:{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId},...A.toolContext?{toolContext:A.toolContext}:{}});if(Q)await A.operationStatus?.attachJob(Q,w);return{...Q?{runId:Q}:{},gitPulled:!0,jobId:w,status:"queued"}}let $=await A.directorySync.queueSyncBatch(A.context,A.source,{interfaceType:A.interfaceType,channelId:A.channelId});if(!$){if(Q)await A.operationStatus?.completeRun(Q,"No files to sync");return{...Q?{runId:Q}:{},gitPulled:!1,status:"settled"}}if(Q)await A.operationStatus?.attachBatch(Q,$.batchId);return{...Q?{runId:Q}:{},...$,gitPulled:!1,status:"queued"}}catch($){if(Q)await A.operationStatus?.failRun(Q,$ instanceof Error?$.message:"Sync request failed",A.gitSync?"git":"source");throw $}}zA();h0();function rx2(A,Q){return e8(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",W.object({entityType:W.string().describe("Entity type (e.g. post, note, link)"),id:W.string().describe("Entity ID"),sha:W.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:W.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async($)=>{let w=`${$.entityType}/${$.id}.md`;try{if($.sha){let X=await Q.show($.sha,w);return d7({sha:$.sha,entityType:$.entityType,id:$.id,content:X},`Content at ${$.sha.slice(0,7)}`)}let B=await Q.log(w,$.limit);if(B.length===0)return d7({commits:[]},`No history found for ${$.entityType}/${$.id}`);return d7({commits:B,entityType:$.entityType,id:$.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return jY(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function ox2(A,Q,$,w,B){let X=[e8($,"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.",W.object({}),async(Y,Z)=>{try{let H=Z.channelId?`${Z.interfaceType}:${Z.channelId}`:`plugin:${$}`,K=await Db0({context:Q,directorySync:A,source:H,interfaceType:Z.interfaceType,channelId:Z.channelId,toolContext:Z,gitSync:w,operationStatus:B});if(K.gitPulled)return d7({jobId:K.jobId,status:K.status,gitPulled:!0,...K.runId?{runId:K.runId}:{}},"Sync queued: git pull and filesystem scan will run in the background");if(K.status==="settled")return d7({gitPulled:!1,...K.runId?{runId:K.runId}:{}},"No files to sync");return d7({batchId:K.batchId,importOperations:K.importOperationsCount,totalFiles:K.totalFiles,gitPulled:!1,...K.runId?{runId:K.runId}:{}},`Sync started: ${K.importOperationsCount} import jobs queued for ${K.totalFiles} files`)}catch(H){return jY(H instanceof Error?H.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),e8($,"status","Read directory and git sync status: last sync, watcher state, and pending git changes. Use this for every status follow-up after directory-sync_sync, even when that call returned a jobId; a sync jobId is not a system_job_status batchId.",W.object({}),async()=>{try{let Y=await A.getStatus(),Z={syncPath:Y.syncPath,lastSync:Y.lastSync?.toISOString(),watching:Y.watching};if(w){let H=await w.getStatus();Z.git={isRepo:H.isRepo,branch:H.branch,hasChanges:H.hasChanges,ahead:H.ahead,behind:H.behind,remote:H.remote}}return d7(Z)}catch(Y){return jY(Y instanceof Error?Y.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(w)X.push(rx2($,w));return X}zA();h0();import{isAbsolute as sx2,relative as KF$}from"path";var QR2=W.enum(["manual","periodic","watcher","save"]),UF$=W.enum(["pulling","scanning","importing","settling"]),$R2={imported:W.number().int().nonnegative(),skipped:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),quarantined:W.number().int().nonnegative(),exported:W.number().int().nonnegative()},GF$=W.object({id:W.string().min(1),source:QR2,state:UF$,startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...$R2}),DF$=W.object({id:W.string().min(1),source:QR2,outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1).max(240),...$R2}),qF$=W.object({id:W.string().min(1),kind:W.enum(["quarantined","import","export","git","source"]),path:W.string().min(1).max(300).optional(),message:W.string().min(1).max(400),occurredAt:W.string().datetime()}),ax2=W.object({activeRun:GF$.optional(),recentRuns:W.array(DF$).max(5),issues:W.array(qF$).max(8)}),zF$=W.object({gitPulled:W.literal(!0),batchQueued:W.boolean(),batchId:W.string().optional(),importOperations:W.number().int().nonnegative().optional(),totalFiles:W.number().int().nonnegative().optional()}),tx2={imported:0,skipped:0,failed:0,quarantined:0,exported:0},VF$={recentRuns:[],issues:[]},JF$="directory-sync.operation-status",ex2="current";class DDA{store;jobs;logger;syncPath;statePromise;writeQueue=Promise.resolve();constructor(A,Q,$,w){this.store=A.scoped({namespace:JF$,schema:ax2}),this.jobs=Q,this.logger=$,this.syncPath=w}setSyncPath(A){this.syncPath=A}async initialize(){let A=await this.load();if(A.activeRun&&!A.activeRun.jobId&&!A.activeRun.batchId){await this.clearRun(A.activeRun.id);return}await this.reconcile()}startRun(A,Q){let $=O4();return this.mutate((w)=>{if(w.activeRun)return;return w.activeRun={id:$,source:A,state:Q,startedAt:new Date().toISOString(),...tx2},$})}markPhase(A,Q){return this.mutate(($)=>{if($.activeRun?.id===A)$.activeRun.state=Q})}attachJob(A,Q){return this.mutate(($)=>{if($.activeRun?.id!==A)return;$.activeRun.jobId=Q,$.activeRun.state="pulling"})}attachBatch(A,Q){return this.mutate(($)=>{if($.activeRun?.id!==A)return;delete $.activeRun.jobId,$.activeRun.batchId=Q,$.activeRun.state="importing"})}addImportResult(A){return this.mutate((Q)=>{if(Q.activeRun)Q.activeRun.imported+=A.imported,Q.activeRun.skipped+=A.skipped,Q.activeRun.failed+=A.failed,Q.activeRun.quarantined+=A.quarantined;let $=[...A.errors.map((w)=>({kind:"import",path:this.safePath(w.path),message:w.error})),...A.quarantinedFiles.map((w)=>({kind:"quarantined",path:this.safePath(w),message:"File was quarantined because it could not be imported"}))];if($.length===0)Q.issues=Q.issues.filter((w)=>w.kind!=="import"&&w.kind!=="quarantined");else for(let w of $)this.prependIssue(Q,w)})}addExportResult(A){return this.mutate((Q)=>{if(Q.activeRun)Q.activeRun.exported+=A.exported,Q.activeRun.failed+=A.failed;if(A.errors.length===0){Q.issues=Q.issues.filter(($)=>$.kind!=="export");return}for(let $ of A.errors)this.prependIssue(Q,{kind:"export",path:`${$.entityType}/${$.entityId}.md`,message:$.error})})}recordIssue(A){return this.mutate((Q)=>this.prependIssue(Q,A))}clearIssues(A){return this.mutate((Q)=>{Q.issues=Q.issues.filter(($)=>!A.includes($.kind))})}completeRun(A,Q){return this.finishRun(A,"succeeded",Q)}clearRun(A){return this.mutate((Q)=>{if(Q.activeRun?.id===A)delete Q.activeRun})}failRun(A,Q,$="git"){return this.mutate((w)=>{let B=w.activeRun;if(B?.id!==A)return;let X=qb0(Q);this.prependRecent(w,B,"failed",X),this.prependIssue(w,{kind:$,message:X}),delete w.activeRun})}recordTerminal(A,Q,$,w={}){return this.mutate((B)=>{let X=new Date().toISOString();this.prependRecent(B,{id:O4(),source:A,state:"settling",startedAt:X,...tx2,...w},Q,$)})}async reconcile(){await this.writeQueue;let A=await this.load(),Q=A.activeRun?{...A.activeRun}:void 0;if(!Q)return;try{if(Q.jobId){let $=await this.jobs.getStatus(Q.jobId);if(!$){await this.failRun(Q.id,"The active sync job could not be found after restart","source");return}if($.status==="pending"||$.status==="processing"){await this.markPhase(Q.id,"pulling");return}if($.status==="failed"){await this.failRun(Q.id,$.lastError??"Git-backed sync failed");return}let w=zF$.safeParse(FF$($.result));if(!w.success){await this.failRun(Q.id,"Sync job completed without a readable result","source");return}if(w.data.batchQueued&&w.data.batchId)return await this.attachBatch(Q.id,w.data.batchId),await this.reconcile();await this.completeRun(Q.id,"Remote checked; no files to import");return}if(Q.batchId){let $=await this.jobs.getBatchStatus(Q.batchId);if(!$){await this.failRun(Q.id,"The active sync batch could not be recovered after restart","source");return}if($.status==="pending"||$.status==="processing"){await this.markPhase(Q.id,"importing");return}if($.status==="failed"){await this.failRun(Q.id,$.errors.join("; ")||"Directory import batch failed","import");return}await this.completeRun(Q.id,`${$.completedOperations} sync operations completed`)}}catch($){this.logger.debug("Unable to reconcile directory sync operation",{error:$})}}async getSnapshot(){await this.reconcile(),await this.writeQueue;let A=await this.load();return structuredClone(A)}finishRun(A,Q,$){return this.mutate((w)=>{let B=w.activeRun;if(B?.id!==A)return;let X=B.failed>0||B.quarantined>0?"attention":Q;if(this.prependRecent(w,B,X,$),delete w.activeRun,X==="succeeded")w.issues=w.issues.filter((Y)=>Y.kind!=="git"&&Y.kind!=="source")})}load(){return this.statePromise??=this.store.get(ex2).then((A)=>A??structuredClone(VF$)),this.statePromise}mutate(A){let Q=this.writeQueue.then(async()=>{let $=await this.load(),w=A($);return await this.persist($),w});return this.writeQueue=Q.then(()=>{return},()=>{return}),Q}persist(A){return this.store.set(ex2,ax2.parse(A))}prependRecent(A,Q,$,w){let B={id:Q.id,source:Q.source,outcome:$,startedAt:Q.startedAt,completedAt:new Date().toISOString(),summary:qb0(w,240),imported:Q.imported,skipped:Q.skipped,failed:Q.failed,quarantined:Q.quarantined,exported:Q.exported};A.recentRuns=[B,...A.recentRuns.filter((X)=>X.id!==B.id)].slice(0,5)}prependIssue(A,Q){let $=Q.path?this.safePath(Q.path):void 0,w={id:`${Q.kind}:${$??qb0(Q.message,80)}`,kind:Q.kind,...$?{path:$}:{},message:qb0(Q.message),occurredAt:new Date().toISOString()};A.issues=[w,...A.issues.filter((B)=>B.id!==w.id)].slice(0,8)}safePath(A){if(!sx2(A))return AR2(A);let Q=KF$(this.syncPath,A);if(Q.startsWith("..")||sx2(Q))return"content file";return AR2(Q)}}function FF$(A){if(typeof A!=="string")return A;try{return JSON.parse(A)}catch{return A}}function AR2(A){return A.replaceAll("\\","/").replace(/^\.\//,"").slice(0,300)||"content file"}function qb0(A,Q=400){return A.replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+:[^\s/@]+@/gi,"$1[redacted]@").replace(/(token|password|authorization)=([^\s&]+)/gi,"$1=[redacted]").replace(/\s+/g," ").trim().slice(0,Q)||"Directory sync operation failed"}zA();h0();import{basename as LF$}from"path";var IF$=W.object({workspaceUrl:W.string()}),NF$=W.object({type:W.literal("sync-now")}),wR2={imported:W.number().int().nonnegative(),skipped:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),quarantined:W.number().int().nonnegative(),exported:W.number().int().nonnegative()},_F$=W.object({health:W.enum(["healthy","active","attention"]),directory:W.object({displayPath:W.string().min(1),exists:W.boolean(),watching:W.boolean(),totalFiles:W.number().int().nonnegative(),byEntityType:W.record(W.string(),W.number().int().nonnegative()),lastSettledAt:W.string().datetime().optional()}),git:W.object({branch:W.string().min(1),remoteLabel:W.string().min(1).optional(),hasChanges:W.boolean(),ahead:W.number().int().nonnegative(),behind:W.number().int().nonnegative(),lastCommit:W.string().min(1).optional(),changedFiles:W.array(W.object({path:W.string().min(1),status:W.string().min(1)})),changedFilesTruncated:W.boolean()}).nullable(),automation:W.object({autoSync:W.boolean(),watchIntervalMs:W.number().int().nonnegative(),remoteIntervalMinutes:W.number().nonnegative().optional(),commitDebounceMs:W.number().int().nonnegative().optional(),deleteOnFileRemoval:W.boolean()}),activeRun:W.object({id:W.string().min(1),source:W.enum(["manual","periodic","watcher","save"]),state:W.enum(["pulling","scanning","importing","settling"]),startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...wR2}).optional(),recentRuns:W.array(W.object({id:W.string().min(1),source:W.enum(["manual","periodic","watcher","save"]),outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1),...wR2})),issues:W.array(W.object({id:W.string().min(1),kind:W.enum(["quarantined","import","export","git","source"]),path:W.string().min(1).optional(),message:W.string().min(1),occurredAt:W.string().datetime()}))});class qDA{options;constructor(A){this.options=A}async getSnapshot(){let A=await this.options.getDirectorySync().getStatus();this.options.operationStatus.setSyncPath(A.syncPath);let Q,$=this.options.getGitSync();if($)try{if(Q=await $.getStatus(),!Q.hasChanges&&Q.ahead===0&&Q.behind===0)await this.options.operationStatus.clearIssues(["git"])}catch(Y){await this.options.operationStatus.recordIssue({kind:"git",message:Y instanceof Error?Y.message:"Git status unavailable"})}if(!A.exists)await this.options.operationStatus.recordIssue({kind:"source",message:"The configured sync directory is unavailable"});else await this.options.operationStatus.clearIssues(["source"]);let w=await this.options.operationStatus.getSnapshot(),B=w.recentRuns[0]?.completedAt??A.lastSync?.toISOString(),X=w.activeRun?"active":w.issues.length>0?"attention":"healthy";return _F$.parse({health:X,directory:{displayPath:LF$(A.syncPath)||"brain-data",exists:A.exists,watching:A.watching,totalFiles:A.stats.totalFiles,byEntityType:A.stats.byEntityType,...B?{lastSettledAt:B}:{}},git:Q?this.toSafeGitStatus(Q):null,automation:{autoSync:this.options.config.autoSync,watchIntervalMs:this.options.config.watchInterval,...$?{remoteIntervalMinutes:this.options.config.syncInterval,commitDebounceMs:this.options.config.commitDebounce}:{},deleteOnFileRemoval:this.options.config.deleteOnFileRemoval},...w.activeRun?{activeRun:w.activeRun}:{},recentRuns:w.recentRuns,issues:w.issues})}async registerCmsWorkspace(){let A={id:"sync",pluginId:this.options.pluginId,label:"Sync",rendererName:"DirectorySyncWorkspace",priority:60,dataProvider:()=>this.getSnapshot(),actionHandler:async(w,B)=>{if(!$9.hasPermission(B.userPermissionLevel,"anchor"))throw Error("Directory sync requires anchor permission");if(!NF$.safeParse(w).success)throw Error("Invalid directory sync workspace action");let Y={interfaceType:"cms",userId:B.userId,userPermissionLevel:B.userPermissionLevel},Z=await Db0({context:this.options.context,directorySync:this.options.getDirectorySync(),source:`cms:${B.userId}`,interfaceType:"cms",toolContext:Y,gitSync:this.options.getGitSync(),operationStatus:this.options.operationStatus});return{accepted:Z.status==="queued",status:Z.status,...Z.runId?{runId:Z.runId}:{},...Z.gitPulled?{jobId:Z.jobId}:{},...!Z.gitPulled&&Z.status==="queued"?{batchId:Z.batchId}:{}}}},Q=await this.options.context.messaging.send({type:v_,payload:A});if(!("success"in Q)||!Q.success)return;let $=IF$.safeParse(Q.data);return $.success?$.data.workspaceUrl:void 0}toSafeGitStatus(A){let Q=A.files.slice(0,20).map((w)=>({path:PF$(w.path),status:w.status.trim()||"changed"})),$=bF$(this.options.config);return{branch:A.branch,...$?{remoteLabel:$}:{},hasChanges:A.hasChanges,ahead:A.ahead,behind:A.behind,...A.lastCommit?{lastCommit:A.lastCommit}:{},changedFiles:Q,changedFilesTruncated:A.files.length>Q.length}}}function PF$(A){let Q=A.replaceAll("\\","/").replace(/^\.\//,"");if(Q.startsWith("../")||Q.startsWith("/"))return"content file";return Q.slice(0,300)||"content file"}function bF$(A){if(A.git?.repo)return A.git.repo;let Q=A.git?.gitUrl;if(!Q)return;if(Q.startsWith("file:"))return"local remote";try{let $=new URL(Q),w=$.pathname.replace(/^\//,"").replace(/\.git$/,"");return w?`${$.hostname}/${w}`:$.hostname}catch{let $=/^(?:[^@]+@)?([^:]+):(.+?)(?:\.git)?$/.exec(Q);if(!$?.[1]||!$[2])return"configured remote";return`${$[1]}/${$[2].replace(/\.git$/,"")}`}}c8();class zb0{resourceScope;scheduleScope;periodicScope;delayScope;scheduleFibers;periodicFibers;delayedFibers;clock;activeOperations=new Set;activeFailures=[];nextPeriodicId=0;closePromise=null;closed=!1;constructor(A={}){this.resourceScope=t0.runSync(j2.make()),this.scheduleScope=t0.runSync(j2.make()),this.periodicScope=t0.runSync(j2.make()),this.delayScope=t0.runSync(j2.make()),this.scheduleFibers=t0.runSync(j2.extend(RZ.make(),this.scheduleScope)),this.periodicFibers=t0.runSync(j2.extend(Vw.make(),this.periodicScope)),this.delayedFibers=t0.runSync(j2.extend(Vw.make(),this.delayScope)),this.clock=A.clock}async acquire(A,Q){if(this.closed)throw Error("Directory sync runtime is closed");let $=t0.acquireRelease(t0.promise(A),(B)=>t0.promise(()=>Q(B))),w=await t0.runPromiseExit(j2.extend($,this.resourceScope));if(y2.isFailure(w))throw a$.squash(w.cause);return w.value}schedulePeriodic(A,Q){if(this.closed)return;if(!Number.isFinite(A)||A<=0)throw Error("Periodic interval must be a positive finite number");let $=this.nextPeriodicId++,w=()=>{if(this.closed||Vw.unsafeHas(this.periodicFibers,$))return;let Y=t0.tryPromise({try:Q,catch:(Z)=>Z}).pipe(t0.catchAll((Z)=>t0.sync(()=>{this.activeFailures.push(Z)})));Vw.unsafeSet(this.periodicFibers,$,t0.runFork(Y),{onlyIfMissing:!0})},B=t0.sleep(A).pipe(t0.andThen(t0.sync(w)),t0.forever),X=this.clock?t0.withClock(B,this.clock):B;RZ.unsafeAdd(this.scheduleFibers,t0.runFork(X))}scheduleTrailing(A,Q,$){if(this.closed)return;let w=t0.sleep(Q).pipe(t0.andThen(t0.sync(()=>{this.trackActive($)}))),B=this.clock?t0.withClock(w,this.clock):w,X=t0.runFork(B);Vw.unsafeSet(this.delayedFibers,A,X)}close(){return this.closed=!0,this.closePromise??=this.closeRuntime(),this.closePromise}trackActive(A){if(this.closed)return;let Q;try{Q=A()}catch(w){Q=Promise.reject(w)}let $=Q.catch((w)=>{this.activeFailures.push(w)}).finally(()=>{this.activeOperations.delete($)});this.activeOperations.add($)}async closeRuntime(){let A=[],Q=async($)=>{try{await $()}catch(w){A.push(w)}};await Q(()=>this.closeScope(this.scheduleScope)),await Q(()=>this.closeScope(this.periodicScope)),await Q(()=>this.closeScope(this.delayScope)),await Q(()=>this.closeScope(this.resourceScope));while(this.activeOperations.size>0)await Promise.all([...this.activeOperations]);if(A.push(...this.activeFailures),A.length>0)throw A[0]}async closeScope(A){let Q=await t0.runPromiseExit(j2.close(A,y2.void));if(y2.isFailure(Q))throw a$.squash(Q.cause)}}function BR2(A){return{initialize:()=>A().initialize(),initializeDirectory:()=>A().initializeDirectory(),setJobQueueCallback:(Q)=>A().setJobQueueCallback(Q),sync:()=>A().sync(),processEntityExport:(Q)=>A().processEntityExport(Q),exportEntities:(Q)=>A().exportEntities(Q),importEntitiesWithProgress:(Q,$,w)=>A().importEntitiesWithProgress(Q,$,w),exportEntitiesWithProgress:(Q,$,w)=>A().exportEntitiesWithProgress(Q,$,w),importEntities:(Q)=>A().importEntities(Q),removeOrphanedEntities:()=>A().removeOrphanedEntities(),get fileOps(){return A().fileOps},get shouldDeleteOnFileRemoval(){return A().shouldDeleteOnFileRemoval},getAllMarkdownFiles:()=>A().getAllMarkdownFiles(),ensureDirectoryStructure:()=>A().ensureDirectoryStructure(),getStatus:()=>A().getStatus(),queueSyncBatch:(Q,$,w)=>A().queueSyncBatch(Q,$,w),startWatching:()=>A().startWatching(),stopWatching:()=>A().stopWatching(),setWatchCallback:(Q)=>A().setWatchCallback(Q)}}function XR2(A){return{withLock:(Q,$)=>A().withLock(Q,$),initialize:()=>A().initialize(),hasRemote:()=>A().hasRemote(),getStatus:()=>A().getStatus(),hasLocalChanges:()=>A().hasLocalChanges(),commit:(Q)=>A().commit(Q),push:(Q)=>A().push(Q),pull:(Q)=>A().pull(Q),cleanup:()=>A().cleanup(),log:(Q,$)=>A().log(Q,$),show:(Q,$)=>A().show(Q,$)}}var YR2={name:"@brains/directory-sync",version:"0.2.0-alpha.196",description:"Directory-based entity synchronization plugin for Brains",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chokidar:"^5.0.0","simple-git":"^3.36.0"},devDependencies:{"@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./env-schema":"./src/env-schema.ts"},main:"./src/index.ts",peerDependencies:{},private:!0,scripts:{clean:"rm -rf .turbo",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class zDA extends d6{directorySync;gitSync;operationStatus;workspaceProvider;cmsWorkspaceUrl;runtime=new zb0;directorySyncFacade=BR2(()=>this.requireDirectorySync());gitSyncFacade=XR2(()=>this.requireGitSync());runtimeScheduler={scheduleTrailing:(A,Q,$)=>{this.runtime.scheduleTrailing(A,Q,$)}};watcherOwned=!1;gitBackgroundStarted=!1;gitAutoCommitRegistered=!1;readyState=!1;shutdownStarted=!1;configurationQueue=Promise.resolve();constructor(A={}){super("directory-sync",YR2,A,J50)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}requireGitSync(){if(!this.gitSync)throw Error("GitSync service not initialized");return this.gitSync}requireOperationStatus(){if(!this.operationStatus)throw Error("Directory sync operation status not initialized");return this.operationStatus}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:F50,basePrompt:"",formatter:new Bb0,requiredPermission:"anchor"}});let Q=this.config.syncPath??A.dataDir;this.directorySync=this.createDirectorySync(A,Q);try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:Q})}catch($){throw this.logger.error("Failed to initialize directory",$),$}if(this.operationStatus=new DDA(A.runtimeState,A.jobs,this.logger.child("OperationStatus"),Q),await this.operationStatus.initialize(),this.config.autoSync)UDA(A,this.directorySync,Q,this.operationStatus);if(await this.registerJobHandlers(A),Ex2(A,()=>this.requireDirectorySync(),this.logger,this.config.entityTypes,this.operationStatus),this.config.git&&!this.isGitConfigured())this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(this.isGitConfigured())await this.bootstrapContentRemote(),this.gitSync=await this.initializeGitSync(Q),A.jobs.registerHandler("sync-request",new Wb0(this.logger.child("DirectorySyncRequestJobHandler"),A,()=>this.requireDirectorySync(),()=>this.requireGitSync()));if(this.config.initialSync)ux2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync?this.gitSyncFacade:void 0);this.workspaceProvider=new qDA({context:A,pluginId:this.id,config:this.config,getDirectorySync:()=>this.requireDirectorySync(),getGitSync:()=>this.gitSync,operationStatus:this.operationStatus}),nx2(A,()=>this.requireDirectorySync(),($)=>this.configure($),this.logger,this.config.git,()=>this.gitSync,()=>this.cmsWorkspaceUrl)}async onReady(){await this.startBackgroundWork(),this.readyState=!0,this.cmsWorkspaceUrl=await this.workspaceProvider?.registerCmsWorkspace()}async getTools(){return ox2(this.directorySyncFacade,this.getContext(),this.id,this.gitSync?this.gitSyncFacade:void 0,this.operationStatus)}async onShutdown(){this.shutdownStarted=!0,await this.configurationQueue,await this.stopGeneration(this.runtime,this.directorySync,this.gitSync),this.readyState=!1,this.watcherOwned=!1,this.gitBackgroundStarted=!1}getDirectorySync(){return this.directorySync}configure(A){let Q=this.configurationQueue.then(()=>this.replaceGeneration(A.syncPath));return this.configurationQueue=Q.catch(()=>{}),Q}async replaceGeneration(A){if(this.shutdownStarted)throw Error("Directory sync plugin is shutting down");let Q=this.getContext(),$=new zb0,w=this.createDirectorySync(Q,A),B;try{if(await w.initializeDirectory(),this.config.autoSync)UDA(Q,w,A,this.operationStatus);if(this.isGitConfigured())B=await this.initializeGitSync(A)}catch(H){throw await this.abandonCandidate($,w,B),H}let X=this.runtime,Y=this.directorySync,Z=this.gitSync;try{await this.stopGeneration(X,Y,Z)}catch(H){throw await this.abandonCandidate($,w,B),H}if(this.runtime=$,this.directorySync=w,this.gitSync=B,this.operationStatus?.setSyncPath(A),this.watcherOwned=!1,this.gitBackgroundStarted=!1,this.readyState)await this.startBackgroundWork();this.logger.info("Directory sync reconfigured",{path:A})}createDirectorySync(A,Q){return new EP0({syncPath:Q,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:A.entityService,logger:A.logger})}isGitConfigured(){return this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0)}async bootstrapContentRemote(){let A=this.config.git;if(!A)return;await dx2({gitUrl:A.gitUrl,branch:A.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:A.bootstrapFromSeed,authorName:A.authorName,authorEmail:A.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")})}async initializeGitSync(A){let Q=this.config.git;if(!Q)throw Error("Git configuration is unavailable");let $=new BDA({logger:this.logger.child("GitSync"),dataDir:A,repo:Q.repo,gitUrl:Q.gitUrl,branch:Q.branch,authToken:Q.authToken,authorName:Q.authorName,authorEmail:Q.authorEmail});return await $.initialize(),this.logger.info("Git integration enabled",{repo:Q.repo}),$}async startBackgroundWork(){let A=this.requireDirectorySync();if(this.config.autoSync&&!this.watcherOwned)await this.runtime.acquire(()=>A.startWatching(),()=>A.stopWatching()),this.watcherOwned=!0;let Q=this.gitSync;if(!Q||this.gitBackgroundStarted)return;let $=this.getContext();if(!this.gitAutoCommitRegistered)cx2($.messaging,()=>this.requireGitSync(),this.config.commitDebounce,this.logger.child("GitAutoCommit"),this.runtimeScheduler,this.operationStatus),this.gitAutoCommitRegistered=!0;if(this.config.autoSync)px2(Q,A,$,this.config.syncInterval,this.logger.child("GitPeriodicSync"),this.runtime,this.operationStatus);this.gitBackgroundStarted=!0}async stopGeneration(A,Q,$){let w=[];try{await A.close()}catch(B){w.push(B)}try{await Q?.stopWatching()}catch(B){w.push(B)}try{$?.cleanup()}catch(B){w.push(B)}if(w.length>0)throw w[0]}async abandonCandidate(A,Q,$){try{await A.close()}catch{}try{await Q.stopWatching()}catch{}try{$?.cleanup()}catch{}}async registerJobHandlers(A){hx2(A,this.directorySyncFacade,this.logger,()=>this.requireDirectorySync(),this.requireOperationStatus())}}function RT(A={}){return new zDA(A)}h0();var Vb0="email:send",ZR2=W.strictObject({to:W.string().email(),subject:W.string().min(1),text:W.string().min(1),html:W.string().min(1).optional(),sensitivity:W.enum(["normal","secret"]).default("normal")});zA();h0();var WR2={name:"@brains/email-resend",version:"0.2.0-alpha.196",description:"Generic email delivery adapter for Resend",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var kF$=W.object({apiKey:W.string().min(1).optional(),from:W.string().min(1).optional()}),OF$=W.looseObject({id:W.string().optional()});class HR2 extends d6{fetchImpl;constructor(A={},Q={}){super("email-resend",WR2,A,kF$);this.fetchImpl=Q.fetchImpl??fetch}async onRegister(A){if(!this.config.apiKey||!this.config.from){this.logger.warn("Email Resend adapter is disabled because apiKey or from is missing");return}let Q=this.logger;A.messaging.subscribe(Vb0,async($)=>{let w=ZR2.parse($.payload);try{return{success:!0,data:await this.sendWithResend(w)}}catch(B){if(w.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:w.to,subject:w.subject,error:B instanceof Error?B.message:String(B)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,$=this.config.from;if(!Q||!$)return{status:"failed"};let w=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:$,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!w.ok)throw Error("Resend email request failed");let B=OF$.parse(await w.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function Jb0(A={}){return new HR2(A)}zA();import{render as od2}from"preact-render-to-string";import{h as Dy}from"preact";function KR2(A){var Q,$,w="";if(typeof A=="string"||typeof A=="number")w+=A;else if(typeof A=="object")if(Array.isArray(A)){var B=A.length;for(Q=0;Q<B;Q++)A[Q]&&($=KR2(A[Q]))&&(w&&(w+=" "),w+=$)}else for($ in A)A[$]&&(w&&(w+=" "),w+=$);return w}function bn(){for(var A,Q,$=0,w="",B=arguments.length;$<B;$++)(A=arguments[$])&&(Q=KR2(A))&&(w&&(w+=" "),w+=Q);return w}var fF$=(A,Q)=>{let $=Array(A.length+Q.length);for(let w=0;w<A.length;w++)$[w]=A[w];for(let w=0;w<Q.length;w++)$[A.length+w]=Q[w];return $},xF$=(A,Q)=>({classGroupId:A,validator:Q}),FR2=(A=new Map,Q=null,$)=>({nextPart:A,validators:Q,classGroupId:$});var UR2=[];var RF$=(A)=>{let Q=CF$(A),{conflictingClassGroups:$,conflictingClassGroupModifiers:w}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return vF$(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return LR2(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=w[Y],K=$[Y];if(H){if(K)return fF$(K,H);return H}return K||UR2}return $[Y]||UR2}}},LR2=(A,Q,$)=>{if(A.length-Q===0)return $.classGroupId;let B=A[Q],X=$.nextPart.get(B);if(X){let K=LR2(A,Q+1,X);if(K)return K}let Y=$.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let K=0;K<H;K++){let U=Y[K];if(U.validator(Z))return U.classGroupId}return},vF$=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),$=Q.indexOf(":"),w=Q.slice(0,$);return w?"arbitrary.."+w:void 0})(),CF$=(A)=>{let{theme:Q,classGroups:$}=A;return hF$($,Q)},hF$=(A,Q)=>{let $=FR2();for(let w in A){let B=A[w];FDA(B,$,w,Q)}return $},FDA=(A,Q,$,w)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];EF$(Y,Q,$,w)}},EF$=(A,Q,$,w)=>{if(typeof A==="string"){TF$(A,Q,$);return}if(typeof A==="function"){yF$(A,Q,$,w);return}gF$(A,Q,$,w)},TF$=(A,Q,$)=>{let w=A===""?Q:IR2(Q,A);w.classGroupId=$},yF$=(A,Q,$,w)=>{if(SF$(A)){FDA(A(w),Q,$,w);return}if(Q.validators===null)Q.validators=[];Q.validators.push(xF$($,A))},gF$=(A,Q,$,w)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];FDA(H,IR2(Q,Z),$,w)}},IR2=(A,Q)=>{let $=A,w=Q.split("-"),B=w.length;for(let X=0;X<B;X++){let Y=w[X],Z=$.nextPart.get(Y);if(!Z)Z=FR2(),$.nextPart.set(Y,Z);$=Z}return $},SF$=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,mF$=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,$=Object.create(null),w=Object.create(null),B=(X,Y)=>{if($[X]=Y,Q++,Q>A)Q=0,w=$,$=Object.create(null)};return{get(X){let Y=$[X];if(Y!==void 0)return Y;if((Y=w[X])!==void 0)return B(X,Y),Y},set(X,Y){if(X in $)$[X]=Y;else B(X,Y)}}};var uF$=[],GR2=(A,Q,$,w,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:$,maybePostfixModifierPosition:w,isExternal:B}),cF$=(A)=>{let{prefix:Q,experimentalParseClassName:$}=A,w=(B)=>{let X=[],Y=0,Z=0,H=0,K,U=B.length;for(let F=0;F<U;F++){let L=B[F];if(Y===0&&Z===0){if(L===":"){X.push(B.slice(H,F)),H=F+1;continue}if(L==="/"){K=F;continue}}if(L==="[")Y++;else if(L==="]")Y--;else if(L==="(")Z++;else if(L===")")Z--}let G=X.length===0?B:B.slice(H),D=G,q=!1;if(G.endsWith("!"))D=G.slice(0,-1),q=!0;else if(G.startsWith("!"))D=G.slice(1),q=!0;let J=K&&K>H?K-H:void 0;return GR2(X,q,D,J)};if(Q){let B=Q+":",X=w;w=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):GR2(uF$,!1,Y,void 0,!0)}if($){let B=w;w=(X)=>$({className:X,parseClassName:B})}return w},pF$=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach(($,w)=>{Q.set($,1e6+w)}),($)=>{let w=[],B=[];for(let X=0;X<$.length;X++){let Y=$[X],Z=Y[0]==="[",H=Q.has(Y);if(Z||H){if(B.length>0)B.sort(),w.push(...B),B=[];w.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),w.push(...B);return w}},lF$=(A)=>({cache:mF$(A.cacheSize),parseClassName:cF$(A),sortModifiers:pF$(A),postfixLookupClassGroupIds:iF$(A),...RF$(A)}),iF$=(A)=>{let Q=Object.create(null),$=A.postfixLookupClassGroups;if($)for(let w=0;w<$.length;w++)Q[$[w]]=!0;return Q},dF$=/\s+/,nF$=(A,Q)=>{let{parseClassName:$,getClassGroupId:w,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(dF$),K="";for(let U=H.length-1;U>=0;U-=1){let G=H[U],{isExternal:D,modifiers:q,hasImportantModifier:J,baseClassName:F,maybePostfixModifierPosition:L}=$(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!L,j;if(_){let O=F.substring(0,L);j=w(O);let S=j&&Y[j]?w(F):void 0;if(S&&S!==j)j=S,_=!1}else j=w(F);if(!j){if(!_){K=G+(K.length>0?" "+K:K);continue}if(j=w(F),!j){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=q.length===0?"":q.length===1?q[0]:X(q).join(":"),f=J?b+"!":b,v=f+j;if(Z.indexOf(v)>-1)continue;Z.push(v);let R=B(j,_);for(let O=0;O<R.length;++O){let S=R[O];Z.push(f+S)}K=G+(K.length>0?" "+K:K)}return K},rF$=(...A)=>{let Q=0,$,w,B="";while(Q<A.length)if($=A[Q++]){if(w=NR2($))B&&(B+=" "),B+=w}return B},NR2=(A)=>{if(typeof A==="string")return A;let Q,$="";for(let w=0;w<A.length;w++)if(A[w]){if(Q=NR2(A[w]))$&&($+=" "),$+=Q}return $},DR2=(A,...Q)=>{let $,w,B,X,Y=(H)=>{let K=Q.reduce((U,G)=>G(U),A());return $=lF$(K),w=$.cache.get,B=$.cache.set,X=Z,Z(H)},Z=(H)=>{let K=w(H);if(K)return K;let U=nF$(H,$);return B(H,U),U};return X=Y,(...H)=>X(rF$(...H))},oF$=[],wX=(A)=>{let Q=($)=>$[A]||oF$;return Q.isThemeGetter=!0,Q},_R2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,PR2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,sF$=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,aF$=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,tF$=/\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$/,eF$=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,AL$=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,QL$=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,bf=(A)=>sF$.test(A),y$=(A)=>!!A&&!Number.isNaN(Number(A)),fL=(A)=>!!A&&Number.isInteger(Number(A)),VDA=(A)=>A.endsWith("%")&&y$(A.slice(0,-1)),eP=(A)=>aF$.test(A),bR2=()=>!0,$L$=(A)=>tF$.test(A)&&!eF$.test(A),LDA=()=>!1,wL$=(A)=>AL$.test(A),BL$=(A)=>QL$.test(A),XL$=(A)=>!a2(A)&&!$Q(A),YL$=(A)=>A.startsWith("@container")&&(A[10]==="/"&&A[11]!==void 0||A[11]==="s"&&A[16]!==void 0&&A.startsWith("-size/",10)||A[11]==="n"&&A[18]!==void 0&&A.startsWith("-normal/",10)),ZL$=(A)=>jf(A,kR2,LDA),a2=(A)=>_R2.test(A),vT=(A)=>jf(A,OR2,$L$),qR2=(A)=>jf(A,zL$,y$),WL$=(A)=>jf(A,xR2,bR2),HL$=(A)=>jf(A,fR2,LDA),zR2=(A)=>jf(A,jR2,LDA),KL$=(A)=>jf(A,MR2,BL$),Fb0=(A)=>jf(A,RR2,wL$),$Q=(A)=>PR2.test(A),L50=(A)=>CT(A,OR2),UL$=(A)=>CT(A,fR2),VR2=(A)=>CT(A,jR2),GL$=(A)=>CT(A,kR2),DL$=(A)=>CT(A,MR2),Lb0=(A)=>CT(A,RR2,!0),qL$=(A)=>CT(A,xR2,!0),jf=(A,Q,$)=>{let w=_R2.exec(A);if(w){if(w[1])return Q(w[1]);return $(w[2])}return!1},CT=(A,Q,$=!1)=>{let w=PR2.exec(A);if(w){if(w[1])return Q(w[1]);return $}return!1},jR2=(A)=>A==="position"||A==="percentage",MR2=(A)=>A==="image"||A==="url",kR2=(A)=>A==="length"||A==="size"||A==="bg-size",OR2=(A)=>A==="length",zL$=(A)=>A==="number",fR2=(A)=>A==="family-name",xR2=(A)=>A==="number"||A==="weight",RR2=(A)=>A==="shadow";var JR2=()=>{let A=wX("color"),Q=wX("font"),$=wX("text"),w=wX("font-weight"),B=wX("tracking"),X=wX("leading"),Y=wX("breakpoint"),Z=wX("container"),H=wX("spacing"),K=wX("radius"),U=wX("shadow"),G=wX("inset-shadow"),D=wX("text-shadow"),q=wX("drop-shadow"),J=wX("blur"),F=wX("perspective"),L=wX("aspect"),_=wX("ease"),j=wX("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],f=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...f(),$Q,a2],R=()=>["auto","hidden","clip","visible","scroll"],O=()=>["auto","contain","none"],S=()=>[$Q,a2,H],u=()=>[bf,"full","auto",...S()],i=()=>[fL,"none","subgrid",$Q,a2],a=()=>["auto",{span:["full",fL,$Q,a2]},fL,$Q,a2],B0=()=>[fL,"auto",$Q,a2],p=()=>["auto","min","max","fr",$Q,a2],k=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],T=()=>["start","end","center","stretch","center-safe","end-safe"],E=()=>["auto",...S()],o=()=>[bf,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...S()],t=()=>[bf,"screen","full","dvw","lvw","svw","min","max","fit",...S()],q0=()=>[bf,"screen","full","lh","dvh","lvh","svh","min","max","fit",...S()],g=()=>[A,$Q,a2],Y0=()=>[...f(),VR2,zR2,{position:[$Q,a2]}],F0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],d=()=>["auto","cover","contain",GL$,ZL$,{size:[$Q,a2]}],c0=()=>[VDA,L50,vT],i0=()=>["","none","full",K,$Q,a2],N0=()=>["",y$,L50,vT],b0=()=>["solid","dashed","dotted","double"],v0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[y$,VDA,VR2,zR2],k0=()=>["","none",J,$Q,a2],O0=()=>["none",y$,$Q,a2],f0=()=>["none",y$,$Q,a2],m0=()=>[y$,$Q,a2],o0=()=>[bf,"full",...S()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[eP],breakpoint:[eP],color:[bR2],container:[eP],"drop-shadow":[eP],ease:["in","out","in-out"],font:[XL$],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[eP],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[eP],shadow:[eP],spacing:["px",y$],text:[eP],"text-shadow":[eP],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",bf,a2,$Q,L]}],container:["container"],"container-type":[{"@container":["","normal","size",$Q,a2]}],"container-named":[YL$],columns:[{columns:[y$,a2,$Q,Z]}],"break-after":[{"break-after":b()}],"break-before":[{"break-before":b()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:v()}],overflow:[{overflow:R()}],"overflow-x":[{"overflow-x":R()}],"overflow-y":[{"overflow-y":R()}],overscroll:[{overscroll:O()}],"overscroll-x":[{"overscroll-x":O()}],"overscroll-y":[{"overscroll-y":O()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:u()}],"inset-x":[{"inset-x":u()}],"inset-y":[{"inset-y":u()}],start:[{"inset-s":u(),start:u()}],end:[{"inset-e":u(),end:u()}],"inset-bs":[{"inset-bs":u()}],"inset-be":[{"inset-be":u()}],top:[{top:u()}],right:[{right:u()}],bottom:[{bottom:u()}],left:[{left:u()}],visibility:["visible","invisible","collapse"],z:[{z:[fL,"auto",$Q,a2]}],basis:[{basis:[bf,"full","auto",Z,...S()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[y$,bf,"auto","initial","none",a2]}],grow:[{grow:["",y$,$Q,a2]}],shrink:[{shrink:["",y$,$Q,a2]}],order:[{order:[fL,"first","last","none",$Q,a2]}],"grid-cols":[{"grid-cols":i()}],"col-start-end":[{col:a()}],"col-start":[{"col-start":B0()}],"col-end":[{"col-end":B0()}],"grid-rows":[{"grid-rows":i()}],"row-start-end":[{row:a()}],"row-start":[{"row-start":B0()}],"row-end":[{"row-end":B0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":p()}],"auto-rows":[{"auto-rows":p()}],gap:[{gap:S()}],"gap-x":[{"gap-x":S()}],"gap-y":[{"gap-y":S()}],"justify-content":[{justify:[...k(),"normal"]}],"justify-items":[{"justify-items":[...T(),"normal"]}],"justify-self":[{"justify-self":["auto",...T()]}],"align-content":[{content:["normal",...k()]}],"align-items":[{items:[...T(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...T(),{baseline:["","last"]}]}],"place-content":[{"place-content":k()}],"place-items":[{"place-items":[...T(),"baseline"]}],"place-self":[{"place-self":["auto",...T()]}],p:[{p:S()}],px:[{px:S()}],py:[{py:S()}],ps:[{ps:S()}],pe:[{pe:S()}],pbs:[{pbs:S()}],pbe:[{pbe:S()}],pt:[{pt:S()}],pr:[{pr:S()}],pb:[{pb:S()}],pl:[{pl:S()}],m:[{m:E()}],mx:[{mx:E()}],my:[{my:E()}],ms:[{ms:E()}],me:[{me:E()}],mbs:[{mbs:E()}],mbe:[{mbe:E()}],mt:[{mt:E()}],mr:[{mr:E()}],mb:[{mb:E()}],ml:[{ml:E()}],"space-x":[{"space-x":S()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":S()}],"space-y-reverse":["space-y-reverse"],size:[{size:o()}],"inline-size":[{inline:["auto",...t()]}],"min-inline-size":[{"min-inline":["auto",...t()]}],"max-inline-size":[{"max-inline":["none",...t()]}],"block-size":[{block:["auto",...q0()]}],"min-block-size":[{"min-block":["auto",...q0()]}],"max-block-size":[{"max-block":["none",...q0()]}],w:[{w:[Z,"screen",...o()]}],"min-w":[{"min-w":[Z,"screen","none",...o()]}],"max-w":[{"max-w":[Z,"screen","none","prose",{screen:[Y]},...o()]}],h:[{h:["screen","lh",...o()]}],"min-h":[{"min-h":["screen","lh","none",...o()]}],"max-h":[{"max-h":["screen","lh",...o()]}],"font-size":[{text:["base",$,L50,vT]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[w,qL$,WL$]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",VDA,a2]}],"font-family":[{font:[UL$,HL$,Q]}],"font-features":[{"font-features":[a2]}],"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:[B,$Q,a2]}],"line-clamp":[{"line-clamp":[y$,"none",$Q,qR2]}],leading:[{leading:[X,...S()]}],"list-image":[{"list-image":["none",$Q,a2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",$Q,a2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:g()}],"text-color":[{text:g()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...b0(),"wavy"]}],"text-decoration-thickness":[{decoration:[y$,"from-font","auto",$Q,vT]}],"text-decoration-color":[{decoration:g()}],"underline-offset":[{"underline-offset":[y$,"auto",$Q,a2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:S()}],"tab-size":[{tab:[fL,$Q,a2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",$Q,a2]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",$Q,a2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:Y0()}],"bg-repeat":[{bg:F0()}],"bg-size":[{bg:d()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},fL,$Q,a2],radial:["",$Q,a2],conic:[fL,$Q,a2]},DL$,KL$]}],"bg-color":[{bg:g()}],"gradient-from-pos":[{from:c0()}],"gradient-via-pos":[{via:c0()}],"gradient-to-pos":[{to:c0()}],"gradient-from":[{from:g()}],"gradient-via":[{via:g()}],"gradient-to":[{to:g()}],rounded:[{rounded:i0()}],"rounded-s":[{"rounded-s":i0()}],"rounded-e":[{"rounded-e":i0()}],"rounded-t":[{"rounded-t":i0()}],"rounded-r":[{"rounded-r":i0()}],"rounded-b":[{"rounded-b":i0()}],"rounded-l":[{"rounded-l":i0()}],"rounded-ss":[{"rounded-ss":i0()}],"rounded-se":[{"rounded-se":i0()}],"rounded-ee":[{"rounded-ee":i0()}],"rounded-es":[{"rounded-es":i0()}],"rounded-tl":[{"rounded-tl":i0()}],"rounded-tr":[{"rounded-tr":i0()}],"rounded-br":[{"rounded-br":i0()}],"rounded-bl":[{"rounded-bl":i0()}],"border-w":[{border:N0()}],"border-w-x":[{"border-x":N0()}],"border-w-y":[{"border-y":N0()}],"border-w-s":[{"border-s":N0()}],"border-w-e":[{"border-e":N0()}],"border-w-bs":[{"border-bs":N0()}],"border-w-be":[{"border-be":N0()}],"border-w-t":[{"border-t":N0()}],"border-w-r":[{"border-r":N0()}],"border-w-b":[{"border-b":N0()}],"border-w-l":[{"border-l":N0()}],"divide-x":[{"divide-x":N0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":N0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...b0(),"hidden","none"]}],"divide-style":[{divide:[...b0(),"hidden","none"]}],"border-color":[{border:g()}],"border-color-x":[{"border-x":g()}],"border-color-y":[{"border-y":g()}],"border-color-s":[{"border-s":g()}],"border-color-e":[{"border-e":g()}],"border-color-bs":[{"border-bs":g()}],"border-color-be":[{"border-be":g()}],"border-color-t":[{"border-t":g()}],"border-color-r":[{"border-r":g()}],"border-color-b":[{"border-b":g()}],"border-color-l":[{"border-l":g()}],"divide-color":[{divide:g()}],"outline-style":[{outline:[...b0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[y$,$Q,a2]}],"outline-w":[{outline:["",y$,L50,vT]}],"outline-color":[{outline:g()}],shadow:[{shadow:["","none",U,Lb0,Fb0]}],"shadow-color":[{shadow:g()}],"inset-shadow":[{"inset-shadow":["none",G,Lb0,Fb0]}],"inset-shadow-color":[{"inset-shadow":g()}],"ring-w":[{ring:N0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:g()}],"ring-offset-w":[{"ring-offset":[y$,vT]}],"ring-offset-color":[{"ring-offset":g()}],"inset-ring-w":[{"inset-ring":N0()}],"inset-ring-color":[{"inset-ring":g()}],"text-shadow":[{"text-shadow":["none",D,Lb0,Fb0]}],"text-shadow-color":[{"text-shadow":g()}],opacity:[{opacity:[y$,$Q,a2]}],"mix-blend":[{"mix-blend":[...v0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":v0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[y$]}],"mask-image-linear-from-pos":[{"mask-linear-from":S0()}],"mask-image-linear-to-pos":[{"mask-linear-to":S0()}],"mask-image-linear-from-color":[{"mask-linear-from":g()}],"mask-image-linear-to-color":[{"mask-linear-to":g()}],"mask-image-t-from-pos":[{"mask-t-from":S0()}],"mask-image-t-to-pos":[{"mask-t-to":S0()}],"mask-image-t-from-color":[{"mask-t-from":g()}],"mask-image-t-to-color":[{"mask-t-to":g()}],"mask-image-r-from-pos":[{"mask-r-from":S0()}],"mask-image-r-to-pos":[{"mask-r-to":S0()}],"mask-image-r-from-color":[{"mask-r-from":g()}],"mask-image-r-to-color":[{"mask-r-to":g()}],"mask-image-b-from-pos":[{"mask-b-from":S0()}],"mask-image-b-to-pos":[{"mask-b-to":S0()}],"mask-image-b-from-color":[{"mask-b-from":g()}],"mask-image-b-to-color":[{"mask-b-to":g()}],"mask-image-l-from-pos":[{"mask-l-from":S0()}],"mask-image-l-to-pos":[{"mask-l-to":S0()}],"mask-image-l-from-color":[{"mask-l-from":g()}],"mask-image-l-to-color":[{"mask-l-to":g()}],"mask-image-x-from-pos":[{"mask-x-from":S0()}],"mask-image-x-to-pos":[{"mask-x-to":S0()}],"mask-image-x-from-color":[{"mask-x-from":g()}],"mask-image-x-to-color":[{"mask-x-to":g()}],"mask-image-y-from-pos":[{"mask-y-from":S0()}],"mask-image-y-to-pos":[{"mask-y-to":S0()}],"mask-image-y-from-color":[{"mask-y-from":g()}],"mask-image-y-to-color":[{"mask-y-to":g()}],"mask-image-radial":[{"mask-radial":[$Q,a2]}],"mask-image-radial-from-pos":[{"mask-radial-from":S0()}],"mask-image-radial-to-pos":[{"mask-radial-to":S0()}],"mask-image-radial-from-color":[{"mask-radial-from":g()}],"mask-image-radial-to-color":[{"mask-radial-to":g()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":f()}],"mask-image-conic-pos":[{"mask-conic":[y$]}],"mask-image-conic-from-pos":[{"mask-conic-from":S0()}],"mask-image-conic-to-pos":[{"mask-conic-to":S0()}],"mask-image-conic-from-color":[{"mask-conic-from":g()}],"mask-image-conic-to-color":[{"mask-conic-to":g()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:Y0()}],"mask-repeat":[{mask:F0()}],"mask-size":[{mask:d()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",$Q,a2]}],filter:[{filter:["","none",$Q,a2]}],blur:[{blur:k0()}],brightness:[{brightness:[y$,$Q,a2]}],contrast:[{contrast:[y$,$Q,a2]}],"drop-shadow":[{"drop-shadow":["","none",q,Lb0,Fb0]}],"drop-shadow-color":[{"drop-shadow":g()}],grayscale:[{grayscale:["",y$,$Q,a2]}],"hue-rotate":[{"hue-rotate":[y$,$Q,a2]}],invert:[{invert:["",y$,$Q,a2]}],saturate:[{saturate:[y$,$Q,a2]}],sepia:[{sepia:["",y$,$Q,a2]}],"backdrop-filter":[{"backdrop-filter":["","none",$Q,a2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[y$,$Q,a2]}],"backdrop-contrast":[{"backdrop-contrast":[y$,$Q,a2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",y$,$Q,a2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[y$,$Q,a2]}],"backdrop-invert":[{"backdrop-invert":["",y$,$Q,a2]}],"backdrop-opacity":[{"backdrop-opacity":[y$,$Q,a2]}],"backdrop-saturate":[{"backdrop-saturate":[y$,$Q,a2]}],"backdrop-sepia":[{"backdrop-sepia":["",y$,$Q,a2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":S()}],"border-spacing-x":[{"border-spacing-x":S()}],"border-spacing-y":[{"border-spacing-y":S()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",$Q,a2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[y$,"initial",$Q,a2]}],ease:[{ease:["linear","initial",_,$Q,a2]}],delay:[{delay:[y$,$Q,a2]}],animate:[{animate:["none",j,$Q,a2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[F,$Q,a2]}],"perspective-origin":[{"perspective-origin":v()}],rotate:[{rotate:O0()}],"rotate-x":[{"rotate-x":O0()}],"rotate-y":[{"rotate-y":O0()}],"rotate-z":[{"rotate-z":O0()}],scale:[{scale:f0()}],"scale-x":[{"scale-x":f0()}],"scale-y":[{"scale-y":f0()}],"scale-z":[{"scale-z":f0()}],"scale-3d":["scale-3d"],skew:[{skew:m0()}],"skew-x":[{"skew-x":m0()}],"skew-y":[{"skew-y":m0()}],transform:[{transform:[$Q,a2,"","none","gpu","cpu"]}],"transform-origin":[{origin:v()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:o0()}],"translate-x":[{"translate-x":o0()}],"translate-y":[{"translate-y":o0()}],"translate-z":[{"translate-z":o0()}],"translate-none":["translate-none"],zoom:[{zoom:[fL,$Q,a2]}],accent:[{accent:g()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:g()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",$Q,a2]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scrollbar-thumb-color":[{"scrollbar-thumb":g()}],"scrollbar-track-color":[{"scrollbar-track":g()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":S()}],"scroll-mx":[{"scroll-mx":S()}],"scroll-my":[{"scroll-my":S()}],"scroll-ms":[{"scroll-ms":S()}],"scroll-me":[{"scroll-me":S()}],"scroll-mbs":[{"scroll-mbs":S()}],"scroll-mbe":[{"scroll-mbe":S()}],"scroll-mt":[{"scroll-mt":S()}],"scroll-mr":[{"scroll-mr":S()}],"scroll-mb":[{"scroll-mb":S()}],"scroll-ml":[{"scroll-ml":S()}],"scroll-p":[{"scroll-p":S()}],"scroll-px":[{"scroll-px":S()}],"scroll-py":[{"scroll-py":S()}],"scroll-ps":[{"scroll-ps":S()}],"scroll-pe":[{"scroll-pe":S()}],"scroll-pbs":[{"scroll-pbs":S()}],"scroll-pbe":[{"scroll-pbe":S()}],"scroll-pt":[{"scroll-pt":S()}],"scroll-pr":[{"scroll-pr":S()}],"scroll-pb":[{"scroll-pb":S()}],"scroll-pl":[{"scroll-pl":S()}],"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",$Q,a2]}],fill:[{fill:["none",...g()]}],"stroke-w":[{stroke:[y$,L50,vT,qR2]}],stroke:[{stroke:["none",...g()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{"container-named":["container-type"],overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","inset-bs","inset-be","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pbs","pbe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mbs","mbe","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-bs","border-w-be","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-bs","border-color-be","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mbs","scroll-mbe","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pbs","scroll-pbe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},postfixLookupClassGroups:["container-type"],orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}},VL$=(A,{cacheSize:Q,prefix:$,experimentalParseClassName:w,extend:B={},override:X={}})=>{return jn(A,"cacheSize",Q),jn(A,"prefix",$),jn(A,"experimentalParseClassName",w),Ib0(A.theme,X.theme),Ib0(A.classGroups,X.classGroups),Ib0(A.conflictingClassGroups,X.conflictingClassGroups),Ib0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),jn(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),jn(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),Nb0(A.theme,B.theme),Nb0(A.classGroups,B.classGroups),Nb0(A.conflictingClassGroups,B.conflictingClassGroups),Nb0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),JDA(A,B,"postfixLookupClassGroups"),JDA(A,B,"orderSensitiveModifiers"),A},jn=(A,Q,$)=>{if($!==void 0)A[Q]=$},Ib0=(A,Q)=>{if(Q)for(let $ in Q)jn(A,$,Q[$])},Nb0=(A,Q)=>{if(Q)for(let $ in Q)JDA(A,Q,$)},JDA=(A,Q,$)=>{let w=Q[$];if(w!==void 0)A[$]=A[$]?A[$].concat(w):w},_b0=(A,...Q)=>typeof A==="function"?DR2(JR2,A,...Q):DR2(()=>VL$(JR2(),A),...Q);var JL$=_b0({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 wQ(...A){return JL$(bn(A))}var vR2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,CR2=bn,B5=(A,Q)=>($)=>{var w;if((Q===null||Q===void 0?void 0:Q.variants)==null)return CR2(A,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className);let{variants:B,defaultVariants:X}=Q,Y=Object.keys(B).map((K)=>{let U=$===null||$===void 0?void 0:$[K],G=X===null||X===void 0?void 0:X[K];if(U===null)return null;let D=vR2(U)||vR2(G);return B[K][D]}),Z=$&&Object.entries($).reduce((K,U)=>{let[G,D]=U;if(D===void 0)return K;return K[G]=D,K},{}),H=Q===null||Q===void 0?void 0:(w=Q.compoundVariants)===null||w===void 0?void 0:w.reduce((K,U)=>{let{class:G,className:D,...q}=U;return Object.entries(q).every((J)=>{let[F,L]=J;return Array.isArray(L)?L.includes({...X,...Z}[F]):{...X,...Z}[F]===L})?[...K,G,D]:K},[]);return CR2(A,Y,H,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className)};import{jsxDEV as IDA}from"preact/jsx-dev-runtime";var hR2=B5("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 NDA({variant:A,title:Q,children:$,className:w}){return IDA("div",{className:wQ(hR2({variant:A}),w),role:"alert",children:[Q&&IDA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),IDA("div",{className:wQ(Q&&"mt-1","text-sm text-current opacity-75"),children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as FL$}from"preact/jsx-dev-runtime";var ER2=B5("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 hT({variant:A,size:Q,className:$,children:w,ssrOnClick:B,type:X="button",...Y}){return FL$("button",{type:X,className:wQ(ER2({variant:A,size:Q}),$),...Y,...B&&{onclick:B},children:w},void 0,!1,void 0,this)}import{jsxDEV as LL$}from"preact/jsx-dev-runtime";var TR2=B5("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 BX({href:A,children:Q,variant:$,size:w,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return LL$("a",{href:A,className:wQ(TR2({variant:$,size:w}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as Pb0}from"preact/jsx-dev-runtime";var yR2=B5("transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2",{variants:{variant:{default:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent hover:border-brand/40",light:"rounded-[10px] bg-theme-subtle border border-theme text-theme-muted hover:text-accent",dark:"rounded-[10px] bg-theme-dark hover:bg-theme-muted text-theme-inverse",footer:"rounded-full bg-theme-toggle hover:bg-theme-toggle-hover text-theme-toggle-icon"},size:{sm:"p-1.5",md:"p-2",lg:"p-3"}},defaultVariants:{variant:"default",size:"md"}}),IL$={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Mn({variant:A,size:Q,className:$}){let w=IL$[Q??"md"];return Pb0("button",{onclick:"toggleTheme()",type:"button",className:wQ(yR2({variant:A,size:Q}),$),"aria-label":"Toggle dark mode",children:Pb0("svg",{className:wQ(w,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[Pb0("path",{className:"sun-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"},void 0,!1,void 0,this),Pb0("path",{className:"moon-icon",strokeLinecap:"round",strokeLinejoin:"round",d:"M20.354 15.354A9 9 0 018.646 3.646 9 9 0 1020.354 15.354z"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as _DA}from"preact/jsx-dev-runtime";var gR2=B5("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function bb0({items:A,className:Q,linkClassName:$="hover:text-accent transition-colors",orientation:w,children:B}){if(A.length===0&&!B)return null;let X=[...A].sort((Y,Z)=>Y.priority-Z.priority);return _DA("ul",{className:wQ(gR2({orientation:w}),Q),children:[X.map((Y)=>_DA("li",{children:_DA("a",{href:Y.href,className:$,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),B]},void 0,!0,void 0,this)}import{jsxDEV as CC5}from"preact/jsx-dev-runtime";import{jsxDEV as TC5}from"preact/jsx-dev-runtime";import{createContext as NL$,h as _L$}from"preact";import{useContext as PL$}from"preact/hooks";var PDA=NL$(null);function kn({headCollector:A,children:Q}){return _L$(PDA.Provider,{value:A},Q)}function SR2(){return PL$(PDA)}function E6(A){let Q=SR2();if(Q)Q.setHeadProps(A);return null}import{createContext as AM$,h as QM$}from"preact";import{useContext as $M$}from"preact/hooks";d2A();var oE2=k1(rE2(),1),tj$=new bV0({gfm:!0,breaks:!0}),ej$={allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","ul","ol","li","blockquote","cite","code","pre","em","strong","del","ins","sub","sup","a","img","span","table","thead","tbody","tr","th","td","div"],allowedAttributes:{a:["href","title","name"],img:["src","srcset","sizes","alt","title","width","height","class","loading","decoding"],code:["class"],pre:["class"],span:["class"],cite:["class"],div:["class"],th:["align","colspan","rowspan","scope"],td:["align","colspan","rowspan"]},allowedSchemes:["http","https","mailto","tel"],allowedSchemesByTag:{img:["http","https","entity"]},allowProtocolRelative:!1,disallowedTagsMode:"discard"};function rqA(A,Q){let{imageRenderer:$}=Q??{},B=($?new bV0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return $(X,Y,Z)??!1}}}):tj$).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
5863
5863
  <cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),oE2.default(B,ej$)}var sE2=AM$(null);function ln({imageRenderer:A,children:Q}){return QM$(sE2.Provider,{value:A??null},Q)}function aE2(){return $M$(sE2)}function Zb(){let A=aE2();return(Q)=>rqA(Q,A?{imageRenderer:A}:void 0)}var wM$=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,BM$={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"},XM$=/&(?:amp|lt|gt|quot|#39);/g;function YM$(A){return A.replace(XM$,(Q)=>BM$[Q]??Q)}function oqA(A){return A.replace(wM$,(Q,$)=>{return`<div class="mermaid">${YM$($)}</div>`})}var tE2=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function eE2(A){let Q={};for(let w of A.matchAll(tE2)){let B=w[1]??"";for(let Y of B.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let Z=Y[1],H=Y[2];if(Z&&H!==void 0)Q[Z]=H}let X=B.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(X)for(let Y of X.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let Z=Y[1];if(Z)Q[Z]="true"}}let $=A.replace(tE2,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
5864
5864
 
5865
5865
  `).trim();return{attributes:Q,markdown:$}}var ZM$=/<!--\s*\.break\s*-->/;function AT2(A){let Q=A.split(ZM$);return Q.length>1?Q:null}import{jsxDEV as TL}from"preact/jsx-dev-runtime";var sqA=({markdown:A,deck:Q})=>{let $=Zb(),B=A.split(/^---$/gm).map((U)=>U.trim()).map((U)=>{let{attributes:G,markdown:D}=eE2(U),q=AT2(D),J;if(q)J=`<div class="slide-columns">${q.map((L)=>`<div class="slide-column">${oqA($(L.trim()))}</div>`).join("")}</div>`;else J=oqA($(D));return{attributes:G,htmlContent:J}}),X=B.some((U)=>U.htmlContent.includes('class="mermaid"')),Y=Q?.frontmatter?.title??Q?.metadata?.title,Z=Q?.frontmatter?.description??Q?.metadata?.description,H=Q?.ogImageUrl??Q?.coverImageUrl,K=B.map(({attributes:U,htmlContent:G},D)=>TL("section",{...U,dangerouslySetInnerHTML:{__html:G}},D,!1,void 0,this));return TL("section",{className:"presentation-section",children:[Y&&TL(E6,{title:Y,...Z?{description:Z}:{},...H?{ogImage:H}:{},ogType:"article"},void 0,!1,void 0,this),TL("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),TL("div",{className:"reveal",children:TL("div",{className:"slides",children:K},void 0,!1,void 0,this)},void 0,!1,void 0,this),TL("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),X&&TL("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),TL("script",{dangerouslySetInnerHTML:{__html:`
@@ -6918,13 +6918,13 @@ ${A.map((X)=>({url:`${Q}${X.path}`,lastmod:$,changefreq:X.path==="/"?"daily":"we
6918
6918
  font-size: 9.5px;
6919
6919
  line-height: 1.45;
6920
6920
  }
6921
- `;var Ul$=W.object({environment:W.enum(["preview","production"]),active:W.object({state:W.enum(["debouncing","queued","building"])}).optional(),lastSuccess:W.object({completedAt:W.string(),routesBuilt:W.number(),warnings:W.array(W.string())}).optional(),lastFailure:W.object({completedAt:W.string(),message:W.string()}).optional()}),jn2=W.object({site:W.object({title:W.string(),previewUrl:W.string().optional(),liveUrl:W.string().optional()}),environments:W.array(Ul$),managementUrl:W.string().optional()});function wJA(A){if(A.active)return A.active.state;if(A.lastFailure)return"failed";if(A.lastSuccess)return"current";return"not built"}function Gl$(A){if(A.lastFailure)return A.lastFailure.message;if(A.lastSuccess){let Q=A.lastSuccess.warnings.length>0?` \xB7 ${A.lastSuccess.warnings.length} warning`:"";return`${A.lastSuccess.routesBuilt} routes${Q}`}return"No completed build in this runtime"}function bn2(A){let Q=A.environment?wJA(A.environment):"unavailable";return KX("div",{class:`pipeline-metric site-health-metric site-health-metric--${Q}`},[KX("dt",{},[KX("span",{class:"site-health-dot","aria-hidden":"true"}),A.label]),KX("dd",{},Q),A.environment?KX("small",{class:"muted"},Gl$(A.environment)):null])}function $JA(A,Q,$="external"){return KX("a",{class:`widget-action widget-action--${$==="manage"?"primary":"secondary"}`,href:A,...$==="external"?{target:"_blank",rel:"noreferrer"}:{}},[KX("span",{},Q),KX("span",{class:"widget-action-arrow","aria-hidden":"true"},$==="external"?"\u2197":"\u2192")])}function Dl$(A){let Q=jn2.safeParse(A.data);if(!Q.success)return KX("p",{class:"muted"},"Site health is unavailable.");let $=Q.data,w=$.environments.find((Z)=>Z.environment==="preview"),B=$.environments.find((Z)=>Z.environment==="production"),X=$.environments.filter((Z)=>Z.lastFailure!==void 0),Y=[];if($.site.previewUrl)Y.push($JA($.site.previewUrl,"Open preview"));if($.site.liveUrl)Y.push($JA($.site.liveUrl,"Open live"));if($.managementUrl)Y.push($JA($.managementUrl,"Open in CMS","manage"));return KX("div",{class:"pipeline-digest site-health-widget"},[KX("dl",{class:"pipeline-metrics"},[KX(bn2,{label:"Preview",environment:w}),KX(bn2,{label:"Live",environment:B})]),X.length>0?KX("section",{class:"pipeline-failures"},[KX("h4",{},"Needs attention"),...X.map((Z)=>KX("div",{class:"pipeline-failure",key:Z.environment},[KX("strong",{},Z.environment),KX("span",{},Z.lastFailure?.message)]))]):null,Y.length>0?KX("nav",{class:"widget-actions","aria-label":"Site actions"},Y):null])}function ql$(A){let Q=jn2.parse(A),$=Q.environments.find((X)=>X.environment==="preview"),w=Q.environments.find((X)=>X.environment==="production"),B=Q.environments.filter((X)=>X.lastFailure!==void 0).length;return{digest:[{label:"Preview",value:$?wJA($):"unavailable",...$?.lastFailure?{tone:"warn"}:{tone:"good"}},{label:"Live",value:w?wJA(w):"unavailable",...w?.lastFailure?{tone:"warn"}:{tone:"good"}}],needsOperator:B}}async function Mn2(A,Q,$){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"site-health",pluginId:"site-builder",title:"Site health",description:"Preview and live build status",group:"publishing",section:"sidebar",priority:50,rendererName:"SiteHealthWidget",visibility:"anchor",component:Dl$,clientStyles:Pn2,dataProvider:async()=>({...await Q.getSnapshot(),...$?{managementUrl:$}:{}}),digestProvider:ql$}})}h0();bX();var zl$=W.object({id:W.string(),template:W.string(),content:W.unknown().optional(),dataQuery:W.looseObject({entityType:W.string().optional(),template:W.string().optional(),query:W.looseObject({id:W.string().optional(),limit:W.number().optional(),offset:W.number().optional()}).optional()}).optional(),order:W.number().optional()}),Vl$=W.object({show:W.boolean().default(!1),label:W.string().optional(),slot:W.enum(yj).default("primary"),priority:W.number().min(0).max(100).default(50)}).optional(),Jl$=W.object({id:W.string(),path:W.string(),title:W.string().default(""),pageLabel:W.string().optional(),description:W.string().default(""),sections:W.array(zl$).default([]),layout:W.string().default("default"),fullscreen:W.boolean().optional(),pluginId:W.string().optional(),sourceEntityType:W.string().optional(),external:W.boolean().optional(),navigation:Vl$}),kn2=W.object({previewOutputDir:W.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:W.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:W.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:W.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:jr.default({title:"Brain",description:"A knowledge management system"}),themeCSS:W.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:W.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:W.any().optional().describe("Template definitions to register"),routes:W.array(Jl$).optional().describe("Routes to register"),layouts:W.record(W.string(),W.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:W.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:W.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:W.record(W.string(),W.object({label:W.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:W.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:W.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:W.boolean().optional().describe("Enable pagination for list pages"),pageSize:W.number().optional().describe("Items per page (default: 10)"),navigation:W.object({show:W.boolean().optional().describe("Show in navigation"),slot:W.enum(yj).optional().describe("Navigation slot (primary or secondary)"),priority:W.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:W.record(W.string(),W.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var On2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.195",description:"Static site generation plugin for Brain system",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*","@tailwindcss/typography":"^0.5.20",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{clean:"rm -rf dist",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class BJA extends d6{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;buildStatusService;siteWorkspaceProvider;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",On2,{...A,layouts:Q},kn2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new eM0(A.logger),this._slotRegistry=new kM0,A.messaging.subscribe("plugin:site-builder:slot:register",async($)=>{let{slotName:w,pluginId:B,render:X,priority:Y}=$.payload;return this._slotRegistry?.register(w,{pluginId:B,render:X,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async($)=>{let{pluginId:w,script:B}=$.payload;return this.headScripts.set(w,B),{success:!0}}),A.entities.registerDataSource(new eVA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},this.buildStatusService=new AJA(A.runtimeState,A.jobs),await this.buildStatusService.initialize(),Dn2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Qk0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:($,w)=>A.templates.resolve($,w),getViewTemplate:($)=>A.views.get($),listViewTemplateNames:()=>A.views.list().map(($)=>$.name)};if(this.siteBuilder=Iz.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new tVA(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},statusService:this.buildStatusService})),this.rebuildManager=new aVA(this.config,A,this.id,this.logger,this.buildStatusService),this.siteWorkspaceProvider=new QJA({context:A,config:this.config,routeRegistry:this.routeRegistry,statusService:this.buildStatusService,requestBuild:($)=>{this.rebuildManager?.requestBuild($)}}),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(ia,async()=>{let $=await this.getInstructions();if($)A.registerInstructions($);return{success:!0}}),Vn2({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}async onReady(A){if(!this.siteWorkspaceProvider)return;let Q=await this.siteWorkspaceProvider.registerCmsWorkspace();await Mn2(A,this.siteWorkspaceProvider,Q)}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 Ln2(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Metadata",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q=await qy(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map(($)=>({id:$.id,path:$.path,title:$.title,description:$.description,sections:$.sections.map((w)=>({id:w.id,template:w.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map(($)=>({name:$.name,description:$.description,hasWebRenderer:!!$.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",$=await qy(A.messaging.send,this.config.siteInfo);return`## Your Site
6921
+ `;var Ul$=W.object({environment:W.enum(["preview","production"]),active:W.object({state:W.enum(["debouncing","queued","building"])}).optional(),lastSuccess:W.object({completedAt:W.string(),routesBuilt:W.number(),warnings:W.array(W.string())}).optional(),lastFailure:W.object({completedAt:W.string(),message:W.string()}).optional()}),jn2=W.object({site:W.object({title:W.string(),previewUrl:W.string().optional(),liveUrl:W.string().optional()}),environments:W.array(Ul$),managementUrl:W.string().optional()});function wJA(A){if(A.active)return A.active.state;if(A.lastFailure)return"failed";if(A.lastSuccess)return"current";return"not built"}function Gl$(A){if(A.lastFailure)return A.lastFailure.message;if(A.lastSuccess){let Q=A.lastSuccess.warnings.length>0?` \xB7 ${A.lastSuccess.warnings.length} warning`:"";return`${A.lastSuccess.routesBuilt} routes${Q}`}return"No completed build in this runtime"}function bn2(A){let Q=A.environment?wJA(A.environment):"unavailable";return KX("div",{class:`pipeline-metric site-health-metric site-health-metric--${Q}`},[KX("dt",{},[KX("span",{class:"site-health-dot","aria-hidden":"true"}),A.label]),KX("dd",{},Q),A.environment?KX("small",{class:"muted"},Gl$(A.environment)):null])}function $JA(A,Q,$="external"){return KX("a",{class:`widget-action widget-action--${$==="manage"?"primary":"secondary"}`,href:A,...$==="external"?{target:"_blank",rel:"noreferrer"}:{}},[KX("span",{},Q),KX("span",{class:"widget-action-arrow","aria-hidden":"true"},$==="external"?"\u2197":"\u2192")])}function Dl$(A){let Q=jn2.safeParse(A.data);if(!Q.success)return KX("p",{class:"muted"},"Site health is unavailable.");let $=Q.data,w=$.environments.find((Z)=>Z.environment==="preview"),B=$.environments.find((Z)=>Z.environment==="production"),X=$.environments.filter((Z)=>Z.lastFailure!==void 0),Y=[];if($.site.previewUrl)Y.push($JA($.site.previewUrl,"Open preview"));if($.site.liveUrl)Y.push($JA($.site.liveUrl,"Open live"));if($.managementUrl)Y.push($JA($.managementUrl,"Open in CMS","manage"));return KX("div",{class:"pipeline-digest site-health-widget"},[KX("dl",{class:"pipeline-metrics"},[KX(bn2,{label:"Preview",environment:w}),KX(bn2,{label:"Live",environment:B})]),X.length>0?KX("section",{class:"pipeline-failures"},[KX("h4",{},"Needs attention"),...X.map((Z)=>KX("div",{class:"pipeline-failure",key:Z.environment},[KX("strong",{},Z.environment),KX("span",{},Z.lastFailure?.message)]))]):null,Y.length>0?KX("nav",{class:"widget-actions","aria-label":"Site actions"},Y):null])}function ql$(A){let Q=jn2.parse(A),$=Q.environments.find((X)=>X.environment==="preview"),w=Q.environments.find((X)=>X.environment==="production"),B=Q.environments.filter((X)=>X.lastFailure!==void 0).length;return{digest:[{label:"Preview",value:$?wJA($):"unavailable",...$?.lastFailure?{tone:"warn"}:{tone:"good"}},{label:"Live",value:w?wJA(w):"unavailable",...w?.lastFailure?{tone:"warn"}:{tone:"good"}}],needsOperator:B}}async function Mn2(A,Q,$){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"site-health",pluginId:"site-builder",title:"Site health",description:"Preview and live build status",group:"publishing",section:"sidebar",priority:50,rendererName:"SiteHealthWidget",visibility:"anchor",component:Dl$,clientStyles:Pn2,dataProvider:async()=>({...await Q.getSnapshot(),...$?{managementUrl:$}:{}}),digestProvider:ql$}})}h0();bX();var zl$=W.object({id:W.string(),template:W.string(),content:W.unknown().optional(),dataQuery:W.looseObject({entityType:W.string().optional(),template:W.string().optional(),query:W.looseObject({id:W.string().optional(),limit:W.number().optional(),offset:W.number().optional()}).optional()}).optional(),order:W.number().optional()}),Vl$=W.object({show:W.boolean().default(!1),label:W.string().optional(),slot:W.enum(yj).default("primary"),priority:W.number().min(0).max(100).default(50)}).optional(),Jl$=W.object({id:W.string(),path:W.string(),title:W.string().default(""),pageLabel:W.string().optional(),description:W.string().default(""),sections:W.array(zl$).default([]),layout:W.string().default("default"),fullscreen:W.boolean().optional(),pluginId:W.string().optional(),sourceEntityType:W.string().optional(),external:W.boolean().optional(),navigation:Vl$}),kn2=W.object({previewOutputDir:W.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:W.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:W.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:W.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:jr.default({title:"Brain",description:"A knowledge management system"}),themeCSS:W.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:W.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:W.any().optional().describe("Template definitions to register"),routes:W.array(Jl$).optional().describe("Routes to register"),layouts:W.record(W.string(),W.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:W.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:W.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:W.record(W.string(),W.object({label:W.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:W.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:W.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:W.boolean().optional().describe("Enable pagination for list pages"),pageSize:W.number().optional().describe("Items per page (default: 10)"),navigation:W.object({show:W.boolean().optional().describe("Show in navigation"),slot:W.enum(yj).optional().describe("Navigation slot (primary or secondary)"),priority:W.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:W.record(W.string(),W.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var On2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.196",description:"Static site generation plugin for Brain system",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*","@tailwindcss/typography":"^0.5.20",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{clean:"rm -rf dist",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class BJA extends d6{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;buildStatusService;siteWorkspaceProvider;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",On2,{...A,layouts:Q},kn2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new eM0(A.logger),this._slotRegistry=new kM0,A.messaging.subscribe("plugin:site-builder:slot:register",async($)=>{let{slotName:w,pluginId:B,render:X,priority:Y}=$.payload;return this._slotRegistry?.register(w,{pluginId:B,render:X,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async($)=>{let{pluginId:w,script:B}=$.payload;return this.headScripts.set(w,B),{success:!0}}),A.entities.registerDataSource(new eVA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},this.buildStatusService=new AJA(A.runtimeState,A.jobs),await this.buildStatusService.initialize(),Dn2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Qk0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:($,w)=>A.templates.resolve($,w),getViewTemplate:($)=>A.views.get($),listViewTemplateNames:()=>A.views.list().map(($)=>$.name)};if(this.siteBuilder=Iz.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new tVA(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},statusService:this.buildStatusService})),this.rebuildManager=new aVA(this.config,A,this.id,this.logger,this.buildStatusService),this.siteWorkspaceProvider=new QJA({context:A,config:this.config,routeRegistry:this.routeRegistry,statusService:this.buildStatusService,requestBuild:($)=>{this.rebuildManager?.requestBuild($)}}),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(ia,async()=>{let $=await this.getInstructions();if($)A.registerInstructions($);return{success:!0}}),Vn2({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}async onReady(A){if(!this.siteWorkspaceProvider)return;let Q=await this.siteWorkspaceProvider.registerCmsWorkspace();await Mn2(A,this.siteWorkspaceProvider,Q)}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 Ln2(this.id,(Q)=>A.requestBuild(Q))}async getResources(){let A=this.getContext();return[{uri:"brain://site",name:"Site Metadata",description:"Site metadata \u2014 title, description, domain, URLs",mimeType:"application/json",handler:async()=>{let Q=await qy(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map(($)=>({id:$.id,path:$.path,title:$.title,description:$.description,sections:$.sections.map((w)=>({id:w.id,template:w.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map(($)=>({name:$.name,description:$.description,hasWebRenderer:!!$.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",$=await qy(A.messaging.send,this.config.siteInfo);return`## Your Site
6922
6922
  ${[`**Title:** ${$.title}`,`**Description:** ${$.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
6923
6923
  `)}
6924
6924
 
6925
6925
  ## Site Builder Actions
6926
6926
  - When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
6927
- - Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),await this.rebuildManager?.dispose(),delete this.rebuildManager,delete this.siteBuilder,this.logger.debug("Cleaned up all event subscriptions")}}function zy(A={}){return new BJA(A)}zA();zA();h0();var XJA=W.object({routeId:W.string(),sectionId:W.string()}),Ll$=W.object({routeId:W.string(),sectionId:W.string()}),iB0=U6.extend({entityType:W.literal("site-content"),template:W.string().optional(),content:W.string(),metadata:Ll$});zA();class fn2 extends zQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:iB0,frontmatterSchema:XJA})}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 YJA=new fn2;h0();var $k0=W.object({routeId:W.string().optional().describe("Optional: specific route filter"),sectionId:W.string().optional().describe("Optional: specific section filter"),dryRun:W.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:W.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),Mr5=W.object({jobs:W.array(W.object({jobId:W.string(),routeId:W.string(),sectionId:W.string()})),totalSections:W.number(),queuedSections:W.number(),skippedSections:W.number().optional(),batchId:W.string().optional()});h0();var Il$=W.looseObject({id:W.string(),template:W.string().optional(),content:W.unknown().optional()}),Nl$=W.looseObject({id:W.string(),title:W.string().optional(),description:W.string().optional(),sections:W.array(Il$)}),_l$=W.array(Nl$);class ZJA{context;constructor(A){this.context=A}createJobOptions(A,Q){if(!A)return;return{source:A.operationType??Q,rootJobId:A.rootJobId??`${Q}-${Date.now()}`,metadata:{operationType:A.operationType??"content_operations",progressToken:A.progressToken,pluginId:A.pluginId??"site-content"}}}async fetchRoutes(){let A=await this.context.messaging.send({type:"site-builder:routes:list",payload:{}});if("noop"in A)throw Error("No handler for site-builder:routes:list \u2014 is site-builder plugin loaded?");if(!A.success||!A.data)throw Error("Failed to fetch routes from site-builder");let Q=_l$.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,$){let w=this.context.logger.child("SiteContentOperations"),B=await this.fetchRoutes(),X=B;if(A.routeId){if(X=B.filter((U)=>U.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let U of X)for(let G of U.sections){if(A.sectionId&&G.id!==A.sectionId)continue;if(G.content){w.debug("Section has static content, skipping",{routeId:U.id,sectionId:G.id});continue}if(G.template){let D=this.context.templates.getCapabilities(G.template);if(!D){w.warn("Template not found, skipping section",{routeId:U.id,sectionId:G.id,templateName:G.template});continue}if(!D.canGenerate){w.debug("Template doesn't support generation, skipping",{routeId:U.id,sectionId:G.id,templateName:G.template,capabilities:D});continue}}else{w.debug("Section has no template, skipping",{routeId:U.id,sectionId:G.id});continue}if(!A.force&&!A.dryRun){let D=`${U.id}:${G.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){w.debug("Content already exists, skipping",{routeId:U.id,sectionId:G.id});continue}}Y.push({route:U,section:G})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let H=[],K=[];for(let{route:U,section:G}of Y){let D=`${U.id}:${G.id}`,q=G.template,J={routeId:U.id,sectionId:G.id,entityId:D,entityType:"site-content",templateName:q,context:{prompt:typeof G.content==="string"?G.content:void 0,data:{routeId:U.id,sectionId:G.id,routeTitle:U.title,routeDescription:U.description,sectionContent:G.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:J})}if(K.length>0){let U=this.createJobOptions($,"site:content-generation"),G=await this.context.jobs.enqueueBatch(K,U);for(let D=0;D<Y.length;D++){let q=Y[D];if(q)H.push({jobId:`${G}-${D}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:Z,queuedSections:H.length,batchId:G}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class WJA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new ZJA(A)}async generateContent(A,Q){let $=$k0.parse(A);return this.operations.generate($,this.siteConfig,Q)}}bX();h0();var Pl$=W.object({namespace:W.string(),sections:W.record(W.string(),W.any())}),xn2=W.custom((A)=>Pl$.safeParse(A).success),HJA=W.object({definitions:W.union([xn2,W.array(xn2)]).optional()});zA();function Rn2(A,Q){return[e8(Q,"generate","Generate content for all routes, a specific route, or a specific section",$k0,async($,w)=>{let B=A();if(!B)return{success:!1,error:"Site content service not initialized"};if($.sectionId&&!$.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let X={rootJobId:`generate-${Date.now()}`,progressToken:w.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:w.interfaceType,channelId:w.channelId},Y=await B.generateContent($,X);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 vn2={name:"@brains/site-content",version:"0.2.0-alpha.195",description:"Site content entity and generation orchestration",dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class KJA extends d6{siteContentService;constructor(A={}){super("site-content",vn2,A,HJA)}async onRegister(A){A.entities.register("site-content",iB0,YJA);for(let Q of Sk(this.config.definitions))A.templates.register(oj(Q),Q.namespace);this.siteContentService=new WJA(A)}async getTools(){return Rn2(()=>this.siteContentService,this.id)}}function Vy(A={}){return new KJA(A)}zA();bX();zA();h0();bX();var jl$=W.object({}),Ml$=W.object({}),dB0=U6.extend({id:W.literal("site-info"),entityType:W.literal("site-info"),metadata:Ml$});var Mr=SS0.omit({url:!0,analyticsScript:!0});zA();h0();var kl$=W.record(W.string(),W.unknown());class oL extends zQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:dB0,frontmatterSchema:Mr,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=Mr.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",kl$.parse(Q))}}class sL{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,$){return sL.instance??=new sL(A,Q,$),sL.instance}static resetInstance(){sL.instance=null}static createFresh(A,Q,$){return new sL(A,Q,$)}constructor(A,Q,$){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new oL;let w=sL.getDefaultSiteInfo();this.defaultSiteInfo={...w,...$}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let $=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:$,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}h0();var Ol$=new oL,fl$=W.looseObject({platform:W.string(),url:W.string(),label:W.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),xl$=W.looseObject({socialLinks:W.array(fl$).optional()});class wk0{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,$){let{entityService:w}=$,B;try{let Z=await w.getEntity({entityType:"site-info",id:"site-info"});B=Z?Ol$.parseSiteInfoBody(Z.content):{title:"Brain",description:"A knowledge management system"}}catch{B={title:"Brain",description:"A knowledge management system"}}let X;try{let Z=await w.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Z){let H=xl$.safeParse(Z.metadata);X=H.success?H.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var Cn2={name:"@brains/site-info",version:"0.2.0-alpha.195",description:"Site info entity \u2014 site metadata, title, description, CTA",dependencies:{"@brains/entity-service":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var vl$=new oL,Cl$="site-info";class UJA extends c6{entityType=Cl$;schema=dB0;adapter=vl$;defaultSiteInfo;constructor(A){super("site-info",Cn2,{},bY);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new wk0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=sL.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(la,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async($)=>{if($.payload.entityType==="site-info"){let B=await Q.getSiteInfo();await A.messaging.send({type:ia,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Jy(A){return new UJA(A)}var hl$=new oL;async function nB0(A){let $=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!$)throw Error("Site info not found \u2014 create a site-info entity");return hl$.parseSiteInfoBody($.content)}function hn2(A,Q){let $=A.metadata.publishedAt??A.created,w=Q.metadata.publishedAt??Q.created;return new Date(w).getTime()-new Date($).getTime()}async function Bk0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(hn2).slice(0,Q.count).map(Q.parse)}function GJA(A){if(!A)throw Error("CTA not configured in site-info");return A}h0();var En2=W.object({label:W.string(),href:W.string(),priority:W.number()}),El$=W.object({primary:W.array(En2),secondary:W.array(En2)}),Tl$=W.object({platform:W.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:W.string().describe("Profile or contact URL"),label:W.string().optional().describe("Optional display label")}),yl$=Mr.extend({navigation:El$,copyright:W.string(),socialLinks:W.array(Tl$).optional().describe("Social media links from profile entity")});zA();AD();fr();h0();var DJA=W.object({defaultPrompt:W.string().default("Write a blog post about my recent work and insights"),paginate:W.boolean().default(!0),pageSize:W.number().default(10)});zA();Uw();p2();h0();var ul$=W.object({prompt:W.string().optional(),title:W.string().optional(),content:W.string().optional(),excerpt:W.string().optional(),coverImageId:W.string().optional(),seriesName:W.string().optional(),seriesIndex:W.number().optional(),skipAi:W.boolean().optional()}),$s5=xU.extend({title:W.string().optional(),slug:W.string().optional()});class qJA extends yZ{constructor(A,Q){super(A,Q,{schema:ul$,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:$,coverImageId:w,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:H,excerpt:K}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
6927
+ - Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),await this.rebuildManager?.dispose(),delete this.rebuildManager,delete this.siteBuilder,this.logger.debug("Cleaned up all event subscriptions")}}function zy(A={}){return new BJA(A)}zA();zA();h0();var XJA=W.object({routeId:W.string(),sectionId:W.string()}),Ll$=W.object({routeId:W.string(),sectionId:W.string()}),iB0=U6.extend({entityType:W.literal("site-content"),template:W.string().optional(),content:W.string(),metadata:Ll$});zA();class fn2 extends zQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:iB0,frontmatterSchema:XJA})}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 YJA=new fn2;h0();var $k0=W.object({routeId:W.string().optional().describe("Optional: specific route filter"),sectionId:W.string().optional().describe("Optional: specific section filter"),dryRun:W.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:W.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),Mr5=W.object({jobs:W.array(W.object({jobId:W.string(),routeId:W.string(),sectionId:W.string()})),totalSections:W.number(),queuedSections:W.number(),skippedSections:W.number().optional(),batchId:W.string().optional()});h0();var Il$=W.looseObject({id:W.string(),template:W.string().optional(),content:W.unknown().optional()}),Nl$=W.looseObject({id:W.string(),title:W.string().optional(),description:W.string().optional(),sections:W.array(Il$)}),_l$=W.array(Nl$);class ZJA{context;constructor(A){this.context=A}createJobOptions(A,Q){if(!A)return;return{source:A.operationType??Q,rootJobId:A.rootJobId??`${Q}-${Date.now()}`,metadata:{operationType:A.operationType??"content_operations",progressToken:A.progressToken,pluginId:A.pluginId??"site-content"}}}async fetchRoutes(){let A=await this.context.messaging.send({type:"site-builder:routes:list",payload:{}});if("noop"in A)throw Error("No handler for site-builder:routes:list \u2014 is site-builder plugin loaded?");if(!A.success||!A.data)throw Error("Failed to fetch routes from site-builder");let Q=_l$.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,$){let w=this.context.logger.child("SiteContentOperations"),B=await this.fetchRoutes(),X=B;if(A.routeId){if(X=B.filter((U)=>U.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let U of X)for(let G of U.sections){if(A.sectionId&&G.id!==A.sectionId)continue;if(G.content){w.debug("Section has static content, skipping",{routeId:U.id,sectionId:G.id});continue}if(G.template){let D=this.context.templates.getCapabilities(G.template);if(!D){w.warn("Template not found, skipping section",{routeId:U.id,sectionId:G.id,templateName:G.template});continue}if(!D.canGenerate){w.debug("Template doesn't support generation, skipping",{routeId:U.id,sectionId:G.id,templateName:G.template,capabilities:D});continue}}else{w.debug("Section has no template, skipping",{routeId:U.id,sectionId:G.id});continue}if(!A.force&&!A.dryRun){let D=`${U.id}:${G.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){w.debug("Content already exists, skipping",{routeId:U.id,sectionId:G.id});continue}}Y.push({route:U,section:G})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let H=[],K=[];for(let{route:U,section:G}of Y){let D=`${U.id}:${G.id}`,q=G.template,J={routeId:U.id,sectionId:G.id,entityId:D,entityType:"site-content",templateName:q,context:{prompt:typeof G.content==="string"?G.content:void 0,data:{routeId:U.id,sectionId:G.id,routeTitle:U.title,routeDescription:U.description,sectionContent:G.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:J})}if(K.length>0){let U=this.createJobOptions($,"site:content-generation"),G=await this.context.jobs.enqueueBatch(K,U);for(let D=0;D<Y.length;D++){let q=Y[D];if(q)H.push({jobId:`${G}-${D}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:Z,queuedSections:H.length,batchId:G}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class WJA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new ZJA(A)}async generateContent(A,Q){let $=$k0.parse(A);return this.operations.generate($,this.siteConfig,Q)}}bX();h0();var Pl$=W.object({namespace:W.string(),sections:W.record(W.string(),W.any())}),xn2=W.custom((A)=>Pl$.safeParse(A).success),HJA=W.object({definitions:W.union([xn2,W.array(xn2)]).optional()});zA();function Rn2(A,Q){return[e8(Q,"generate","Generate content for all routes, a specific route, or a specific section",$k0,async($,w)=>{let B=A();if(!B)return{success:!1,error:"Site content service not initialized"};if($.sectionId&&!$.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let X={rootJobId:`generate-${Date.now()}`,progressToken:w.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:w.interfaceType,channelId:w.channelId},Y=await B.generateContent($,X);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 vn2={name:"@brains/site-content",version:"0.2.0-alpha.196",description:"Site content entity and generation orchestration",dependencies:{"@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class KJA extends d6{siteContentService;constructor(A={}){super("site-content",vn2,A,HJA)}async onRegister(A){A.entities.register("site-content",iB0,YJA);for(let Q of Sk(this.config.definitions))A.templates.register(oj(Q),Q.namespace);this.siteContentService=new WJA(A)}async getTools(){return Rn2(()=>this.siteContentService,this.id)}}function Vy(A={}){return new KJA(A)}zA();bX();zA();h0();bX();var jl$=W.object({}),Ml$=W.object({}),dB0=U6.extend({id:W.literal("site-info"),entityType:W.literal("site-info"),metadata:Ml$});var Mr=SS0.omit({url:!0,analyticsScript:!0});zA();h0();var kl$=W.record(W.string(),W.unknown());class oL extends zQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:dB0,frontmatterSchema:Mr,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=Mr.parse(A);return this.buildMarkdown("",Q)}parseSiteInfoBody(A){return this.parseFrontmatter(A)}fromMarkdown(A){return{content:A,entityType:"site-info"}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseFrontmatter(A.content);return this.buildMarkdown("",kl$.parse(Q))}}class sL{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,$){return sL.instance??=new sL(A,Q,$),sL.instance}static resetInstance(){sL.instance=null}static createFresh(A,Q,$){return new sL(A,Q,$)}constructor(A,Q,$){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new oL;let w=sL.getDefaultSiteInfo();this.defaultSiteInfo={...w,...$}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let $=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:$,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}h0();var Ol$=new oL,fl$=W.looseObject({platform:W.string(),url:W.string(),label:W.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),xl$=W.looseObject({socialLinks:W.array(fl$).optional()});class wk0{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,$){let{entityService:w}=$,B;try{let Z=await w.getEntity({entityType:"site-info",id:"site-info"});B=Z?Ol$.parseSiteInfoBody(Z.content):{title:"Brain",description:"A knowledge management system"}}catch{B={title:"Brain",description:"A knowledge management system"}}let X;try{let Z=await w.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Z){let H=xl$.safeParse(Z.metadata);X=H.success?H.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var Cn2={name:"@brains/site-info",version:"0.2.0-alpha.196",description:"Site info entity \u2014 site metadata, title, description, CTA",dependencies:{"@brains/entity-service":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var vl$=new oL,Cl$="site-info";class UJA extends c6{entityType=Cl$;schema=dB0;adapter=vl$;defaultSiteInfo;constructor(A){super("site-info",Cn2,{},bY);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new wk0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=sL.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(la,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async($)=>{if($.payload.entityType==="site-info"){let B=await Q.getSiteInfo();await A.messaging.send({type:ia,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Jy(A){return new UJA(A)}var hl$=new oL;async function nB0(A){let $=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!$)throw Error("Site info not found \u2014 create a site-info entity");return hl$.parseSiteInfoBody($.content)}function hn2(A,Q){let $=A.metadata.publishedAt??A.created,w=Q.metadata.publishedAt??Q.created;return new Date(w).getTime()-new Date($).getTime()}async function Bk0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(hn2).slice(0,Q.count).map(Q.parse)}function GJA(A){if(!A)throw Error("CTA not configured in site-info");return A}h0();var En2=W.object({label:W.string(),href:W.string(),priority:W.number()}),El$=W.object({primary:W.array(En2),secondary:W.array(En2)}),Tl$=W.object({platform:W.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:W.string().describe("Profile or contact URL"),label:W.string().optional().describe("Optional display label")}),yl$=Mr.extend({navigation:El$,copyright:W.string(),socialLinks:W.array(Tl$).optional().describe("Social media links from profile entity")});zA();AD();fr();h0();var DJA=W.object({defaultPrompt:W.string().default("Write a blog post about my recent work and insights"),paginate:W.boolean().default(!0),pageSize:W.number().default(10)});zA();Uw();p2();h0();var ul$=W.object({prompt:W.string().optional(),title:W.string().optional(),content:W.string().optional(),excerpt:W.string().optional(),coverImageId:W.string().optional(),seriesName:W.string().optional(),seriesIndex:W.number().optional(),skipAi:W.boolean().optional()}),$s5=xU.extend({title:W.string().optional(),slug:W.string().optional()});class qJA extends yZ{constructor(A,Q){super(A,Q,{schema:ul$,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:$,coverImageId:w,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:H,excerpt:K}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
6928
6928
 
6929
6929
  Add your introduction here.
6930
6930
 
@@ -7144,7 +7144,7 @@ ${$.content}`,templateName:"blog:excerpt"})})}zA();fr();AD();function Ui$(A){let
7144
7144
  letter-spacing: 0.02em;
7145
7145
  }
7146
7146
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
7147
- `}},void 0,!1,void 0,this),nY("header",{className:"printable-hero",children:[nY("div",{className:"printable-masthead",children:Q.brandLabel&&nY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),nY("div",{children:[nY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&nY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),nY("div",{className:"printable-meta",children:[Q.author&&nY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),$&&nY("span",{children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&nY("figure",{className:"printable-cover-wrap",children:nY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),nY(XX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&nY("footer",{className:"printable-footer",children:[nY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&nY("a",{href:Q.canonicalUrl,children:Q.canonicalUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var si$=26214400,ai$=60000;class MJA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Wk0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=ti$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await di$(oi$(ri$(),"brain-blog-printable-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/printable/post/${Q.id}`,template:$r2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:si$,timeoutMs:ai$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${ei$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await ni$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=UB.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function ti$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=UB.parse($);return{title:B.title,body:w,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.canonicalUrl?{canonicalUrl:B.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function ei$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}import{mkdtemp as Bd$,rm as Xd$}from"fs/promises";import{tmpdir as Yd$}from"os";import{join as Zd$}from"path";u4();p2();AD();h0();import{jsxDEV as wd$}from"preact/jsx-dev-runtime";var eB0="og-image",Ad$="blog:og-image",wr2=W.object({title:W.string().min(1),excerpt:W.string().optional(),author:W.string().optional(),publishedAt:W.string().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),Br2={name:Ad$,pluginId:"blog",schema:wr2,renderers:{image:$d$}};function Qd$(A){if(!A)return;let Q=new Date(A);if(Number.isNaN(Q.getTime()))return;return Q.toLocaleDateString("en-GB",{year:"numeric",month:"short",day:"2-digit"})}function $d$(A){let Q=wr2.parse(A);return wd$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Qd$(Q.publishedAt)},void 0,!1,void 0,this)}var Wd$={width:1200,height:630},Hd$=60000;class kJA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??tB0}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==eB0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=Kd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Bd$(Zd$(Yd$(),"brain-blog-og-image-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/og/post/${Q.id}`,template:Br2,format:"image",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),Wd$,{timeoutMs:Hd$,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${Ud$(Q)}-og.png`}}finally{await X.close()}}finally{await Xd$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=UB.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function Kd$(A,Q={}){let{frontmatter:$}=t8(A.content),w=UB.parse($);return{title:w.title,...w.excerpt?{excerpt:w.excerpt}:{},...w.author?{author:w.author}:{},...w.publishedAt?{publishedAt:w.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Ud$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var Xr2={name:"@brains/blog",version:"0.2.0-alpha.195",description:"AI-powered blog post generation from existing brain content",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class OJA extends c6{entityType=bb.entityType;schema=kr;adapter=bb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Xr2,A,DJA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new qJA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return un2()}getDataSources(){return[new VJA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (Wr2(),Zr2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),cn2(A,this.logger),pn2(A,this.logger),in2(A,this.logger),dn2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Wk0,new MJA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",eB0,new kJA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=D9.getInstance().register(LJA()),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}deferPublishAssetRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish-assets:register",payload:{entityType:"post",attachmentType:eB0,mediaEntityType:"image",targetEntityField:{location:"frontmatter",field:"ogImageId"},requiredWhen:{status:"published"},autoGenerate:!0,jobType:"image:image-render-source"}}),{success:!0}})}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function fJA(A={}){return new OJA(A)}AD();fr();zA();h0();e9();zA();h0();var iV=W.object({title:W.string(),slug:W.string(),coverImageId:W.string().optional()}),qd$=W.object({title:W.string(),slug:W.string()}),zd$=W.object({title:W.string(),slug:W.string()}),tf=U6.extend({entityType:W.literal("series"),metadata:zd$}),Hk0=tf.extend({frontmatter:iV}),Vd$=Hk0.extend({description:W.string().optional(),postCount:W.number(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Hr2=W.object({description:W.string().optional()});function Iy(A){return new n$(Hr2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}zA();class xJA extends zQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:tf,frontmatterSchema:iV,supportsCoverImage:!0,bodyFormatter:Iy("")})}toMarkdown(A){let Q,$={};try{Q=this.parseFrontMatter(A.content,iV).coverImageId,$=Iy(A.metadata.title).parse(this.extractBody(A.content))}catch{}let w={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=Iy(A.metadata.title).format($);return this.buildMarkdown(X,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,iV);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,iV);return Iy(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var ef=new xJA;zA();p2();EZ();h0();var Jd$=W.object({seriesName:W.string().optional(),seriesIndex:W.number().optional()});function Kk0(A){let Q=Jd$.safeParse(A);return Q.success?Q.data:{}}function Ny(A){return Kk0(A.metadata).seriesName}function Kr2(A){return Kk0(A.metadata).seriesIndex}function Ur2(A,Q){let $=Kr2(A)??Number.MAX_SAFE_INTEGER,w=Kr2(Q)??Number.MAX_SAFE_INTEGER;return $-w}class RJA{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),$=new Map(Q.map((B)=>[B.id,B])),w=new Set;for(let B of A){let X=O1(B);w.add(X);let Y=$.get(X),Z=Y?.content??this.createSeriesContent(B),H=u6(Z);if(Y?.contentHash===H)continue;let K={id:X,entityType:"series",content:Z,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:O1(B)}};await this.entityService.upsertEntity({entity:K}),this.logger.debug(`Upserted series: ${B}`)}for(let B of Q)if(!w.has(B.id))await this.entityService.deleteEntity({entityType:"series",id:B.id}),this.logger.debug(`Deleted orphaned series: ${B.id}`)}async handleEntityChange(A,Q){let $=Ny(A);if($)await this.ensureSeriesExists($);if(Q&&Q!==$)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=O1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let w=this.createSeriesContent(A),B={id:Q,entityType:"series",content:w,contentHash:u6(w),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:O1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=O1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let $ of Q){if($==="series")continue;if((await this.entityService.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let $ of Q){if($==="series")continue;let w=await this.entityService.listEntities({entityType:$});for(let B of w){let X=Ny(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:O1(A)};return i7("",Q)}}zA();h0();var Fd$=W.object({entityType:W.literal("series"),query:W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional()})}),Ld$=W.object({type:W.enum(["list","detail"]),seriesName:W.string().optional()});function Id$(A){let Q=Ld$.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let $=Fd$.safeParse(A);if($.success){let{query:w}=$.data;if(w.id)return{type:"detail",seriesSlug:w.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Gr2(A){let Q=MQ(A.content,iV);return Hk0.parse({...A,frontmatter:Q.metadata})}class vJA{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,$){let w=Id$(A),B=$.entityService;if(w.type==="list")return this.fetchSeriesList(Q,B);if(w.seriesName)return this.fetchSeriesDetail(w.seriesName,Q,B);if(w.seriesSlug)return this.fetchSeriesDetailBySlug(w.seriesSlug,Q,B);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let $=await Q.listEntities({entityType:"series"}),w=await this.countEntitiesPerSeries(Q),B=$.map((X)=>{let Y=Gr2(X),Z=ef.parseBody(X.content);return{...Y,description:Z.description,postCount:w.get(X.metadata.title)??0}});return this.logger.debug(`Found ${B.length} series entities`),A.parse({series:B})}async fetchSeriesDetail(A,Q,$,w){if(!w)w=(await $.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!w)throw Error(`Series not found: ${A}`);let B=Gr2(w),X=ef.parseBody(w.content),Y=await this.getSeriesMembers(A,$);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...B,description:X.description,postCount:Y.length},description:X.description})}async fetchSeriesDetailBySlug(A,Q,$){let B=(await $.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!B)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail(B.metadata.title,Q,$,B)}async countEntitiesPerSeries(A){let Q=new Map,$=A.getEntityTypes();for(let w of $){if(w==="series")continue;let B=await A.listEntities({entityType:w});for(let X of B){let Y=Ny(X);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let $=[],w=Q.getEntityTypes();for(let B of w){if(B==="series")continue;let X=await Q.listEntities({entityType:B,options:{filter:{metadata:{seriesName:A}}}});$.push(...X)}return $.sort(Ur2),$}}zA();h0();EZ();var Nd$=W.object({prompt:W.string().optional(),title:W.string().optional(),seriesId:W.string().optional()}),_d$=W.object({title:W.string().optional(),excerpt:W.string().optional()});class Uk0{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 $=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!$)return{success:!1,error:`Series not found: ${Q}`};let w=await this.gatherMemberSummaries($.metadata.title);if(w.length===0)return{success:!1,error:`No members found in series: ${$.metadata.title}`};let B=A.prompt??`Series name: ${$.metadata.title}
7147
+ `}},void 0,!1,void 0,this),nY("header",{className:"printable-hero",children:[nY("div",{className:"printable-masthead",children:Q.brandLabel&&nY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),nY("div",{children:[nY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&nY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),nY("div",{className:"printable-meta",children:[Q.author&&nY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),$&&nY("span",{children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&nY("figure",{className:"printable-cover-wrap",children:nY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),nY(XX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&nY("footer",{className:"printable-footer",children:[nY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&nY("a",{href:Q.canonicalUrl,children:Q.canonicalUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var si$=26214400,ai$=60000;class MJA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Wk0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=ti$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await di$(oi$(ri$(),"brain-blog-printable-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/printable/post/${Q.id}`,template:$r2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:si$,timeoutMs:ai$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${ei$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await ni$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=UB.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function ti$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=UB.parse($);return{title:B.title,body:w,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.canonicalUrl?{canonicalUrl:B.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function ei$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}import{mkdtemp as Bd$,rm as Xd$}from"fs/promises";import{tmpdir as Yd$}from"os";import{join as Zd$}from"path";u4();p2();AD();h0();import{jsxDEV as wd$}from"preact/jsx-dev-runtime";var eB0="og-image",Ad$="blog:og-image",wr2=W.object({title:W.string().min(1),excerpt:W.string().optional(),author:W.string().optional(),publishedAt:W.string().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),Br2={name:Ad$,pluginId:"blog",schema:wr2,renderers:{image:$d$}};function Qd$(A){if(!A)return;let Q=new Date(A);if(Number.isNaN(Q.getTime()))return;return Q.toLocaleDateString("en-GB",{year:"numeric",month:"short",day:"2-digit"})}function $d$(A){let Q=wr2.parse(A);return wd$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Qd$(Q.publishedAt)},void 0,!1,void 0,this)}var Wd$={width:1200,height:630},Hd$=60000;class kJA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??tB0}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==eB0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=Kd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Bd$(Zd$(Yd$(),"brain-blog-og-image-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/og/post/${Q.id}`,template:Br2,format:"image",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),Wd$,{timeoutMs:Hd$,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${Ud$(Q)}-og.png`}}finally{await X.close()}}finally{await Xd$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=UB.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function Kd$(A,Q={}){let{frontmatter:$}=t8(A.content),w=UB.parse($);return{title:w.title,...w.excerpt?{excerpt:w.excerpt}:{},...w.author?{author:w.author}:{},...w.publishedAt?{publishedAt:w.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Ud$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var Xr2={name:"@brains/blog",version:"0.2.0-alpha.196",description:"AI-powered blog post generation from existing brain content",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class OJA extends c6{entityType=bb.entityType;schema=kr;adapter=bb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Xr2,A,DJA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new qJA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return un2()}getDataSources(){return[new VJA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (Wr2(),Zr2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),cn2(A,this.logger),pn2(A,this.logger),in2(A,this.logger),dn2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Wk0,new MJA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",eB0,new kJA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=D9.getInstance().register(LJA()),this.logger.info("Blog plugin registered (routes auto-generated at /posts/)")}deferPublishAssetRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish-assets:register",payload:{entityType:"post",attachmentType:eB0,mediaEntityType:"image",targetEntityField:{location:"frontmatter",field:"ogImageId"},requiredWhen:{status:"published"},autoGenerate:!0,jobType:"image:image-render-source"}}),{success:!0}})}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function fJA(A={}){return new OJA(A)}AD();fr();zA();h0();e9();zA();h0();var iV=W.object({title:W.string(),slug:W.string(),coverImageId:W.string().optional()}),qd$=W.object({title:W.string(),slug:W.string()}),zd$=W.object({title:W.string(),slug:W.string()}),tf=U6.extend({entityType:W.literal("series"),metadata:zd$}),Hk0=tf.extend({frontmatter:iV}),Vd$=Hk0.extend({description:W.string().optional(),postCount:W.number(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Hr2=W.object({description:W.string().optional()});function Iy(A){return new n$(Hr2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}zA();class xJA extends zQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:tf,frontmatterSchema:iV,supportsCoverImage:!0,bodyFormatter:Iy("")})}toMarkdown(A){let Q,$={};try{Q=this.parseFrontMatter(A.content,iV).coverImageId,$=Iy(A.metadata.title).parse(this.extractBody(A.content))}catch{}let w={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=Iy(A.metadata.title).format($);return this.buildMarkdown(X,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,iV);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,iV);return Iy(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var ef=new xJA;zA();p2();EZ();h0();var Jd$=W.object({seriesName:W.string().optional(),seriesIndex:W.number().optional()});function Kk0(A){let Q=Jd$.safeParse(A);return Q.success?Q.data:{}}function Ny(A){return Kk0(A.metadata).seriesName}function Kr2(A){return Kk0(A.metadata).seriesIndex}function Ur2(A,Q){let $=Kr2(A)??Number.MAX_SAFE_INTEGER,w=Kr2(Q)??Number.MAX_SAFE_INTEGER;return $-w}class RJA{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),$=new Map(Q.map((B)=>[B.id,B])),w=new Set;for(let B of A){let X=O1(B);w.add(X);let Y=$.get(X),Z=Y?.content??this.createSeriesContent(B),H=u6(Z);if(Y?.contentHash===H)continue;let K={id:X,entityType:"series",content:Z,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:O1(B)}};await this.entityService.upsertEntity({entity:K}),this.logger.debug(`Upserted series: ${B}`)}for(let B of Q)if(!w.has(B.id))await this.entityService.deleteEntity({entityType:"series",id:B.id}),this.logger.debug(`Deleted orphaned series: ${B.id}`)}async handleEntityChange(A,Q){let $=Ny(A);if($)await this.ensureSeriesExists($);if(Q&&Q!==$)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=O1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let w=this.createSeriesContent(A),B={id:Q,entityType:"series",content:w,contentHash:u6(w),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:O1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=O1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let $ of Q){if($==="series")continue;if((await this.entityService.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let $ of Q){if($==="series")continue;let w=await this.entityService.listEntities({entityType:$});for(let B of w){let X=Ny(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:O1(A)};return i7("",Q)}}zA();h0();var Fd$=W.object({entityType:W.literal("series"),query:W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional()})}),Ld$=W.object({type:W.enum(["list","detail"]),seriesName:W.string().optional()});function Id$(A){let Q=Ld$.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let $=Fd$.safeParse(A);if($.success){let{query:w}=$.data;if(w.id)return{type:"detail",seriesSlug:w.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Gr2(A){let Q=MQ(A.content,iV);return Hk0.parse({...A,frontmatter:Q.metadata})}class vJA{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,$){let w=Id$(A),B=$.entityService;if(w.type==="list")return this.fetchSeriesList(Q,B);if(w.seriesName)return this.fetchSeriesDetail(w.seriesName,Q,B);if(w.seriesSlug)return this.fetchSeriesDetailBySlug(w.seriesSlug,Q,B);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let $=await Q.listEntities({entityType:"series"}),w=await this.countEntitiesPerSeries(Q),B=$.map((X)=>{let Y=Gr2(X),Z=ef.parseBody(X.content);return{...Y,description:Z.description,postCount:w.get(X.metadata.title)??0}});return this.logger.debug(`Found ${B.length} series entities`),A.parse({series:B})}async fetchSeriesDetail(A,Q,$,w){if(!w)w=(await $.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!w)throw Error(`Series not found: ${A}`);let B=Gr2(w),X=ef.parseBody(w.content),Y=await this.getSeriesMembers(A,$);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...B,description:X.description,postCount:Y.length},description:X.description})}async fetchSeriesDetailBySlug(A,Q,$){let B=(await $.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!B)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail(B.metadata.title,Q,$,B)}async countEntitiesPerSeries(A){let Q=new Map,$=A.getEntityTypes();for(let w of $){if(w==="series")continue;let B=await A.listEntities({entityType:w});for(let X of B){let Y=Ny(X);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let $=[],w=Q.getEntityTypes();for(let B of w){if(B==="series")continue;let X=await Q.listEntities({entityType:B,options:{filter:{metadata:{seriesName:A}}}});$.push(...X)}return $.sort(Ur2),$}}zA();h0();EZ();var Nd$=W.object({prompt:W.string().optional(),title:W.string().optional(),seriesId:W.string().optional()}),_d$=W.object({title:W.string().optional(),excerpt:W.string().optional()});class Uk0{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 $=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!$)return{success:!1,error:`Series not found: ${Q}`};let w=await this.gatherMemberSummaries($.metadata.title);if(w.length===0)return{success:!1,error:`No members found in series: ${$.metadata.title}`};let B=A.prompt??`Series name: ${$.metadata.title}
7148
7148
 
7149
7149
  Content in this series:
7150
7150
  ${w.join(`
@@ -7156,7 +7156,7 @@ Your task is to write a series description (2-3 sentences) that:
7156
7156
  3. Is engaging and makes readers want to explore the content
7157
7157
  4. Works well as a series overview on a website
7158
7158
 
7159
- Be concise and focus on what makes this series unique and valuable.`});async function Ir2({entity:A,config:Q}){let $=tf.parse(A),w=ef.parseBody($.content);return{$type:"ai.rizom.brain.series",title:$.metadata.title,slug:$.metadata.slug,...w.description&&{description:w.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function CJA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:i8["ai.rizom.brain.series"],validate:!1,buildRecord:Ir2}}var Nr2={name:"@brains/series",version:"0.2.0-alpha.195",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/entity-service":"workspace:*","@brains/job-queue":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var _r2=W.discriminatedUnion("mode",[W.object({mode:W.literal("derive"),reason:W.string().optional()}),W.object({mode:W.literal("source"),entityId:W.string(),entityType:W.string(),seriesName:W.string().optional(),previousSeriesName:W.string().optional()})]);class hJA extends c6{entityType="series";schema=tf;adapter=ef;manager;unregisterAtprotoProjection;constructor(){super("series",Nr2,{},bY)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Uk0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Fr2(),description:Lr2}}getDataSources(){return[new vJA(this.logger.child("SeriesDataSource"))]}getDerivedEntityProjections(A){return[{id:"series-projection",targetType:"series",job:{type:"series:project",handler:this.createSeriesProjectionHandler(A)},initialSync:{jobData:{mode:"derive",reason:"initial-sync"},jobOptions:this.getSyncProjectionJobOptions("initial-sync")},sourceChange:{sourceTypes:["*"],events:["entity:created","entity:updated","entity:deleted"],requireInitialSync:!0,jobData:(Q)=>{if(Q.entityType==="series")return null;if(!Q.entity)return null;let $=Ny(Q.entity),w=Kk0(Q.previousMetadata).seriesName;if(!$&&!w)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...$?{seriesName:$}:{},...w&&w!==$?{previousSeriesName:w}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new RJA(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=D9.getInstance().register(CJA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let $=_r2.parse(Q);if($.mode==="derive")return await this.projectAll(A),{success:!0};let w=await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(w)await this.projectSource(w,$.previousSeriesName);else{let B=this.requireManager();for(let X of[$.seriesName,$.previousSeriesName])if(X)await B.cleanupOrphanedSeries(X)}return{success:!0}},validateAndParse:(Q)=>{let $=_r2.safeParse(Q??{});return $.success?$.data:null}}}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}getSyncProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-sync:${A}`,metadata:{operationType:"data_processing",operationTarget:"series"}}}getSourceProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-source:${A.entityType}:${A.id}`,metadata:{operationType:"data_processing",operationTarget:`series:${A.entityType}:${A.id}`}}}async projectSource(A,Q){await this.requireManager().handleEntityChange(A,Q)}async projectAll(A){await this.requireManager().syncAllSeries();let Q=new Uk0(this.logger.child("SeriesGenerationHandler"),A),$=await A.entityService.listEntities({entityType:"series"});for(let w of $)try{if(!this.adapter.parseBody(w.content).description)this.logger.info(`Generating description for series: ${w.metadata.title}`),await Q.process({seriesId:w.id})}catch(B){this.logger.error(`Failed to generate description for series: ${w.id}`,{error:B})}}}function EJA(){return new hJA}zA();h0();zA();p2();h0();zA();var Pr2=W.enum(["generating","draft","queued","published","failed"]),br2=W.enum(["generating","draft","queued","published","failed"]),TJA="publishedAt is required when deck status is published",yJA=(A)=>A.status==="published"&&!A.publishedAt,gJA=(A)=>{if(yJA(A))throw Error(TJA)},aL=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:Pr2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),te5=W.object({title:W.string(),description:W.string().optional(),status:Pr2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!yJA(A))return;Q.addIssue({code:W.ZodIssueCode.custom,path:["publishedAt"],message:TJA})}),Rd$=W.object({title:W.string(),description:W.string().optional(),status:br2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!yJA(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:TJA})}),vd$=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:br2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),vr=U6.extend({entityType:W.literal("deck"),metadata:Rd$}),Gk0=vr.extend({frontmatter:vd$,body:W.string(),ogImageUrl:W.string().optional()}),A90=Gk0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});class SJA extends zQ{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:vr,frontmatterSchema:aL,supportsCoverImage:!0})}validateSlideStructure(A){if(!/^---$/gm.test(A))throw Error("Invalid deck: markdown must contain slide separators (---) to be a valid presentation")}toMarkdown(A){let Q=this.extractBody(A.content);this.validateSlideStructure(Q);let $=this.parseFrontMatter(A.content,aL);gJA($);let w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontmatter(A),$=this.extractBody(A);gJA(Q),this.validateSlideStructure($);let w=Q.slug??O1(Q.title),B=Q.status;return{entityType:"deck",content:A,metadata:{slug:w,title:Q.title,description:Q.description,status:B,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
7159
+ Be concise and focus on what makes this series unique and valuable.`});async function Ir2({entity:A,config:Q}){let $=tf.parse(A),w=ef.parseBody($.content);return{$type:"ai.rizom.brain.series",title:$.metadata.title,slug:$.metadata.slug,...w.description&&{description:w.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function CJA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:i8["ai.rizom.brain.series"],validate:!1,buildRecord:Ir2}}var Nr2={name:"@brains/series",version:"0.2.0-alpha.196",description:"Cross-content series \u2014 auto-derived from entities with seriesName metadata",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/entity-service":"workspace:*","@brains/job-queue":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var _r2=W.discriminatedUnion("mode",[W.object({mode:W.literal("derive"),reason:W.string().optional()}),W.object({mode:W.literal("source"),entityId:W.string(),entityType:W.string(),seriesName:W.string().optional(),previousSeriesName:W.string().optional()})]);class hJA extends c6{entityType="series";schema=tf;adapter=ef;manager;unregisterAtprotoProjection;constructor(){super("series",Nr2,{},bY)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Uk0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Fr2(),description:Lr2}}getDataSources(){return[new vJA(this.logger.child("SeriesDataSource"))]}getDerivedEntityProjections(A){return[{id:"series-projection",targetType:"series",job:{type:"series:project",handler:this.createSeriesProjectionHandler(A)},initialSync:{jobData:{mode:"derive",reason:"initial-sync"},jobOptions:this.getSyncProjectionJobOptions("initial-sync")},sourceChange:{sourceTypes:["*"],events:["entity:created","entity:updated","entity:deleted"],requireInitialSync:!0,jobData:(Q)=>{if(Q.entityType==="series")return null;if(!Q.entity)return null;let $=Ny(Q.entity),w=Kk0(Q.previousMetadata).seriesName;if(!$&&!w)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...$?{seriesName:$}:{},...w&&w!==$?{previousSeriesName:w}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new RJA(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=D9.getInstance().register(CJA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let $=_r2.parse(Q);if($.mode==="derive")return await this.projectAll(A),{success:!0};let w=await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(w)await this.projectSource(w,$.previousSeriesName);else{let B=this.requireManager();for(let X of[$.seriesName,$.previousSeriesName])if(X)await B.cleanupOrphanedSeries(X)}return{success:!0}},validateAndParse:(Q)=>{let $=_r2.safeParse(Q??{});return $.success?$.data:null}}}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}getSyncProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-sync:${A}`,metadata:{operationType:"data_processing",operationTarget:"series"}}}getSourceProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-source:${A.entityType}:${A.id}`,metadata:{operationType:"data_processing",operationTarget:`series:${A.entityType}:${A.id}`}}}async projectSource(A,Q){await this.requireManager().handleEntityChange(A,Q)}async projectAll(A){await this.requireManager().syncAllSeries();let Q=new Uk0(this.logger.child("SeriesGenerationHandler"),A),$=await A.entityService.listEntities({entityType:"series"});for(let w of $)try{if(!this.adapter.parseBody(w.content).description)this.logger.info(`Generating description for series: ${w.metadata.title}`),await Q.process({seriesId:w.id})}catch(B){this.logger.error(`Failed to generate description for series: ${w.id}`,{error:B})}}}function EJA(){return new hJA}zA();h0();zA();p2();h0();zA();var Pr2=W.enum(["generating","draft","queued","published","failed"]),br2=W.enum(["generating","draft","queued","published","failed"]),TJA="publishedAt is required when deck status is published",yJA=(A)=>A.status==="published"&&!A.publishedAt,gJA=(A)=>{if(yJA(A))throw Error(TJA)},aL=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:Pr2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),te5=W.object({title:W.string(),description:W.string().optional(),status:Pr2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!yJA(A))return;Q.addIssue({code:W.ZodIssueCode.custom,path:["publishedAt"],message:TJA})}),Rd$=W.object({title:W.string(),description:W.string().optional(),status:br2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!yJA(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:TJA})}),vd$=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:br2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),vr=U6.extend({entityType:W.literal("deck"),metadata:Rd$}),Gk0=vr.extend({frontmatter:vd$,body:W.string(),ogImageUrl:W.string().optional()}),A90=Gk0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});class SJA extends zQ{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:vr,frontmatterSchema:aL,supportsCoverImage:!0})}validateSlideStructure(A){if(!/^---$/gm.test(A))throw Error("Invalid deck: markdown must contain slide separators (---) to be a valid presentation")}toMarkdown(A){let Q=this.extractBody(A.content);this.validateSlideStructure(Q);let $=this.parseFrontMatter(A.content,aL);gJA($);let w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontmatter(A),$=this.extractBody(A);gJA(Q),this.validateSlideStructure($);let w=Q.slug??O1(Q.title),B=Q.status;return{entityType:"deck",content:A,metadata:{slug:w,title:Q.title,description:Q.description,status:B,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
7160
7160
  `,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var Q90=new SJA;h0();D5();var Cd$=W.object({markdown:W.string().describe("Markdown content with slide separators (---)"),deck:A90.optional()}),mJA=G2({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:Cd$,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:sqA,fullscreen:!0}});D5();h0();var uJA=W.object({decks:W.array(Gk0)}),cJA=W.object({decks:W.array(A90),pageTitle:W.string().optional(),pageLabel:W.string().optional()});import{jsxDEV as pJA}from"preact/jsx-dev-runtime";var hd$="Presentations",lJA=({decks:A,pageLabel:Q})=>{let $=A.map((B)=>({id:B.id,url:B.url,title:B.frontmatter.title,date:B.frontmatter.publishedAt??B.created,description:B.frontmatter.description}));return pJA("div",{className:"deck-list bg-theme",children:pJA("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:pJA(d50,{label:Q&&Q!=="Decks"?Q:hd$,items:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};e9();class Dk0 extends n${constructor(){super(uJA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var iJA=G2({name:"deck-list",description:"List view of all presentation decks",schema:cJA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new Dk0,layout:{component:lJA}});h0();zA();var Ed$=W.object({title:W.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:W.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:W.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),jr2=G2({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:Ed$,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
7161
7161
 
7162
7162
  Your task is to generate a complete slide deck based on the user's prompt.
@@ -7464,7 +7464,7 @@ ${Z}`,templateName:"decks:description"})).description,await this.reportProgress(
7464
7464
  color: var(--carousel-accent);
7465
7465
  font-weight: 600;
7466
7466
  }
7467
- `}},void 0,!1,void 0,this),B.map((K,U)=>zW("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[zW("header",{className:"deck-carousel-header",children:zW("span",{className:"deck-carousel-wordmark","aria-label":$??Q,children:[zW("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&zW(ud$,{children:[zW("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),zW("span",{className:"wm-secondary",children:X.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),zW("div",{className:"deck-carousel-body",children:zW("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),zW("footer",{className:"deck-carousel-footer",children:[zW("span",{className:"deck-carousel-footer-meta",children:w??Q},void 0,!1,void 0,this),zW("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[zW("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",zW("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},U,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as cd$,rm as pd$}from"fs/promises";import{tmpdir as ld$}from"os";import{join as id$}from"path";u4();p2();var dd$=26214400,nd$=60000,xr2=20;class rJA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let $=rd$(Q,{brandLabel:this.resolveBrandLabel()});if($.slides.length>xr2)throw Error(`Refusing to render carousel with ${$.slides.length} slides; maxSlides=${xr2}`);let w=await this.getThemeMode(),B=await cd$(id$(ld$(),"brain-deck-carousel-"));try{let X=await $D({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:fr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:w},themeCSS:this.context.themeCSS}),Y=await wD({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:dd$,timeoutMs:nd$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${od$(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await pd$(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function rd$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=typeof $.title==="string"?$.title:A.metadata.title,X=typeof $.event==="string"&&$.event.length>0?$.event:void 0,Y=w.split(/^---$/gm).map((Z)=>Z.trim()).filter((Z)=>Z.length>0).map((Z)=>({markdown:Z}));return{title:B,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...X?{eyebrow:X}:{}}}function od$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}h0();import{jsxDEV as td$}from"preact/jsx-dev-runtime";var qk0="og-image",sd$="decks:og-image",Rr2=W.object({title:W.string().min(1),description:W.string().optional(),event:W.string().optional(),brandLabel:W.string().optional(),slideCount:W.number().int().positive().optional(),coverImageUrl:W.string().optional()}),vr2={name:sd$,pluginId:"decks",schema:Rr2,renderers:{image:ad$}};function ad$(A){let Q=Rr2.parse(A),$=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return td$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:$},void 0,!1,void 0,this)}u4();p2();class oJA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==qk0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=aL.parse($),X=ed$(w),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),H={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Ly({mediaPath:`/_media/og/deck/${Q.id}`,template:vr2,content:H,title:H.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${An$(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function ed$(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function An$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}zA();async function Cr2({entity:A,config:Q}){let $=vr.parse(A),w=MQ($.content,aL),B=w.metadata;return{$type:"ai.rizom.brain.deck",title:B.title,...B.slug&&{slug:B.slug},...B.description&&{description:B.description},body:w.content,format:"text/markdown",...B.author&&{author:B.author},...B.event&&{event:B.event},...B.publishedAt&&{publishedAt:B.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function sJA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:i8["ai.rizom.brain.deck"],validate:!1,buildRecord:Cr2}}var hr2={name:"@brains/decks",version:"0.2.0-alpha.195",description:"Presentation decks plugin for creating and viewing slide presentations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var $n$=W.object({prompt:W.string(),event:W.string().optional()}),wn$=W.object({title:W.string(),content:W.string()});class aJA extends c6{deps;entityType=Q90.entityType;schema=Q90.schema;adapter=Q90;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",hr2,{},bY);this.deps=A}createGenerationHandler(A){return new nJA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":mJA,"deck-list":iJA,generation:jr2,description:Mr2}}getDataSources(){return[new dJA(this.logger)]}getEntityTypeConfig(){return{weight:1.5}}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.registerCarouselAttachmentProvider(A),this.registerOgImageAttachmentProvider(A),this.registerEvalHandlers(A),this.unregisterAtprotoProjection=D9.getInstance().register(sJA()),this.logger.info("Decks plugin registered")}async onShutdown(){this.unregisterCarouselAttachmentProvider?.(),this.unregisterCarouselAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}deferPublishRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})},config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:$,entityId:w}=Q.payload;if($!=="deck")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"deck",id:w});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:`Deck not found: ${w}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=new Date().toISOString(),Y={...B,metadata:{...B.metadata,status:"published",publishedAt:X}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:$,entityId:w,result:{id:w}}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:eA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await nB0(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",kr2,new rJA(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",qk0,new oJA(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let $=$n$.parse(Q);return A.ai.generate({prompt:`${$.prompt}${$.event?`
7467
+ `}},void 0,!1,void 0,this),B.map((K,U)=>zW("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[zW("header",{className:"deck-carousel-header",children:zW("span",{className:"deck-carousel-wordmark","aria-label":$??Q,children:[zW("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&zW(ud$,{children:[zW("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),zW("span",{className:"wm-secondary",children:X.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),zW("div",{className:"deck-carousel-body",children:zW("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),zW("footer",{className:"deck-carousel-footer",children:[zW("span",{className:"deck-carousel-footer-meta",children:w??Q},void 0,!1,void 0,this),zW("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[zW("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",zW("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},U,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as cd$,rm as pd$}from"fs/promises";import{tmpdir as ld$}from"os";import{join as id$}from"path";u4();p2();var dd$=26214400,nd$=60000,xr2=20;class rJA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let $=rd$(Q,{brandLabel:this.resolveBrandLabel()});if($.slides.length>xr2)throw Error(`Refusing to render carousel with ${$.slides.length} slides; maxSlides=${xr2}`);let w=await this.getThemeMode(),B=await cd$(id$(ld$(),"brain-deck-carousel-"));try{let X=await $D({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:fr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:w},themeCSS:this.context.themeCSS}),Y=await wD({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:dd$,timeoutMs:nd$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${od$(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await pd$(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function rd$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=typeof $.title==="string"?$.title:A.metadata.title,X=typeof $.event==="string"&&$.event.length>0?$.event:void 0,Y=w.split(/^---$/gm).map((Z)=>Z.trim()).filter((Z)=>Z.length>0).map((Z)=>({markdown:Z}));return{title:B,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...X?{eyebrow:X}:{}}}function od$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}h0();import{jsxDEV as td$}from"preact/jsx-dev-runtime";var qk0="og-image",sd$="decks:og-image",Rr2=W.object({title:W.string().min(1),description:W.string().optional(),event:W.string().optional(),brandLabel:W.string().optional(),slideCount:W.number().int().positive().optional(),coverImageUrl:W.string().optional()}),vr2={name:sd$,pluginId:"decks",schema:Rr2,renderers:{image:ad$}};function ad$(A){let Q=Rr2.parse(A),$=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return td$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:$},void 0,!1,void 0,this)}u4();p2();class oJA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="deck"||A.attachmentType!==qk0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=aL.parse($),X=ed$(w),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),H={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Ly({mediaPath:`/_media/og/deck/${Q.id}`,template:vr2,content:H,title:H.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${An$(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function ed$(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function An$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}zA();async function Cr2({entity:A,config:Q}){let $=vr.parse(A),w=MQ($.content,aL),B=w.metadata;return{$type:"ai.rizom.brain.deck",title:B.title,...B.slug&&{slug:B.slug},...B.description&&{description:B.description},body:w.content,format:"text/markdown",...B.author&&{author:B.author},...B.event&&{event:B.event},...B.publishedAt&&{publishedAt:B.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function sJA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:i8["ai.rizom.brain.deck"],validate:!1,buildRecord:Cr2}}var hr2={name:"@brains/decks",version:"0.2.0-alpha.196",description:"Presentation decks plugin for creating and viewing slide presentations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/image":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/site-info":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var $n$=W.object({prompt:W.string(),event:W.string().optional()}),wn$=W.object({title:W.string(),content:W.string()});class aJA extends c6{deps;entityType=Q90.entityType;schema=Q90.schema;adapter=Q90;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",hr2,{},bY);this.deps=A}createGenerationHandler(A){return new nJA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":mJA,"deck-list":iJA,generation:jr2,description:Mr2}}getDataSources(){return[new dJA(this.logger)]}getEntityTypeConfig(){return{weight:1.5}}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.registerCarouselAttachmentProvider(A),this.registerOgImageAttachmentProvider(A),this.registerEvalHandlers(A),this.unregisterAtprotoProjection=D9.getInstance().register(sJA()),this.logger.info("Decks plugin registered")}async onShutdown(){this.unregisterCarouselAttachmentProvider?.(),this.unregisterCarouselAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}deferPublishRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})},config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:$,entityId:w}=Q.payload;if($!=="deck")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"deck",id:w});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:`Deck not found: ${w}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=new Date().toISOString(),Y={...B,metadata:{...B.metadata,status:"published",publishedAt:X}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:$,entityId:w,result:{id:w}}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:eA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await nB0(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",kr2,new rJA(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",qk0,new oJA(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let $=$n$.parse(Q);return A.ai.generate({prompt:`${$.prompt}${$.event?`
7468
7468
 
7469
7469
  Note: This presentation is for "${$.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let $=wn$.parse(Q);return A.ai.generate({prompt:`Title: ${$.title}
7470
7470
 
@@ -7621,9 +7621,9 @@ ${$.content}`,templateName:"decks:description"})})}}function w90(){return new aJ
7621
7621
  background: transparent;
7622
7622
  }
7623
7623
 
7624
- `,lr2=()=>J4("style",{children:Hn$},void 0,!1,void 0,this);import{jsxDEV as GQ,Fragment as Kn$}from"preact/jsx-dev-runtime";var Lk0=({title:A,description:Q,children:$,detail:w=!1,footer:B=!1,contentClassName:X=""})=>GQ(Kn$,{children:[GQ(E6,{title:A,description:Q},void 0,!1,void 0,this),GQ(lr2,{},void 0,!1,void 0,this),GQ("div",{className:`docs-handbook${w?" docs-handbook--detail":""}`,children:[GQ(cr2,{},void 0,!1,void 0,this),GQ("div",{className:`${tL.wrap} ${X}`.trim(),children:[$,B&&GQ(pr2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ir2=({docsCount:A,sectionsCount:Q,startDoc:$})=>GQ("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[GQ("p",{className:`${tL.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),GQ("h1",{className:`${tL.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",GQ("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GQ("p",{className:"mt-8 max-w-[52ch] text-lg leading-[1.65] text-[var(--docs-text-muted)]",children:"Documentation for composing brain models, managing markdown entities, wiring interfaces, and shipping generated sites."},void 0,!1,void 0,this),GQ("dl",{className:"mt-10 flex flex-wrap gap-7 docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] md:mt-14 md:gap-12",children:[GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:A},void 0,!1,void 0,this),"Documents"]},void 0,!0,void 0,this),GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:Q},void 0,!1,void 0,this),"Sections"]},void 0,!0,void 0,this),GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:"April 2026"},void 0,!1,void 0,this),"Updated"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),GQ("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[$&&GQ("a",{className:tL.primaryButton,href:hr($),children:"Start reading"},void 0,!1,void 0,this),GQ("a",{className:tL.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),dr2=({groups:A})=>GQ("aside",{className:"docs-rail sticky top-8 hidden docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] min-[861px]:block","aria-label":"Documentation sections",children:[GQ("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.map((Q,$)=>GQ("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[GQ("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Er($),"."]},void 0,!0,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Fk0($)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),nr2=({group:A,index:Q})=>GQ("article",{className:"mb-16 last:mb-0",id:Fk0(Q),children:[GQ("header",{className:"mb-2 grid grid-cols-[36px_auto_1fr] items-baseline gap-x-3 border-b border-[var(--docs-border)] pb-3.5 md:grid-cols-[48px_auto_1fr] md:gap-x-5",children:[GQ("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Er(Q),"."]},void 0,!0,void 0,this),GQ("h2",{className:`${tL.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),GQ("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.docs.map(($)=>GQ("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:GQ("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:hr($),children:[GQ("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:$.metadata.title},void 0,!1,void 0,this),$.metadata.description&&GQ("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:$.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},$.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),rr2=({title:A})=>GQ("nav",{className:"mb-8 flex flex-wrap items-baseline gap-2.5 docs-font-label text-[11px] uppercase tracking-[0.06em] text-[var(--docs-text-light)]","aria-label":"Breadcrumb",children:[GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),GQ("span",{children:"/"},void 0,!1,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),GQ("span",{children:"/"},void 0,!1,void 0,this),GQ("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),or2=({groups:A,activeGroupIndex:Q,activeSlug:$})=>GQ("aside",{className:"docs-detail-rail sticky top-24 hidden max-h-[calc(100vh-120px)] overflow-auto pr-2 min-[861px]:block","aria-label":"Documentation navigation",children:GQ("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[GQ("p",{className:"m-0 mb-4 border-b border-[var(--docs-text)] pb-3 text-[11px] uppercase tracking-[0.08em] text-[var(--docs-text-light)]",children:"Documentation"},void 0,!1,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.map((w,B)=>{let X=B===Q;return GQ("li",{className:X?"mb-[22px]":"mb-3.5",children:[GQ("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${X?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${Fk0(B)}`,children:[GQ("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Er(B),"."]},void 0,!0,void 0,this)," ",w.section]},void 0,!0,void 0,this),X&&GQ("ol",{className:"mt-0.5 list-none p-0",children:w.docs.map((Y)=>{let Z=Y.metadata.slug===$;return GQ("li",{children:GQ("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${Z?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:hr(Y),"aria-current":Z?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},w.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),sr2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return GQ("nav",{className:"mt-12 grid grid-cols-1 gap-5 border-t border-[var(--docs-border)] pt-7 md:grid-cols-2","aria-label":"Previous and next docs",children:[A?GQ("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:hr(A),children:[GQ("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Previous"},void 0,!1,void 0,this),GQ("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:["\u2190 ",A.metadata.title]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):GQ("span",{},void 0,!1,void 0,this),Q&&GQ("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] text-left transition-colors duration-150 hover:border-[var(--docs-accent)] md:text-right",href:hr(Q),children:[GQ("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Next"},void 0,!1,void 0,this),GQ("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:[Q.metadata.title," \u2192"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as Tr}from"preact/jsx-dev-runtime";var QFA=({docs:A})=>{let Q=B90(A),$=Jk0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return Tr(Lk0,{title:"Documentation",description:"Brains documentation",children:[Tr(ir2,{docsCount:A.length,sectionsCount:$.length,startDoc:B},void 0,!1,void 0,this),Tr("section",{className:"grid items-start gap-10 py-12 md:grid-cols-[200px_minmax(0,1fr)] md:gap-20 md:py-20 md:pb-[120px]",id:"sections",children:[Tr(dr2,{groups:$},void 0,!1,void 0,this),Tr("div",{children:$.map((X,Y)=>Tr(nr2,{group:X,index:Y},X.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as BD}from"preact/jsx-dev-runtime";var $FA=({doc:A,docs:Q,prevDoc:$,nextDoc:w})=>{let B=Jk0(Q.length>0?Q:[A]),X=B90(Q.length>0?Q:[A]),Y=X.findIndex((H)=>H.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((H)=>H.docs.some((K)=>K.metadata.slug===A.metadata.slug)),0);return BD(Lk0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[BD(rr2,{title:A.metadata.title},void 0,!1,void 0,this),BD("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[BD(or2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),BD("article",{className:"min-w-0",children:[BD("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[BD("p",{className:`${tL.label} m-0 mb-6 flex items-baseline gap-3`,children:[BD("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Er(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),BD("h1",{className:`${tL.display} m-0 max-w-[18ch] text-4xl leading-[1.05] tracking-[-0.02em] md:text-6xl`,children:A.metadata.title},void 0,!1,void 0,this),A.metadata.description&&BD("p",{className:"mt-6 max-w-[56ch] docs-font-display text-[22px] font-[350] leading-[1.5] text-[var(--docs-text-muted)]",children:A.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),BD("div",{className:"docs-article__body",children:BD(XX,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),BD(sr2,{prevDoc:$,nextDoc:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var Un$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Gn$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Dn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),sourcePath:W.string(),description:W.string().optional(),slug:W.string().optional()}),qn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),description:W.string().optional(),slug:W.string()}),X90=W.object({id:W.string(),entityType:W.literal("doc"),content:W.string(),created:W.string(),updated:W.string(),visibility:Gn$,metadata:qn$,contentHash:W.string(),frontmatter:Dn$,body:W.string()}),zn$=W.object({docs:W.array(X90),pagination:Un$.nullable(),baseUrl:W.string().optional()}),Vn$=W.object({doc:X90,docs:W.array(X90),prevDoc:X90.nullable(),nextDoc:X90.nullable()});function ar2(){return{"doc-list":G2({name:"doc-list",description:"Documentation index template",schema:zn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:QFA}}),"doc-detail":G2({name:"doc-detail",description:"Documentation page template",schema:Vn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:$FA}})}}var tr2={name:"@brains/doc",version:"0.2.0-alpha.195",description:"Documentation entity type \u2014 markdown docs as first-class brain content",dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class wFA extends c6{entityType=zk0.entityType;schema=Cr;adapter=zk0;constructor(){super("docs",tr2,{},bY)}getTemplates(){return ar2()}getDataSources(){return[new Vk0(this.logger.child("DocDataSource"))]}}function Y90(){return new wFA}zA();p2();h0();QB();h0();var BFA=W.literal("application/pdf"),er2=W.enum(["pending","draft","failed"]),XFA=W.object({title:W.string().optional(),mimeType:BFA,filename:W.string().min(1),pageCount:W.number().int().min(0).optional(),status:er2.optional(),processingJobId:W.string().optional(),processingError:W.string().optional(),sourceEntityType:W.string().min(1).optional(),sourceEntityId:W.string().min(1).optional(),sourceUploadId:W.string().optional(),sourceFilename:W.string().optional(),sourceMediaType:W.string().optional(),attachmentType:W.string().min(1).optional(),dedupKey:W.string().min(1).optional()}),yr=U6.extend({entityType:W.literal("document"),content:W.string().regex(/^data:application\/pdf;base64,.+$/),metadata:XFA});function Z90(A){let Q=A.match(/^data:(application\/pdf);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid PDF document data URL");return{mimeType:"application/pdf",base64:Q[2]}}function Ik0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function YFA(A){let Q=Buffer.from(A).toString("latin1"),$=0,w=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let X of Q.matchAll(w)){let Y=parseInt(X[1]??X[2]??"0",10);if(Y>$)$=Y}if($>0)return $;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class Nk0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=yr;toMarkdown(A){return A.content}fromMarkdown(A){return Z90(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...$}=A,{mimeType:w}=Z90(Q);return{entityType:"document",content:Q,metadata:{mimeType:w,...$}}}}var jb=new Nk0;async function dFA(A,Q={}){let $=Q.maxBytes??5000000;if(A.byteLength>$)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${$} bytes)`);let B=(await Promise.resolve().then(() => (Wa2(),Za2))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),X=await B.promise;try{let Y=Q.maxPages??50;if(X.numPages>Y)throw Error(`Uploaded PDF has ${X.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let Z=[];for(let K=1;K<=X.numPages;K+=1){let D=(await(await X.getPage(K)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)Z.push(D)}let H=Z.join(`
7624
+ `,lr2=()=>J4("style",{children:Hn$},void 0,!1,void 0,this);import{jsxDEV as GQ,Fragment as Kn$}from"preact/jsx-dev-runtime";var Lk0=({title:A,description:Q,children:$,detail:w=!1,footer:B=!1,contentClassName:X=""})=>GQ(Kn$,{children:[GQ(E6,{title:A,description:Q},void 0,!1,void 0,this),GQ(lr2,{},void 0,!1,void 0,this),GQ("div",{className:`docs-handbook${w?" docs-handbook--detail":""}`,children:[GQ(cr2,{},void 0,!1,void 0,this),GQ("div",{className:`${tL.wrap} ${X}`.trim(),children:[$,B&&GQ(pr2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ir2=({docsCount:A,sectionsCount:Q,startDoc:$})=>GQ("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[GQ("p",{className:`${tL.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),GQ("h1",{className:`${tL.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",GQ("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GQ("p",{className:"mt-8 max-w-[52ch] text-lg leading-[1.65] text-[var(--docs-text-muted)]",children:"Documentation for composing brain models, managing markdown entities, wiring interfaces, and shipping generated sites."},void 0,!1,void 0,this),GQ("dl",{className:"mt-10 flex flex-wrap gap-7 docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] md:mt-14 md:gap-12",children:[GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:A},void 0,!1,void 0,this),"Documents"]},void 0,!0,void 0,this),GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:Q},void 0,!1,void 0,this),"Sections"]},void 0,!0,void 0,this),GQ("div",{children:[GQ("strong",{className:"mb-0.5 block font-medium text-[var(--docs-text)]",children:"April 2026"},void 0,!1,void 0,this),"Updated"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),GQ("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[$&&GQ("a",{className:tL.primaryButton,href:hr($),children:"Start reading"},void 0,!1,void 0,this),GQ("a",{className:tL.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),dr2=({groups:A})=>GQ("aside",{className:"docs-rail sticky top-8 hidden docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)] min-[861px]:block","aria-label":"Documentation sections",children:[GQ("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.map((Q,$)=>GQ("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[GQ("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Er($),"."]},void 0,!0,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Fk0($)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),nr2=({group:A,index:Q})=>GQ("article",{className:"mb-16 last:mb-0",id:Fk0(Q),children:[GQ("header",{className:"mb-2 grid grid-cols-[36px_auto_1fr] items-baseline gap-x-3 border-b border-[var(--docs-border)] pb-3.5 md:grid-cols-[48px_auto_1fr] md:gap-x-5",children:[GQ("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Er(Q),"."]},void 0,!0,void 0,this),GQ("h2",{className:`${tL.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),GQ("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.docs.map(($)=>GQ("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:GQ("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:hr($),children:[GQ("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:$.metadata.title},void 0,!1,void 0,this),$.metadata.description&&GQ("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:$.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},$.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),rr2=({title:A})=>GQ("nav",{className:"mb-8 flex flex-wrap items-baseline gap-2.5 docs-font-label text-[11px] uppercase tracking-[0.06em] text-[var(--docs-text-light)]","aria-label":"Breadcrumb",children:[GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),GQ("span",{children:"/"},void 0,!1,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),GQ("span",{children:"/"},void 0,!1,void 0,this),GQ("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),or2=({groups:A,activeGroupIndex:Q,activeSlug:$})=>GQ("aside",{className:"docs-detail-rail sticky top-24 hidden max-h-[calc(100vh-120px)] overflow-auto pr-2 min-[861px]:block","aria-label":"Documentation navigation",children:GQ("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[GQ("p",{className:"m-0 mb-4 border-b border-[var(--docs-text)] pb-3 text-[11px] uppercase tracking-[0.08em] text-[var(--docs-text-light)]",children:"Documentation"},void 0,!1,void 0,this),GQ("ol",{className:"m-0 list-none p-0",children:A.map((w,B)=>{let X=B===Q;return GQ("li",{className:X?"mb-[22px]":"mb-3.5",children:[GQ("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${X?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${Fk0(B)}`,children:[GQ("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Er(B),"."]},void 0,!0,void 0,this)," ",w.section]},void 0,!0,void 0,this),X&&GQ("ol",{className:"mt-0.5 list-none p-0",children:w.docs.map((Y)=>{let Z=Y.metadata.slug===$;return GQ("li",{children:GQ("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${Z?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:hr(Y),"aria-current":Z?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},w.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),sr2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return GQ("nav",{className:"mt-12 grid grid-cols-1 gap-5 border-t border-[var(--docs-border)] pt-7 md:grid-cols-2","aria-label":"Previous and next docs",children:[A?GQ("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:hr(A),children:[GQ("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Previous"},void 0,!1,void 0,this),GQ("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:["\u2190 ",A.metadata.title]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):GQ("span",{},void 0,!1,void 0,this),Q&&GQ("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] text-left transition-colors duration-150 hover:border-[var(--docs-accent)] md:text-right",href:hr(Q),children:[GQ("span",{className:"block docs-font-label text-[10.5px] uppercase tracking-[0.22em] text-[var(--docs-text-light)]",children:"Next"},void 0,!1,void 0,this),GQ("span",{className:"mt-2 block docs-font-display text-[22px] leading-[1.2] text-[var(--docs-heading)] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:[Q.metadata.title," \u2192"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as Tr}from"preact/jsx-dev-runtime";var QFA=({docs:A})=>{let Q=B90(A),$=Jk0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return Tr(Lk0,{title:"Documentation",description:"Brains documentation",children:[Tr(ir2,{docsCount:A.length,sectionsCount:$.length,startDoc:B},void 0,!1,void 0,this),Tr("section",{className:"grid items-start gap-10 py-12 md:grid-cols-[200px_minmax(0,1fr)] md:gap-20 md:py-20 md:pb-[120px]",id:"sections",children:[Tr(dr2,{groups:$},void 0,!1,void 0,this),Tr("div",{children:$.map((X,Y)=>Tr(nr2,{group:X,index:Y},X.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as BD}from"preact/jsx-dev-runtime";var $FA=({doc:A,docs:Q,prevDoc:$,nextDoc:w})=>{let B=Jk0(Q.length>0?Q:[A]),X=B90(Q.length>0?Q:[A]),Y=X.findIndex((H)=>H.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((H)=>H.docs.some((K)=>K.metadata.slug===A.metadata.slug)),0);return BD(Lk0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[BD(rr2,{title:A.metadata.title},void 0,!1,void 0,this),BD("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[BD(or2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),BD("article",{className:"min-w-0",children:[BD("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[BD("p",{className:`${tL.label} m-0 mb-6 flex items-baseline gap-3`,children:[BD("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Er(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),BD("h1",{className:`${tL.display} m-0 max-w-[18ch] text-4xl leading-[1.05] tracking-[-0.02em] md:text-6xl`,children:A.metadata.title},void 0,!1,void 0,this),A.metadata.description&&BD("p",{className:"mt-6 max-w-[56ch] docs-font-display text-[22px] font-[350] leading-[1.5] text-[var(--docs-text-muted)]",children:A.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),BD("div",{className:"docs-article__body",children:BD(XX,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),BD(sr2,{prevDoc:$,nextDoc:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var Un$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Gn$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Dn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),sourcePath:W.string(),description:W.string().optional(),slug:W.string().optional()}),qn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),description:W.string().optional(),slug:W.string()}),X90=W.object({id:W.string(),entityType:W.literal("doc"),content:W.string(),created:W.string(),updated:W.string(),visibility:Gn$,metadata:qn$,contentHash:W.string(),frontmatter:Dn$,body:W.string()}),zn$=W.object({docs:W.array(X90),pagination:Un$.nullable(),baseUrl:W.string().optional()}),Vn$=W.object({doc:X90,docs:W.array(X90),prevDoc:X90.nullable(),nextDoc:X90.nullable()});function ar2(){return{"doc-list":G2({name:"doc-list",description:"Documentation index template",schema:zn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:QFA}}),"doc-detail":G2({name:"doc-detail",description:"Documentation page template",schema:Vn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:$FA}})}}var tr2={name:"@brains/doc",version:"0.2.0-alpha.196",description:"Documentation entity type \u2014 markdown docs as first-class brain content",dependencies:{"@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class wFA extends c6{entityType=zk0.entityType;schema=Cr;adapter=zk0;constructor(){super("docs",tr2,{},bY)}getTemplates(){return ar2()}getDataSources(){return[new Vk0(this.logger.child("DocDataSource"))]}}function Y90(){return new wFA}zA();p2();h0();QB();h0();var BFA=W.literal("application/pdf"),er2=W.enum(["pending","draft","failed"]),XFA=W.object({title:W.string().optional(),mimeType:BFA,filename:W.string().min(1),pageCount:W.number().int().min(0).optional(),status:er2.optional(),processingJobId:W.string().optional(),processingError:W.string().optional(),sourceEntityType:W.string().min(1).optional(),sourceEntityId:W.string().min(1).optional(),sourceUploadId:W.string().optional(),sourceFilename:W.string().optional(),sourceMediaType:W.string().optional(),attachmentType:W.string().min(1).optional(),dedupKey:W.string().min(1).optional()}),yr=U6.extend({entityType:W.literal("document"),content:W.string().regex(/^data:application\/pdf;base64,.+$/),metadata:XFA});function Z90(A){let Q=A.match(/^data:(application\/pdf);base64,(.+)$/i);if(!Q?.[1]||!Q[2])throw Error("Invalid PDF document data URL");return{mimeType:"application/pdf",base64:Q[2]}}function Ik0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function YFA(A){let Q=Buffer.from(A).toString("latin1"),$=0,w=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let X of Q.matchAll(w)){let Y=parseInt(X[1]??X[2]??"0",10);if(Y>$)$=Y}if($>0)return $;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class Nk0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=yr;toMarkdown(A){return A.content}fromMarkdown(A){return Z90(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...$}=A,{mimeType:w}=Z90(Q);return{entityType:"document",content:Q,metadata:{mimeType:w,...$}}}}var jb=new Nk0;async function dFA(A,Q={}){let $=Q.maxBytes??5000000;if(A.byteLength>$)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${$} bytes)`);let B=(await Promise.resolve().then(() => (Wa2(),Za2))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),X=await B.promise;try{let Y=Q.maxPages??50;if(X.numPages>Y)throw Error(`Uploaded PDF has ${X.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let Z=[];for(let K=1;K<=X.numPages;K+=1){let D=(await(await X.getPage(K)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)Z.push(D)}let H=Z.join(`
7625
7625
 
7626
- `).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await B.destroy()}}zA();u4();p2();h0();import{createHash as wr$}from"crypto";var Br$=26214400,Xr$=20,Yr$=60000,Ha2=80,Zr$=10,Wr$={renderUrl:W.url().optional(),sourceEntityType:W.string().min(1),sourceEntityId:W.string().min(1),attachmentType:W.string().min(1),documentId:W.string().min(1).optional(),title:W.string().min(1).optional(),filename:W.string().min(1).optional(),dedupKey:W.string().min(1).optional(),replace:W.boolean().optional(),pageCount:W.number().int().min(0).optional(),maxPageCount:W.number().int().positive().optional(),maxBytes:W.number().int().positive().optional(),timeoutMs:W.number().int().positive().optional(),width:W.union([W.string(),W.number()]).optional(),height:W.union([W.string(),W.number()]).optional(),format:W.string().optional(),targetEntityType:W.string().min(1).optional(),targetEntityId:W.string().min(1).optional()},Ua2=W.object(Wr$),ZO0=Ua2.refine((A)=>A.targetEntityType===void 0&&A.targetEntityId===void 0||A.targetEntityType!==void 0&&A.targetEntityId!==void 0,{message:"targetEntityType and targetEntityId must be provided together",path:["targetEntityId"]});class WO0 extends H8{context;renderPdf;constructor(A,Q,$={}){super(A,{schema:ZO0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=$.renderPdf??lV}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,$=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return $?`${Q}:${$.contentHash}`:Q}async process(A,Q,$){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let w=A.maxPageCount??Xr$,B=A.maxBytes??Br$,X=A.timeoutMs??Yr$;if(A.pageCount!==void 0&&A.pageCount>w)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${w}`);let Y=await this.getDedupKey(A),Z=nFA(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let K=await this.findDocumentByDedupKey(Y,H?Z:void 0);if(K&&(!H||K.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,K.id,A);return await this.reportProgress($,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:K.id,reused:!0}}}await this.reportProgress($,{progress:20,message:"Rendering PDF document"});try{let K=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),U=K.data;if(U.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${U.byteLength} bytes`);let G=YFA(U);if(G>w)throw Error(`Rendered PDF has ${G} pages, exceeding maxPageCount=${w}`);let D=G>0?G:A.pageCount;await this.reportProgress($,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?K.filename:`${Z}.pdf`),J=jb.createDocumentEntity({dataUrl:Ik0(U),filename:q,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await BH({entityService:this.context.entityService,entity:{...J,id:Z}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Z,A);return await this.reportProgress($,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Z,reused:!1}}catch(K){let U=eA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await NF({entityService:this.context.entityService,entityType:"document",id:Z,error:U}),K}}async resolveDocumentAttachment(A,Q,$){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:$.timeoutMs,maxBytes:$.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let w=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!w)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(w.type!=="document")throw Error(`Attachment provider returned ${w.type}; expected document`);return w}async findDocumentByDedupKey(A,Q){let $=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if($.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:$.length,ids:$.map((B)=>B.id),preferredDocumentId:Q});let w=$.filter((B)=>B.metadata.status!=="pending"&&B.metadata.status!=="failed");return w.find((B)=>B.id===Q)??w[0]}async attachDocumentToTarget(A,Q,$,w){let B=await this.context.entityService.getEntity({entityType:A,id:Q});if(!B)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:X}=t8(B.content),Y=Array.isArray(X.documents)?X.documents.filter(Kr$):[],Z=w.replace?await this.removeReferencesForSameSourceAttachment(Y,$,w):Y,H=Z.some((K)=>K.id===$)?Z:[...Z,{id:$}];await this.context.entityService.updateEntity({entity:{...B,content:hX(B.content,"documents",H)}})}async removeReferencesForSameSourceAttachment(A,Q,$){let w=[];for(let B of A){if(B.id===Q){w.push(B);continue}let X=await this.context.entityService.getEntity({entityType:"document",id:B.id});if(!X||!Ur$(X,$))w.push(B)}return w}}function nFA(A,Q){let $=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,w=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??$,B=A.replace===!0&&A.documentId===void 0?`${w}-${Date.now()}`:w;return Hr$(B)}function Hr$(A){let Q=O1(A.replace(/[/:]+/g," "))||`document-${Ka2(A)}`;if(Q.length<=Ha2)return Q;let $=`-${Ka2(A)}`;return`${Q.slice(0,Ha2-$.length).replace(/-+$/g,"")}${$}`}function Ka2(A){return wr$("sha256").update(A).digest("hex").slice(0,Zr$)}function Kr$(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function Ur$(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ga2={name:"@brains/document-plugin",version:"0.2.0-alpha.195",description:"Document entity type for generated PDFs and publishable document attachments",dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Dr$=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
7626
+ `).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await B.destroy()}}zA();u4();p2();h0();import{createHash as wr$}from"crypto";var Br$=26214400,Xr$=20,Yr$=60000,Ha2=80,Zr$=10,Wr$={renderUrl:W.url().optional(),sourceEntityType:W.string().min(1),sourceEntityId:W.string().min(1),attachmentType:W.string().min(1),documentId:W.string().min(1).optional(),title:W.string().min(1).optional(),filename:W.string().min(1).optional(),dedupKey:W.string().min(1).optional(),replace:W.boolean().optional(),pageCount:W.number().int().min(0).optional(),maxPageCount:W.number().int().positive().optional(),maxBytes:W.number().int().positive().optional(),timeoutMs:W.number().int().positive().optional(),width:W.union([W.string(),W.number()]).optional(),height:W.union([W.string(),W.number()]).optional(),format:W.string().optional(),targetEntityType:W.string().min(1).optional(),targetEntityId:W.string().min(1).optional()},Ua2=W.object(Wr$),ZO0=Ua2.refine((A)=>A.targetEntityType===void 0&&A.targetEntityId===void 0||A.targetEntityType!==void 0&&A.targetEntityId!==void 0,{message:"targetEntityType and targetEntityId must be provided together",path:["targetEntityId"]});class WO0 extends H8{context;renderPdf;constructor(A,Q,$={}){super(A,{schema:ZO0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=$.renderPdf??lV}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,$=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return $?`${Q}:${$.contentHash}`:Q}async process(A,Q,$){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let w=A.maxPageCount??Xr$,B=A.maxBytes??Br$,X=A.timeoutMs??Yr$;if(A.pageCount!==void 0&&A.pageCount>w)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${w}`);let Y=await this.getDedupKey(A),Z=nFA(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let K=await this.findDocumentByDedupKey(Y,H?Z:void 0);if(K&&(!H||K.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,K.id,A);return await this.reportProgress($,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:K.id,reused:!0}}}await this.reportProgress($,{progress:20,message:"Rendering PDF document"});try{let K=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),U=K.data;if(U.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${U.byteLength} bytes`);let G=YFA(U);if(G>w)throw Error(`Rendered PDF has ${G} pages, exceeding maxPageCount=${w}`);let D=G>0?G:A.pageCount;await this.reportProgress($,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?K.filename:`${Z}.pdf`),J=jb.createDocumentEntity({dataUrl:Ik0(U),filename:q,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await BH({entityService:this.context.entityService,entity:{...J,id:Z}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Z,A);return await this.reportProgress($,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Z,reused:!1}}catch(K){let U=eA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await NF({entityService:this.context.entityService,entityType:"document",id:Z,error:U}),K}}async resolveDocumentAttachment(A,Q,$){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:$.timeoutMs,maxBytes:$.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let w=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!w)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(w.type!=="document")throw Error(`Attachment provider returned ${w.type}; expected document`);return w}async findDocumentByDedupKey(A,Q){let $=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if($.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:$.length,ids:$.map((B)=>B.id),preferredDocumentId:Q});let w=$.filter((B)=>B.metadata.status!=="pending"&&B.metadata.status!=="failed");return w.find((B)=>B.id===Q)??w[0]}async attachDocumentToTarget(A,Q,$,w){let B=await this.context.entityService.getEntity({entityType:A,id:Q});if(!B)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:X}=t8(B.content),Y=Array.isArray(X.documents)?X.documents.filter(Kr$):[],Z=w.replace?await this.removeReferencesForSameSourceAttachment(Y,$,w):Y,H=Z.some((K)=>K.id===$)?Z:[...Z,{id:$}];await this.context.entityService.updateEntity({entity:{...B,content:hX(B.content,"documents",H)}})}async removeReferencesForSameSourceAttachment(A,Q,$){let w=[];for(let B of A){if(B.id===Q){w.push(B);continue}let X=await this.context.entityService.getEntity({entityType:"document",id:B.id});if(!X||!Ur$(X,$))w.push(B)}return w}}function nFA(A,Q){let $=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,w=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??$,B=A.replace===!0&&A.documentId===void 0?`${w}-${Date.now()}`:w;return Hr$(B)}function Hr$(A){let Q=O1(A.replace(/[/:]+/g," "))||`document-${Ka2(A)}`;if(Q.length<=Ha2)return Q;let $=`-${Ka2(A)}`;return`${Q.slice(0,Ha2-$.length).replace(/-+$/g,"")}${$}`}function Ka2(A){return wr$("sha256").update(A).digest("hex").slice(0,Zr$)}function Kr$(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function Ur$(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ga2={name:"@brains/document-plugin",version:"0.2.0-alpha.196",description:"Document entity type for generated PDFs and publishable document attachments",dependencies:{"@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Dr$=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
7627
7627
  % Pending document placeholder
7628
7628
  %%EOF
7629
7629
  `).toString("base64")}`,qr$=W.object({}).catchall(W.unknown()).transform(()=>({})),rFA={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function zr$(A,Q){let $=A.title?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}function Vr$(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function Jr$(A){let Q=encodeURIComponent(A.entityId);return{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${Q}`,downloadUrl:`/api/chat/attachments/document?id=${Q}&download=1`,filename:A.filename,source:{entityType:"document",entityId:A.entityId,attachmentType:"uploaded"}}}class oFA extends d6{entityType=jb.entityType;schema=yr;adapter=jb;pluginContext;constructor(){super("document",Ga2,{},qr$)}async onRegister(A){this.pluginContext=A,A.entities.register(this.entityType,this.schema,this.adapter,{embeddable:!1}),A.entities.registerCreateInterceptor(this.entityType,(Q)=>this.interceptCreate(Q)),A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["application/pdf"],handler:async(Q)=>{let $=await this.promoteUpload({entityType:this.entityType,...Q.title!==void 0?{title:Q.title}:{},from:Q.upload},A);return $.kind==="handled"?$.result:{success:!1,error:"Document upload save was not handled"}}}),A.jobs.registerHandler("generate",new WO0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===rFA.refKind){if(!Q)return{kind:"handled",result:{success:!1,error:"Plugin context not initialized"}};return this.promoteUpload(A,Q)}if(A.from?.kind!=="entity-attachment")return{kind:"continue",input:A};if(!Q)return{kind:"handled",result:{success:!1,error:"Plugin context not initialized"}};let $=ZO0.parse({sourceEntityType:A.from.sourceEntityType,sourceEntityId:A.from.sourceEntityId,attachmentType:A.from.attachmentType,...A.title&&{title:A.title},...A.replace===!0&&{replace:!0},...A.targetEntityType&&{targetEntityType:A.targetEntityType},...A.targetEntityId&&{targetEntityId:A.targetEntityId}}),w=await this.getDedupKey($,Q),B=$.replace===!0?void 0:await this.findExistingDocument(w,Q),X=B?.id??nFA($,w);if(!B)await this.createPendingDocument(Q,{id:X,title:$.title??X,filename:`${X}.pdf`,sourceEntityType:$.sourceEntityType,sourceEntityId:$.sourceEntityId,attachmentType:$.attachmentType,dedupKey:w});let Y=await Q.jobs.enqueue({type:"generate",data:{...$,dedupKey:w,documentId:X}}),Z=`${X}.pdf`;return{kind:"handled",result:{success:!0,data:{entityId:X,jobId:Y,status:"generating",attachment:{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${encodeURIComponent(X)}`,downloadUrl:`/api/chat/attachments/document?id=${encodeURIComponent(X)}&download=1`,filename:Z,source:{entityType:"document",entityId:X,attachmentType:$.attachmentType}}}}}}async promoteUpload(A,Q){let $=A.from;if($?.kind!==rFA.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w;try{w=await Q.uploads.scoped(rFA).read($.id)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(w.record.mediaType!=="application/pdf")return{kind:"handled",result:{success:!1,error:"Only PDF uploads can be promoted to document entities"}};let B=zr$(A,w.record.filename),X=O1(B);if(!X)return{kind:"handled",result:{success:!1,error:"Could not derive a document id from the uploaded filename. Provide a title."}};let Y=new Date().toISOString(),Z=jb.createDocumentEntity({dataUrl:Vr$(w.record.mediaType,w.content),filename:w.record.filename,title:B,status:"draft",sourceUploadId:$.id,sourceFilename:w.record.filename,sourceMediaType:w.record.mediaType,attachmentType:"uploaded",dedupKey:`upload:${$.kind}:${$.id}`}),H=await Q.entityService.createEntity({entity:{id:X,...Z,created:Y,updated:Y},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"created",attachment:Jr$({entityId:H.entityId,filename:w.record.filename})}}}}async createPendingDocument(A,Q){let $=new Date().toISOString(),w=jb.createDocumentEntity({dataUrl:Dr$,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await fC({entityService:A.entityService,entity:{id:Q.id,...w,created:$,updated:$}})}async getDedupKey(A,Q){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let $=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,w=await Q.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return w?`${$}:${w.contentHash}`:$}async findExistingDocument(A,Q){return(await Q.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}}))[0]}async getInstructions(){return"Document entities store durable file artifacts such as PDFs. Uploaded PDFs are raw document files, not decks. Source-derived document artifacts are durable documents backed by registered attachment providers such as carousel or printable. Generate saved PDF artifacts through system_generate with source.kind attachment; preserve raw uploaded PDFs with system_create source.kind upload and transform preserve."}async getTools(){return[]}}function sFA(){return new oFA}zA();h0();zA();h0();var Da2=W.enum(["generating","failed"]),Fr$=W.enum(["generating","failed"]),Yx=W.object({title:W.string().optional(),status:Da2.optional(),error:W.string().optional()}),Lr$=W.object({title:W.string(),status:Da2.optional(),error:W.string().optional()}),Ir$=W.object({title:W.string(),status:Fr$.optional(),error:W.string().optional()}),Zx=U6.extend({entityType:W.literal("note"),metadata:Ir$}),Nr$=Zx.extend({frontmatter:Yx,body:W.string()});zA();h0();var _r$=W.record(W.string(),W.unknown());class aFA extends zQ{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:Zx,frontmatterSchema:Yx})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Yx);if(Object.values($).some((w)=>w!==void 0))return this.buildMarkdown(Q,$)}catch{}return Q}fromMarkdown(A){let Q=this.parseMarkdownFrontmatter(A),$=Q.title??this.extractH1(A)??"Untitled";return{content:A,entityType:"note",metadata:{title:$,...Q.status&&{status:Q.status},...Q.error&&{error:Q.error}}}}parseNoteFrontmatter(A){return this.parseMarkdownFrontmatter(A.content)}parseMarkdownFrontmatter(A){try{return this.parseFrontMatter(A,Yx)}catch{return{}}}buildStub(A){let Q={title:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:{title:A.title,status:"generating"}}}createNoteContent(A,Q){try{let $=this.parseFrontMatter(Q,_r$);if(Object.keys($).length===0)return Q;let w={...$,title:$.title??A},B=this.extractBody(Q);return this.buildMarkdown(B,w)}catch{return Q}}extractH1(A){return A.match(/^#\s+(.+)$/m)?.[1]?.trim()??null}}var fb=new aFA;h0();var tFA=W.object({defaultPrompt:W.string().default("Create a note summarizing key concepts from my knowledge base")});h0();zA();var qa2=W.object({title:W.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:W.string().describe("Note content in markdown format with clear organization and structure")}),eFA=G2({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:qa2,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
@@ -7641,7 +7641,7 @@ title: ${JSON.stringify(A)}
7641
7641
  ---
7642
7642
 
7643
7643
  ${Q.trim()}
7644
- `}var kr$={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Or$=W.object({uploadId:W.string().min(1),entityId:W.string().min(1),stubContentHash:W.string().min(1).optional(),title:W.string().optional()});class QLA extends H8{context;constructor(A,Q){super(A,{schema:Or$,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,$){try{await this.reportProgress($,{progress:10,message:"Reading uploaded file"});let w=await this.context.uploads.scoped(kr$).read(A.uploadId);await this.reportProgress($,{progress:35,message:"Extracting markdown from upload"});let B=await Fa2({upload:w,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress($,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=fb.fromMarkdown(B.content),Z=await BH({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:B.content,metadata:{title:B.title,...Y.metadata},created:X,updated:X},...A.stubContentHash!==void 0?{expectedContentHash:A.stubContentHash}:{}});if(Z.mutation.skipReason==="content-conflict")return await this.reportProgress($,{progress:100,message:"Upload import superseded by newer note content"}),{entityId:Z.entityId,status:"superseded"};return await this.reportProgress($,{progress:100,message:"Upload imported as markdown note"}),{entityId:Z.entityId,status:"created"}}catch(w){return await this.markStubFailed(A.entityId,eA(w),A.stubContentHash),o5.failure(w)}}async markStubFailed(A,Q,$){try{let w=await this.context.entityService.getEntity({entityType:"note",id:A});if(!w)return;await this.context.entityService.updateEntity({entity:{...w,content:hX(hX(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}},...$!==void 0?{options:{expectedContentHash:$}}:{}})}catch(w){this.logger.warn("Failed to mark import stub as failed",{error:w,entityId:A})}}summarizeDataForLog(A){return{uploadId:A.uploadId,entityId:A.entityId,hasTitle:A.title!==void 0,hasStubContentHash:A.stubContentHash!==void 0}}}zA();async function La2({entity:A,config:Q}){let $=Zx.parse(A),w=MQ($.content,Yx);return{$type:"ai.rizom.brain.note",title:$.metadata.title,body:w.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function $LA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:i8["ai.rizom.brain.note"],validate:!1,buildRecord:La2}}var Ia2={name:"@brains/note",version:"0.2.0-alpha.195",description:"Personal knowledge capture with markdown-first workflow",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Na2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},xr$=W.object({prompt:W.string()});class wLA extends c6{entityType=fb.entityType;schema=Zx;adapter=fb;unregisterAtprotoProjection;constructor(A={}){super("note",Ia2,A,tFA)}async interceptCreate(A,Q,$){if(A.from?.kind!==Na2.refKind)return{kind:"continue",input:A};if(A.transform!=="extract-markdown")return{kind:"handled",result:{success:!1,error:'Importing an upload as a note requires transform: "extract-markdown"'}};let w=A.from.id,B;try{B=await $.uploads.scoped(Na2).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ja2(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=ALA({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=fb.buildStub({id:X.id,title:X.title}),Z=new Date().toISOString(),H=await $.entityService.createEntity({entity:{id:X.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:Z,updated:Z},options:{deduplicateId:!0}}),K=await $.entityService.getEntity({entityType:"note",id:H.entityId});if(!K)throw Error("Created note import stub could not be read");let U=await $.jobs.enqueue({type:"upload-import",data:{uploadId:w,entityId:H.entityId,stubContentHash:K.contentHash,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"generating",jobId:U}}}}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new HO0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:eFA}}async onRegister(A){A.jobs.registerHandler("upload-import",new QLA(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let $=xr$.parse(Q);return A.ai.generate({prompt:$.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=D9.getInstance().register($LA())}async getInstructions(){return"Note entities are editable markdown notes. Use them for durable text captures, summaries, and imported markdown; raw files remain document or image entities instead of notes."}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function fy(A={}){return new wLA(A)}zA();h0();zA();var _a2=W.object({ref:W.string(),label:W.string()}),Pa2=W.enum(["pending","draft","published"]),Rr$=W.enum(["pending","draft","published"]),C90=W.object({status:Pa2,title:W.string(),url:W.string().url(),description:W.string().optional(),domain:W.string(),capturedAt:W.string().datetime(),source:_a2}),vr$=C90.pick({title:!0,status:!0}),Cr$=W.object({title:W.string(),status:Rr$}),xy=U6.extend({entityType:W.literal("link"),metadata:Cr$});p2();h0();h0();var BLA=W.object({enableSummarization:W.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:W.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});zA();class Wx extends zQ{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:xy,frontmatterSchema:C90})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,domain:A.domain,capturedAt:A.capturedAt,source:A.source},$=A.summary??"";return this.buildMarkdown($,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,C90),summary:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseLinkContent(A);return{content:A,entityType:"link",metadata:{title:Q.title,status:Q.status}}}}var ar=new Wx;zA();h0();var hr$=W.object({success:W.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:W.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:W.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:W.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:W.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),ba2=G2({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:hr$,basePrompt:`You are an expert at extracting key information from webpage content.
7644
+ `}var kr$={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Or$=W.object({uploadId:W.string().min(1),entityId:W.string().min(1),stubContentHash:W.string().min(1).optional(),title:W.string().optional()});class QLA extends H8{context;constructor(A,Q){super(A,{schema:Or$,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,$){try{await this.reportProgress($,{progress:10,message:"Reading uploaded file"});let w=await this.context.uploads.scoped(kr$).read(A.uploadId);await this.reportProgress($,{progress:35,message:"Extracting markdown from upload"});let B=await Fa2({upload:w,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress($,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=fb.fromMarkdown(B.content),Z=await BH({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:B.content,metadata:{title:B.title,...Y.metadata},created:X,updated:X},...A.stubContentHash!==void 0?{expectedContentHash:A.stubContentHash}:{}});if(Z.mutation.skipReason==="content-conflict")return await this.reportProgress($,{progress:100,message:"Upload import superseded by newer note content"}),{entityId:Z.entityId,status:"superseded"};return await this.reportProgress($,{progress:100,message:"Upload imported as markdown note"}),{entityId:Z.entityId,status:"created"}}catch(w){return await this.markStubFailed(A.entityId,eA(w),A.stubContentHash),o5.failure(w)}}async markStubFailed(A,Q,$){try{let w=await this.context.entityService.getEntity({entityType:"note",id:A});if(!w)return;await this.context.entityService.updateEntity({entity:{...w,content:hX(hX(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}},...$!==void 0?{options:{expectedContentHash:$}}:{}})}catch(w){this.logger.warn("Failed to mark import stub as failed",{error:w,entityId:A})}}summarizeDataForLog(A){return{uploadId:A.uploadId,entityId:A.entityId,hasTitle:A.title!==void 0,hasStubContentHash:A.stubContentHash!==void 0}}}zA();async function La2({entity:A,config:Q}){let $=Zx.parse(A),w=MQ($.content,Yx);return{$type:"ai.rizom.brain.note",title:$.metadata.title,body:w.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function $LA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:i8["ai.rizom.brain.note"],validate:!1,buildRecord:La2}}var Ia2={name:"@brains/note",version:"0.2.0-alpha.196",description:"Personal knowledge capture with markdown-first workflow",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/document":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Na2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},xr$=W.object({prompt:W.string()});class wLA extends c6{entityType=fb.entityType;schema=Zx;adapter=fb;unregisterAtprotoProjection;constructor(A={}){super("note",Ia2,A,tFA)}async interceptCreate(A,Q,$){if(A.from?.kind!==Na2.refKind)return{kind:"continue",input:A};if(A.transform!=="extract-markdown")return{kind:"handled",result:{success:!1,error:'Importing an upload as a note requires transform: "extract-markdown"'}};let w=A.from.id,B;try{B=await $.uploads.scoped(Na2).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ja2(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=ALA({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=fb.buildStub({id:X.id,title:X.title}),Z=new Date().toISOString(),H=await $.entityService.createEntity({entity:{id:X.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:Z,updated:Z},options:{deduplicateId:!0}}),K=await $.entityService.getEntity({entityType:"note",id:H.entityId});if(!K)throw Error("Created note import stub could not be read");let U=await $.jobs.enqueue({type:"upload-import",data:{uploadId:w,entityId:H.entityId,stubContentHash:K.contentHash,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"generating",jobId:U}}}}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new HO0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:eFA}}async onRegister(A){A.jobs.registerHandler("upload-import",new QLA(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let $=xr$.parse(Q);return A.ai.generate({prompt:$.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=D9.getInstance().register($LA())}async getInstructions(){return"Note entities are editable markdown notes. Use them for durable text captures, summaries, and imported markdown; raw files remain document or image entities instead of notes."}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function fy(A={}){return new wLA(A)}zA();h0();zA();var _a2=W.object({ref:W.string(),label:W.string()}),Pa2=W.enum(["pending","draft","published"]),Rr$=W.enum(["pending","draft","published"]),C90=W.object({status:Pa2,title:W.string(),url:W.string().url(),description:W.string().optional(),domain:W.string(),capturedAt:W.string().datetime(),source:_a2}),vr$=C90.pick({title:!0,status:!0}),Cr$=W.object({title:W.string(),status:Rr$}),xy=U6.extend({entityType:W.literal("link"),metadata:Cr$});p2();h0();h0();var BLA=W.object({enableSummarization:W.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:W.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});zA();class Wx extends zQ{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:xy,frontmatterSchema:C90})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,domain:A.domain,capturedAt:A.capturedAt,source:A.source},$=A.summary??"";return this.buildMarkdown($,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,C90),summary:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseLinkContent(A);return{content:A,entityType:"link",metadata:{title:Q.title,status:Q.status}}}}var ar=new Wx;zA();h0();var hr$=W.object({success:W.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:W.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:W.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:W.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:W.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),ba2=G2({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:hr$,basePrompt:`You are an expert at extracting key information from webpage content.
7645
7645
 
7646
7646
  You will receive webpage content in markdown format. Your job is to extract structured information from it.
7647
7647
 
@@ -7663,7 +7663,7 @@ Accuracy rules:
7663
7663
 
7664
7664
  `))return{success:!1,error:Y.trim(),errorType:"fetch_failed"};return{success:!0,content:Y}}catch($){return this.handleFetchError($,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 mr$}from"crypto";class Hx{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(Hx.URL_PATTERN)??[];return[...new Set(Q)]}static normalizeUrl(A){try{let Q=new URL(A),$=Q.pathname.replace(/\/$/,"")||"/";return`${Q.protocol}//${Q.host}${$}`}catch{return A}}static generateEntityId(A){let Q=this.normalizeUrl(A),$=mr$("sha256").update(Q).digest("hex");try{return`${new URL(Q).hostname.replace(/\./g,"-")}-${$.substring(0,6)}`}catch{return $.substring(0,12)}}static isValidUrl(A){try{let Q=new URL(A);return["http:","https:"].includes(Q.protocol)}catch{return!1}}}zA();h0();Uw();var ur$=W.object({interfaceId:W.string().optional(),userId:W.string().optional(),channelId:W.string().optional(),channelName:W.string().optional(),timestamp:W.string().optional()}),cr$=W.object({url:W.url(),metadata:ur$.optional()}),A$B=W.object({success:W.boolean(),entityId:W.string().optional(),title:W.string().optional(),url:W.string().optional(),status:W.enum(["pending","draft","published"]).optional(),error:W.string().optional()});class UO0 extends H8{context;linkAdapter;urlFetcher;constructor(A,Q,$){super(A,{schema:cr$,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new Wx,this.urlFetcher=new tr($?.jinaApiKey?{jinaApiKey:$.jinaApiKey}:void 0)}async process(A,Q,$){let{url:w,metadata:B}=A;try{await $.report({progress:g6.START,total:100,message:"Starting link capture"});let X=Hx.generateEntityId(w);await $.report({progress:g6.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity({entityType:"link",id:X});if(Y){let{frontmatter:q}=this.linkAdapter.parseLinkContent(Y.content),J=Y.metadata.status;if(J!=="pending")return this.logger.info("Link already captured, returning existing",{url:w,entityId:X}),{success:!0,entityId:Y.id,title:q.title,url:w,status:J};this.logger.info("Pending link exists, completing extraction",{url:w,entityId:X})}let Z=this.resolveSource(B),H=new Date().toISOString();await $.report({progress:g6.FETCH,total:100,message:"Fetching webpage content"});let K=await this.urlFetcher.fetch(w);if(!K.success){if(K.errorType==="url_not_found"||K.errorType==="url_unreachable"){this.logger.warn("Link URL not accessible",{url:w,errorType:K.errorType,error:K.error});let q=new URL(w).hostname,J=`Could not capture link: ${K.error}`,F=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:J,summary:J,domain:q,capturedAt:H,source:Z});return await BH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:F,metadata:{status:"pending",title:q}}}),{success:!1,entityId:X,title:q,url:w,status:"pending",error:J}}}await $.report({progress:g6.PROCESS,total:100,message:"Extracting content with AI"});let U=await this.context.ai.generate({templateName:"link:extraction",prompt:K.success?`Extract structured information from this webpage content:
7665
7665
 
7666
- ${K.content}`:`The URL ${w} could not be fetched. Return success: false with error: "${K.error}"`,data:{url:w,hasContent:K.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:U}),await $.report({progress:g6.EXTRACT,total:100,message:"Processing extraction results"}),U.success===!1||!U.title||!U.description||!U.summary){let q=U.title||new URL(w).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:w}),await $.report({progress:g6.SAVE,total:100,message:"Saving link as pending"});let J=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),F=await BH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:J,metadata:{status:"pending",title:q}}});return await $.report({progress:g6.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:F.entityId,title:q,url:w,status:"pending"}}await $.report({progress:g6.SAVE,total:100,message:`Saving link: "${U.title}"`});let G=this.linkAdapter.createLinkContent({status:"draft",title:U.title,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),D=await BH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:G,metadata:{status:"draft",title:U.title}}});return await $.report({progress:g6.COMPLETE,total:100,message:`Link captured: "${U.title}"`}),{success:!0,entityId:D.entityId,title:U.title,url:w,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),o5.failure(X)}}resolveSource(A){let Q=A?.channelId,$=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:$??Q};let w=A?.interfaceId??"cli";return{ref:`${w}:local`,label:w.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function ka2({entity:A,config:Q}){let $=xy.parse(A),{frontmatter:w,summary:B}=ar.parseLinkContent($.content);return{$type:"ai.rizom.brain.link",title:w.title,url:w.url,...w.description&&{description:w.description},...B&&{summary:B},domain:w.domain,capturedAt:w.capturedAt,source:w.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function KLA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:i8["ai.rizom.brain.link"],validate:!1,buildRecord:ka2}}var Oa2={name:"@brains/link",version:"0.2.0-alpha.195",description:"Web content capture plugin with AI-powered extraction and structured storage",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var lr$=W.object({url:W.url()});class ULA extends c6{entityType=ar.entityType;schema=xy;adapter=ar;shell;unregisterAtprotoProjection;constructor(A={}){super("link",Oa2,A,BLA)}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 UO0(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,$){if(A.content)try{let X=this.adapter.fromMarkdown(A.content).metadata,Y=typeof X?.title==="string"?X.title:void 0,Z=typeof X?.status==="string"?X.status:void 0,H=this.extractFirstUrl(A.content);if(Y&&Z&&H){let K=O1(H)||O1(Y)||`${A.entityType}-${Date.now()}`,U=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await $.entityService.createEntity({entity:{id:K,entityType:A.entityType,content:A.content,metadata:{title:Y,status:Z},created:U,updated:U}})).entityId,status:"created"}}}}}catch{}let w=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(w){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let B=await this.createPendingLink(w,A.title,Q,$),X=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:w,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:B,status:"generating",jobId:X}}}}catch(B){return{kind:"handled",result:{success:!1,error:B instanceof Error?B.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 UO0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:ba2,"link-list":ja2,"link-detail":Ma2}}getDataSources(){return[new HLA(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=D9.getInstance().register(KLA()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:$}=lr$.parse(Q),B=await new tr(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch($);if(!B.success)return{success:!1,error:B.error,errorType:B.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
7666
+ ${K.content}`:`The URL ${w} could not be fetched. Return success: false with error: "${K.error}"`,data:{url:w,hasContent:K.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:U}),await $.report({progress:g6.EXTRACT,total:100,message:"Processing extraction results"}),U.success===!1||!U.title||!U.description||!U.summary){let q=U.title||new URL(w).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:w}),await $.report({progress:g6.SAVE,total:100,message:"Saving link as pending"});let J=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),F=await BH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:J,metadata:{status:"pending",title:q}}});return await $.report({progress:g6.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:F.entityId,title:q,url:w,status:"pending"}}await $.report({progress:g6.SAVE,total:100,message:`Saving link: "${U.title}"`});let G=this.linkAdapter.createLinkContent({status:"draft",title:U.title,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),D=await BH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:G,metadata:{status:"draft",title:U.title}}});return await $.report({progress:g6.COMPLETE,total:100,message:`Link captured: "${U.title}"`}),{success:!0,entityId:D.entityId,title:U.title,url:w,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),o5.failure(X)}}resolveSource(A){let Q=A?.channelId,$=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:$??Q};let w=A?.interfaceId??"cli";return{ref:`${w}:local`,label:w.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function ka2({entity:A,config:Q}){let $=xy.parse(A),{frontmatter:w,summary:B}=ar.parseLinkContent($.content);return{$type:"ai.rizom.brain.link",title:w.title,url:w.url,...w.description&&{description:w.description},...B&&{summary:B},domain:w.domain,capturedAt:w.capturedAt,source:w.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function KLA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:i8["ai.rizom.brain.link"],validate:!1,buildRecord:ka2}}var Oa2={name:"@brains/link",version:"0.2.0-alpha.196",description:"Web content capture plugin with AI-powered extraction and structured storage",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var lr$=W.object({url:W.url()});class ULA extends c6{entityType=ar.entityType;schema=xy;adapter=ar;shell;unregisterAtprotoProjection;constructor(A={}){super("link",Oa2,A,BLA)}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 UO0(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,$){if(A.content)try{let X=this.adapter.fromMarkdown(A.content).metadata,Y=typeof X?.title==="string"?X.title:void 0,Z=typeof X?.status==="string"?X.status:void 0,H=this.extractFirstUrl(A.content);if(Y&&Z&&H){let K=O1(H)||O1(Y)||`${A.entityType}-${Date.now()}`,U=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await $.entityService.createEntity({entity:{id:K,entityType:A.entityType,content:A.content,metadata:{title:Y,status:Z},created:U,updated:U}})).entityId,status:"created"}}}}}catch{}let w=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(w){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let B=await this.createPendingLink(w,A.title,Q,$),X=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:w,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:B,status:"generating",jobId:X}}}}catch(B){return{kind:"handled",result:{success:!1,error:B instanceof Error?B.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 UO0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:ba2,"link-list":ja2,"link-detail":Ma2}}getDataSources(){return[new HLA(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=D9.getInstance().register(KLA()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:$}=lr$.parse(Q),B=await new tr(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch($);if(!B.success)return{success:!1,error:B.error,errorType:B.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
7667
7667
 
7668
7668
  ${B.content}`,data:{url:$,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,$,w){let B=Hx.generateEntityId(A),X=new URL(A),Y=new Date().toISOString(),Z=Q?.trim()?Q.trim():X.hostname,H=this.adapter.createLinkContent({status:"pending",title:Z,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:X.hostname,capturedAt:Y,source:this.resolveSource($)});return(await fC({entityService:w.entityService,entity:{id:B,entityType:"link",content:H,metadata:{status:"pending",title:Z},created:Y,updated:Y}})).entityId}resolveSource(A){if(A.channelId)return{ref:`matrix:${A.channelId}`,label:A.channelName??A.channelId};return{ref:`${A.interfaceType}:local`,label:A.interfaceType.toUpperCase()}}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[$]=Hx.extractUrls(Q);if($)return $}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function fa2(A={}){return new ULA(A)}var Ry=fa2;h0();var ir$=W.object({conversationId:W.string().optional(),interfaceId:W.string().optional(),userId:W.string().optional(),messageId:W.string().optional(),timestamp:W.string().optional()}),O$B=W.object({id:W.string().optional(),metadata:ir$.optional()});zA();h0();D5();h0();zA();var xa2=W.enum(["generating","draft","published","failed"]),Ra2=W.enum(["generating","draft","published","failed"]),XY=W.object({title:W.string(),slug:W.string().optional(),status:xa2,publishedAt:W.string().datetime().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.string().url().optional()}),dr$=XY.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:W.string(),error:W.string().optional()}),nr$=W.object({title:W.string(),status:Ra2,publishedAt:W.string().datetime().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),rr$=W.object({title:W.string(),slug:W.string().optional(),status:Ra2,publishedAt:W.string().datetime().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.string().url().optional()}),Kx=U6.extend({entityType:W.literal("project"),metadata:nr$}),GO0=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),E90=Kx.extend({frontmatter:rr$,body:W.string(),structuredContent:GO0.optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional()}),or$=E90.extend({url:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),sr$=E90.extend({url:W.string(),typeLabel:W.string(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});zA();p2();e9();class GLA extends n${constructor(){super(GO0,{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 DLA=new GLA;class qLA extends zQ{constructor(){super({entityType:"project",purpose:"A portfolio project or case study.",schema:Kx,frontmatterSchema:XY,supportsCoverImage:!0,bodyFormatter:DLA})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,XY),w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,XY),$=Q.slug??O1(Q.title);return{content:A,entityType:"project",metadata:{title:Q.title,slug:$,status:Q.status,publishedAt:Q.publishedAt,year:Q.year}}}parseProjectFrontmatter(A){return this.parseFrontMatter(A.content,XY)}parseStructuredContent(A){return DLA.parse(this.extractBody(A.content))}createProjectContent(A,Q){let $=DLA.format(Q);return this.buildMarkdown($,A)}buildStub(A){let Q=new Date().getUTCFullYear(),$={title:A.title,slug:A.id,status:"generating",description:"",year:Q};return{content:this.buildMarkdown("",$),metadata:{title:A.title,slug:A.id,status:"generating",year:Q}}}}var vy=new qLA;h0();var zLA=W.looseObject({});import{jsxDEV as GD,Fragment as tr$}from"preact/jsx-dev-runtime";var ar$=({project:A})=>{let{frontmatter:Q,url:$,coverImageUrl:w}=A;return GD(v8,{href:$,children:[w&&GD("img",{src:w,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),GD(AY,{children:Q.title},void 0,!1,void 0,this),GD("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},VLA=({projects:A,pageTitle:Q,pagination:$,baseUrl:w="/projects"})=>{let B=Q??"Projects",X=$?.totalItems??A.length,Y=`Browse all ${X} ${X===1?"project":"projects"}`;return GD(tr$,{children:[GD(E6,{title:B,description:Y},void 0,!1,void 0,this),GD("div",{className:"project-list bg-theme",children:GD("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[GD("h1",{className:"text-4xl font-bold text-heading mb-12",children:B},void 0,!1,void 0,this),GD("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((Z)=>GD(ar$,{project:Z},Z.id,!1,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&GD("div",{className:"mt-12",children:GD(Ub,{currentPage:$.currentPage,totalPages:$.totalPages,baseUrl:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as Pw,Fragment as va2}from"preact/jsx-dev-runtime";var er$=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return Pw("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:Pw("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?Pw(v8,{href:A.url,variant:"compact",children:[Pw("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),Pw("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):Pw("div",{},void 0,!1,void 0,this),Q&&Pw(v8,{href:Q.url,variant:"compact",className:"md:text-right",children:[Pw("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),Pw("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)},DO0=({title:A,content:Q})=>{if(!Q)return null;return Pw("section",{className:"mb-12",children:[Pw("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),Pw(XX,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},JLA=({project:A,prevProject:Q,nextProject:$})=>{let{frontmatter:w,structuredContent:B,metadata:X,coverImageUrl:Y}=A,Z=A.ogImageUrl??Y;return Pw(va2,{children:[Pw(E6,{title:w.title,description:w.description,...Z?{ogImage:Z}:{},ogType:"article"},void 0,!1,void 0,this),Pw("article",{className:"project-detail",children:Pw("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:Pw("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&Pw(Hb,{src:Y,alt:w.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),Pw("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:w.title},void 0,!1,void 0,this),Pw("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[Pw("span",{className:"text-sm",children:X.year},void 0,!1,void 0,this),w.url&&Pw(va2,{children:[Pw("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),Pw("a",{href:w.url,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:"View Project"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Pw("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:w.description},void 0,!1,void 0,this),B&&Pw("div",{className:"case-study",children:[Pw(DO0,{title:"Context",content:B.context},void 0,!1,void 0,this),Pw(DO0,{title:"Problem",content:B.problem},void 0,!1,void 0,this),Pw(DO0,{title:"Solution",content:B.solution},void 0,!1,void 0,this),Pw(DO0,{title:"Outcome",content:B.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Pw(er$,{prevProject:Q,nextProject:$},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)};h0();zA();var Ao$=W.object({title:W.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:W.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:W.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:W.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:W.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:W.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),FLA=G2({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:Ao$,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
7669
7669
 
@@ -7839,7 +7839,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
7839
7839
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
7840
7840
  }
7841
7841
  .printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
7842
- `}},void 0,!1,void 0,this),GX("section",{className:"project-shell",children:[GX("header",{className:"project-hero",children:[GX("div",{className:"project-index",children:[Q.brandLabel&&GX("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&GX("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GX("div",{className:"project-title-panel",children:[GX("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),GX("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&GX("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),GX("div",{className:"printable-meta",children:[Q.year&&GX("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&GX("span",{children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&GX("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),GX(XX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&GX("footer",{className:"printable-footer",children:[GX("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?GX("a",{href:Q.canonicalUrl??Q.url,children:Q.canonicalUrl??Q.url},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Ho$=26214400,Ko$=60000;class NLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==VO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let $=Uo$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Xo$(Wo$(Zo$(),"brain-project-printable-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/printable/project/${Q.id}`,template:Ea2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:Ho$,timeoutMs:Ko$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Go$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await Yo$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=XY.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function Uo$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=XY.parse($);return{title:B.title,body:w,...B.description?{description:B.description}:{},year:B.year,...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.url?{url:B.url,canonicalUrl:B.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Go$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}u4();p2();h0();import{jsxDEV as zo$}from"preact/jsx-dev-runtime";var JO0="og-image",Do$="portfolio:og-image",Ta2=W.object({title:W.string().min(1),description:W.string().optional(),year:W.number().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),ya2={name:Do$,pluginId:"portfolio",schema:Ta2,renderers:{image:qo$}};function qo$(A){let Q=Ta2.parse(A);return zo$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class _LA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==JO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$}=t8(Q.content),w=XY.parse($),B=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl(w.coverImageId),Y={title:w.title,...w.description?{description:w.description}:{},year:w.year,...X?{coverImageUrl:X}:{},...B?{brandLabel:B}:{}};return{type:"image",data:await Ly({mediaPath:`/_media/og/project/${Q.id}`,template:ya2,content:Y,title:Y.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${Vo$(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function Vo$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var ga2={name:"@brains/portfolio",version:"0.2.0-alpha.195",description:"Portfolio showcase for projects and case studies",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Fo$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Lo$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Sa2=W.enum(["generating","draft","published","failed"]),Io$=W.object({title:W.string(),slug:W.string().optional(),status:Sa2,publishedAt:W.string().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.url().optional()}),No$=W.object({title:W.string(),status:Sa2,publishedAt:W.string().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),_o$=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),FO0=W.object({id:W.string(),entityType:W.literal("project"),content:W.string(),created:W.string(),updated:W.string(),visibility:Lo$,metadata:No$,contentHash:W.string(),frontmatter:Io$,body:W.string(),structuredContent:_o$.optional(),url:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Po$=W.object({projects:W.array(FO0),pageTitle:W.string().optional(),pagination:Fo$.nullable(),baseUrl:W.string().optional()}),bo$=W.object({prompt:W.string(),year:W.number()});function jo$(A,Q){for(let $ of[A,Q]){let w=$?.match(/\b(19\d{2}|20\d{2})\b/);if(w?.[1])return Number(w[1])}return null}class PLA extends c6{entityType="project";schema=Kx;adapter=vy;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",ga2,A,zLA)}async interceptCreate(A,Q,$){if(!A.prompt||A.content)return{kind:"continue",input:A};let w=jo$(A.title,A.prompt);if(!w)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await $.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:w},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new qO0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":G2({name:"project-list",description:"Portfolio project list page template",schema:Po$,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:VLA}}),"project-detail":G2({name:"project-detail",description:"Individual project case study template",schema:W.object({project:FO0,prevProject:FO0.nullable(),nextProject:FO0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:JLA}}),generation:FLA}}getDataSources(){return[new zO0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",VO0,new NLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",JO0,new _LA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=D9.getInstance().register(ILA())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let $=bo$.parse(Q);return A.ai.generate({prompt:LLA($),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:$,entityId:w}=Q.payload;if($!=="project")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"project",id:w});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:`Project not found: ${w}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=MQ(B.content,XY),Y=new Date().toISOString(),Z=i7(X.content,{...X.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...B,content:Z,metadata:{...B.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:$,entityId:w,publishedAt:Y}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:eA(B)}})}return{success:!0}})}}function bLA(A={}){return new PLA(A)}zA();h0();D5();h0();zA();var ma2=W.enum(["available","early access","coming soon","planned"]),ua2=W.enum(["available","early access","coming soon","planned"]),ca2=W.object({title:W.string(),description:W.string()}),bz=W.object({name:W.string(),availability:ma2,order:W.number(),ogImageId:W.string().optional()}),LO0=W.object({tagline:W.string(),promise:W.string(),role:W.string(),purpose:W.string(),audience:W.string(),values:W.array(W.string()).min(1),features:W.array(ca2).min(1).max(6),story:W.string()}),MwB=bz.pick({name:!0,availability:!0,order:!0}).extend({slug:W.string()}),Mo$=W.object({name:W.string(),availability:ua2,order:W.number(),slug:W.string()}),ko$=W.object({name:W.string(),availability:ua2,order:W.number(),ogImageId:W.string().optional()}),er=U6.extend({entityType:W.literal("product"),metadata:Mo$}),IO0=er.extend({frontmatter:ko$,body:LO0,labels:W.record(W.string(),W.string()),ogImageUrl:W.string().optional()}),Oo$=IO0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()});zA();p2();e9();class Ao extends n${constructor(){super(LO0,{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 jLA extends zQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:er,frontmatterSchema:bz,bodyFormatter:new Ao})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,bz);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,bz),$=O1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:$,availability:Q.availability,order:Q.order}}}}var NO0=new jLA;h0();zA();var pa2=W.object({title:W.string(),description:W.string()}),la2=W.object({title:W.string(),description:W.string()}),fo$=W.object({title:W.string(),description:W.string()}),ia2=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Ux=W.object({headline:W.string(),tagline:W.string()}),xo$=W.object({title:W.string(),description:W.string()}),_O0=W.object({vision:W.string(),pillars:W.array(pa2).min(1).max(6),approach:W.array(xo$).min(1).max(6),productsIntro:W.string(),technologies:W.array(fo$).min(1).max(6),benefits:W.array(la2).min(1).max(6),cta:ia2}),Ro$=Ux.pick({headline:!0}).extend({slug:W.string()}),vo$=W.object({headline:W.string(),slug:W.string()}),Co$=W.object({headline:W.string(),tagline:W.string()}),Qo=U6.extend({entityType:W.literal("products-overview"),metadata:vo$}),MLA=Qo.extend({frontmatter:Co$,body:_O0,labels:W.record(W.string(),W.string())});zA();p2();e9();class $o extends n${constructor(){super(_O0,{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 kLA extends zQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Qo,frontmatterSchema:Ux,bodyFormatter:new $o})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Ux);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ux),$=O1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:$}}}}var OLA=new kLA;zA();h0();var ho$=W.object({entityType:W.string(),query:W.object({id:W.string().optional()}).optional()});function da2(A,Q){let $=MQ(A.content,bz),w=Q.parse($.content),B=Q.getLabels();return IO0.parse({...A,frontmatter:$.metadata,body:w,labels:B})}function na2(A,Q){let $=MQ(A.content,Ux),w=Q.parse($.content),B=Q.getLabels();return MLA.parse({...A,frontmatter:$.metadata,body:w,labels:B})}class PO0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new $o;productFormatter=new Ao;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,$){let w=ho$.parse(A),B=$.entityService;if(w.entityType==="products-overview"){let K=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!K)throw Error("Products overview entity not found");let U=na2(K,this.overviewFormatter);return Q.parse(U)}if(w.query?.id){let K=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:w.query.id}},limit:1}}))[0];if(!K)throw Error(`Product not found: ${w.query.id}`);return Q.parse({product:da2(K,this.productFormatter)})}let[X,Y]=await Promise.all([B.listEntities({entityType:"products-overview",options:{limit:1}}),B.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Z=X[0];if(!Z)throw Error("Products overview entity not found");return Q.parse({overview:na2(Z,this.overviewFormatter),products:Y.map((H)=>da2(H,this.productFormatter))})}}import{jsxDEV as v1,Fragment as yo$}from"preact/jsx-dev-runtime";var ra2=({overview:A,products:Q})=>{let{frontmatter:$,body:w,labels:B}=A;return v1(yo$,{children:[v1(E6,{title:$.headline,description:$.tagline},void 0,!1,void 0,this),v1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[v1("style",{children:`
7842
+ `}},void 0,!1,void 0,this),GX("section",{className:"project-shell",children:[GX("header",{className:"project-hero",children:[GX("div",{className:"project-index",children:[Q.brandLabel&&GX("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&GX("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),GX("div",{className:"project-title-panel",children:[GX("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),GX("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&GX("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),GX("div",{className:"printable-meta",children:[Q.year&&GX("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&GX("span",{children:Q.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&GX("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),GX(XX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&GX("footer",{className:"printable-footer",children:[GX("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?GX("a",{href:Q.canonicalUrl??Q.url,children:Q.canonicalUrl??Q.url},void 0,!1,void 0,this):null]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Ho$=26214400,Ko$=60000;class NLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==VO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let $=Uo$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Xo$(Wo$(Zo$(),"brain-project-printable-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/printable/project/${Q.id}`,template:Ea2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:Ho$,timeoutMs:Ko$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Go$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await Yo$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=XY.parse(Q);if(!$.coverImageId)return;let w=await this.context.entityService.getEntity({entityType:"image",id:$.coverImageId});return w?.content.startsWith("data:image/")?w.content:void 0}}function Uo$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=XY.parse($);return{title:B.title,body:w,...B.description?{description:B.description}:{},year:B.year,...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.url?{url:B.url,canonicalUrl:B.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Go$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}u4();p2();h0();import{jsxDEV as zo$}from"preact/jsx-dev-runtime";var JO0="og-image",Do$="portfolio:og-image",Ta2=W.object({title:W.string().min(1),description:W.string().optional(),year:W.number().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),ya2={name:Do$,pluginId:"portfolio",schema:Ta2,renderers:{image:qo$}};function qo$(A){let Q=Ta2.parse(A);return zo$(Wb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class _LA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==JO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$}=t8(Q.content),w=XY.parse($),B=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl(w.coverImageId),Y={title:w.title,...w.description?{description:w.description}:{},year:w.year,...X?{coverImageUrl:X}:{},...B?{brandLabel:B}:{}};return{type:"image",data:await Ly({mediaPath:`/_media/og/project/${Q.id}`,template:ya2,content:Y,title:Y.title,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-project-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${Vo$(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){if(!A)return;let Q=await this.context.entityService.getEntity({entityType:"image",id:A});return Q?.content.startsWith("data:image/")?Q.content:void 0}}function Vo$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var ga2={name:"@brains/portfolio",version:"0.2.0-alpha.196",description:"Portfolio showcase for projects and case studies",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Fo$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Lo$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Sa2=W.enum(["generating","draft","published","failed"]),Io$=W.object({title:W.string(),slug:W.string().optional(),status:Sa2,publishedAt:W.string().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.url().optional()}),No$=W.object({title:W.string(),status:Sa2,publishedAt:W.string().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),_o$=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),FO0=W.object({id:W.string(),entityType:W.literal("project"),content:W.string(),created:W.string(),updated:W.string(),visibility:Lo$,metadata:No$,contentHash:W.string(),frontmatter:Io$,body:W.string(),structuredContent:_o$.optional(),url:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Po$=W.object({projects:W.array(FO0),pageTitle:W.string().optional(),pagination:Fo$.nullable(),baseUrl:W.string().optional()}),bo$=W.object({prompt:W.string(),year:W.number()});function jo$(A,Q){for(let $ of[A,Q]){let w=$?.match(/\b(19\d{2}|20\d{2})\b/);if(w?.[1])return Number(w[1])}return null}class PLA extends c6{entityType="project";schema=Kx;adapter=vy;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",ga2,A,zLA)}async interceptCreate(A,Q,$){if(!A.prompt||A.content)return{kind:"continue",input:A};let w=jo$(A.title,A.prompt);if(!w)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await $.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:w},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new qO0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":G2({name:"project-list",description:"Portfolio project list page template",schema:Po$,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:VLA}}),"project-detail":G2({name:"project-detail",description:"Individual project case study template",schema:W.object({project:FO0,prevProject:FO0.nullable(),nextProject:FO0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:JLA}}),generation:FLA}}getDataSources(){return[new zO0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",VO0,new NLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",JO0,new _LA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=D9.getInstance().register(ILA())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let $=bo$.parse(Q);return A.ai.generate({prompt:LLA($),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:$,entityId:w}=Q.payload;if($!=="project")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"project",id:w});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:`Project not found: ${w}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=MQ(B.content,XY),Y=new Date().toISOString(),Z=i7(X.content,{...X.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...B,content:Z,metadata:{...B.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:$,entityId:w,publishedAt:Y}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:$,entityId:w,error:eA(B)}})}return{success:!0}})}}function bLA(A={}){return new PLA(A)}zA();h0();D5();h0();zA();var ma2=W.enum(["available","early access","coming soon","planned"]),ua2=W.enum(["available","early access","coming soon","planned"]),ca2=W.object({title:W.string(),description:W.string()}),bz=W.object({name:W.string(),availability:ma2,order:W.number(),ogImageId:W.string().optional()}),LO0=W.object({tagline:W.string(),promise:W.string(),role:W.string(),purpose:W.string(),audience:W.string(),values:W.array(W.string()).min(1),features:W.array(ca2).min(1).max(6),story:W.string()}),MwB=bz.pick({name:!0,availability:!0,order:!0}).extend({slug:W.string()}),Mo$=W.object({name:W.string(),availability:ua2,order:W.number(),slug:W.string()}),ko$=W.object({name:W.string(),availability:ua2,order:W.number(),ogImageId:W.string().optional()}),er=U6.extend({entityType:W.literal("product"),metadata:Mo$}),IO0=er.extend({frontmatter:ko$,body:LO0,labels:W.record(W.string(),W.string()),ogImageUrl:W.string().optional()}),Oo$=IO0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()});zA();p2();e9();class Ao extends n${constructor(){super(LO0,{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 jLA extends zQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:er,frontmatterSchema:bz,bodyFormatter:new Ao})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,bz);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,bz),$=O1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:$,availability:Q.availability,order:Q.order}}}}var NO0=new jLA;h0();zA();var pa2=W.object({title:W.string(),description:W.string()}),la2=W.object({title:W.string(),description:W.string()}),fo$=W.object({title:W.string(),description:W.string()}),ia2=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Ux=W.object({headline:W.string(),tagline:W.string()}),xo$=W.object({title:W.string(),description:W.string()}),_O0=W.object({vision:W.string(),pillars:W.array(pa2).min(1).max(6),approach:W.array(xo$).min(1).max(6),productsIntro:W.string(),technologies:W.array(fo$).min(1).max(6),benefits:W.array(la2).min(1).max(6),cta:ia2}),Ro$=Ux.pick({headline:!0}).extend({slug:W.string()}),vo$=W.object({headline:W.string(),slug:W.string()}),Co$=W.object({headline:W.string(),tagline:W.string()}),Qo=U6.extend({entityType:W.literal("products-overview"),metadata:vo$}),MLA=Qo.extend({frontmatter:Co$,body:_O0,labels:W.record(W.string(),W.string())});zA();p2();e9();class $o extends n${constructor(){super(_O0,{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 kLA extends zQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Qo,frontmatterSchema:Ux,bodyFormatter:new $o})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Ux);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Ux),$=O1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:$}}}}var OLA=new kLA;zA();h0();var ho$=W.object({entityType:W.string(),query:W.object({id:W.string().optional()}).optional()});function da2(A,Q){let $=MQ(A.content,bz),w=Q.parse($.content),B=Q.getLabels();return IO0.parse({...A,frontmatter:$.metadata,body:w,labels:B})}function na2(A,Q){let $=MQ(A.content,Ux),w=Q.parse($.content),B=Q.getLabels();return MLA.parse({...A,frontmatter:$.metadata,body:w,labels:B})}class PO0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new $o;productFormatter=new Ao;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,$){let w=ho$.parse(A),B=$.entityService;if(w.entityType==="products-overview"){let K=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!K)throw Error("Products overview entity not found");let U=na2(K,this.overviewFormatter);return Q.parse(U)}if(w.query?.id){let K=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:w.query.id}},limit:1}}))[0];if(!K)throw Error(`Product not found: ${w.query.id}`);return Q.parse({product:da2(K,this.productFormatter)})}let[X,Y]=await Promise.all([B.listEntities({entityType:"products-overview",options:{limit:1}}),B.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Z=X[0];if(!Z)throw Error("Products overview entity not found");return Q.parse({overview:na2(Z,this.overviewFormatter),products:Y.map((H)=>da2(H,this.productFormatter))})}}import{jsxDEV as v1,Fragment as yo$}from"preact/jsx-dev-runtime";var ra2=({overview:A,products:Q})=>{let{frontmatter:$,body:w,labels:B}=A;return v1(yo$,{children:[v1(E6,{title:$.headline,description:$.tagline},void 0,!1,void 0,this),v1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[v1("style",{children:`
7843
7843
  @keyframes wave-drift {
7844
7844
  from { transform: translateX(0); }
7845
7845
  to { transform: translateX(-50%); }
@@ -8034,7 +8034,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
8034
8034
  font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
8035
8035
  }
8036
8036
  `}},void 0,!1,void 0,this),DD("section",{className:"product-shell",children:[DD("header",{className:"product-hero",children:[Q.brandLabel&&DD("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),DD("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&DD("div",{className:"printable-meta",children:DD("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),DD("div",{className:"product-body-wrap",children:[DD("aside",{className:"product-rail","aria-hidden":"true",children:DD("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),DD(XX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&DD("footer",{className:"printable-footer",children:Q.brandLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var io$=26214400,do$=60000;class xLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??lV}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==bO0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let $=no$(Q,{brandLabel:this.resolveBrandLabel()}),w=await uo$(lo$(po$(),"brain-product-printable-"));try{let B=await $D({outputDir:w,mediaPath:`/_media/printable/product/${Q.id}`,template:aa2,format:"pdf",content:$,siteConfig:{title:$.name,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await wD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:io$,timeoutMs:do$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${ro$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await co$(w,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}}function no$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=bz.parse($);return{name:B.name,body:w,availability:B.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function ro$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}u4();p2();h0();import{jsxDEV as ao$}from"preact/jsx-dev-runtime";var jO0="og-image",oo$="products:og-image",ta2=W.object({name:W.string().min(1),tagline:W.string().optional(),availability:W.string().optional(),brandLabel:W.string().optional()}),ea2={name:oo$,pluginId:"products",schema:ta2,renderers:{image:so$}};function so$(A){let Q=ta2.parse(A);return ao$(Wb,{cover:!0,brandLabel:Q.brandLabel??Q.name,eyebrow:"Product",title:Q.name,subtitle:Q.tagline,tag:Q.availability},void 0,!1,void 0,this)}class RLA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;deps;constructor(A,Q={}){this.context=A,this.deps=Q}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==jO0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=bz.parse($),X=to$(w,"Tagline"),Y=this.resolveBrandLabel(),Z={name:B.name,availability:B.availability,...X?{tagline:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Ly({mediaPath:`/_media/og/product/${Q.id}`,template:ea2,content:Z,title:Z.name,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-product-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${eo$(Q)}-og.png`}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}}function to$(A,Q){let $=A.split(/\r?\n/),w=$.findIndex((Y)=>Y.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(w===-1)return;let B=[];for(let Y of $.slice(w+1)){if(Y.trim().startsWith("## "))break;B.push(Y)}let X=B.join(`
8037
- `).trim();return X.length>0?X:void 0}function eo$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}var At2={name:"@brains/products",version:"0.2.0-alpha.195",description:"Product entity management and overview page for marketing showcase",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Qs$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Qt2=W.object({id:W.string(),entityType:W.string(),content:W.string(),created:W.string(),updated:W.string(),visibility:Qs$,metadata:W.record(W.string(),W.unknown()),contentHash:W.string()}),$t2=W.enum(["available","early access","coming soon","planned"]),$s$=W.object({title:W.string(),description:W.string()}),ws$=W.object({name:W.string(),availability:$t2,order:W.number(),ogImageId:W.string().optional()}),Bs$=W.object({tagline:W.string(),promise:W.string(),role:W.string(),purpose:W.string(),audience:W.string(),values:W.array(W.string()).min(1),features:W.array($s$).min(1).max(6),story:W.string()}),Xs$=W.object({name:W.string(),availability:$t2,order:W.number(),slug:W.string()}),wt2=Qt2.extend({entityType:W.literal("product"),metadata:Xs$,frontmatter:ws$,body:Bs$,labels:W.record(W.string(),W.string()),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()}),MO0=W.object({title:W.string(),description:W.string()}),Ys$=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Zs$=W.object({headline:W.string(),tagline:W.string()}),Ws$=W.object({vision:W.string(),pillars:W.array(MO0).min(1).max(6),approach:W.array(MO0).min(1).max(6),productsIntro:W.string(),technologies:W.array(MO0).min(1).max(6),benefits:W.array(MO0).min(1).max(6),cta:Ys$}),Hs$=W.object({headline:W.string(),slug:W.string()}),Ks$=Qt2.extend({entityType:W.literal("products-overview"),metadata:Hs$,frontmatter:Zs$,body:Ws$,labels:W.record(W.string(),W.string())}),Us$=W.object({overview:Ks$,products:W.array(wt2)}),Gs$=W.object({product:wt2});class vLA extends c6{entityType=NO0.entityType;schema=er;adapter=NO0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",At2,A,fLA)}getTemplates(){return{"product-list":G2({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:Us$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ra2}}),"product-detail":G2({name:"product-detail",description:"Individual product detail page",schema:Gs$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:oa2}})}}getDataSources(){return[new PO0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",bO0,new xLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",jO0,new RLA(A)),A.entities.register("products-overview",Qo,OLA)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function T90(A={}){return new vLA(A)}zA();h0();h0();var Ds$=W.enum(["public","shared","restricted"]),Bt2=W.object({includeEntityTypes:W.array(W.string()).default([]),minRelevanceScore:W.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:W.number().min(0).max(1).default(0.85),autoMerge:W.boolean().default(!0),extractableStatuses:W.array(W.string()).default(["published"]),enableAutoExtraction:W.boolean().default(!0),extractionVisibility:Ds$.default("public"),sourceChangeBatchDelayMs:W.number().int().min(0).default(1000)});zA();h0();zA();var KBB=W.object({}),qs$=W.record(W.string(),W.unknown()).transform(()=>({})),wo=U6.extend({entityType:W.literal("topic"),metadata:qs$}),UBB=W.object({content:W.string()}),Xt2=W.object({title:W.string().describe("Topic title")});var Cy="topics",bw="topic",CLA="topics-projection",Yt2="topic:project",kO0="topics-plugin",Zt2="topics:batch-completed",Wt2="topics-source-batch";class rV extends zQ{constructor(){super({entityType:bw,purpose:"A recurring theme or subject derived from the user's content.",schema:wo,frontmatterSchema:Xt2})}buildFrontmatter(A){return{title:A}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title))}fromMarkdown(A){return{content:A,entityType:bw}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),w=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return w?w[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),formatted:A,title:Q.title}}catch{return{content:A,formatted:A,title:"Unknown Topic"}}return{content:A,formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title))}}zA();h0();h0();var zs$=W.object({title:W.string().max(100),content:W.string(),relevanceScore:W.number().min(0).max(1)}),Ht2=W.array(zs$);var Vs$=W.object({topics:Ht2}),Kt2=G2({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:Vs$,basePrompt:`You are an expert at analyzing content and extracting key topics.
8037
+ `).trim();return X.length>0?X:void 0}function eo$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}var At2={name:"@brains/products",version:"0.2.0-alpha.196",description:"Product entity management and overview page for marketing showcase",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/media-page-composer":"workspace:*","@brains/media-renderer":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/app":"workspace:*","@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var Qs$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Qt2=W.object({id:W.string(),entityType:W.string(),content:W.string(),created:W.string(),updated:W.string(),visibility:Qs$,metadata:W.record(W.string(),W.unknown()),contentHash:W.string()}),$t2=W.enum(["available","early access","coming soon","planned"]),$s$=W.object({title:W.string(),description:W.string()}),ws$=W.object({name:W.string(),availability:$t2,order:W.number(),ogImageId:W.string().optional()}),Bs$=W.object({tagline:W.string(),promise:W.string(),role:W.string(),purpose:W.string(),audience:W.string(),values:W.array(W.string()).min(1),features:W.array($s$).min(1).max(6),story:W.string()}),Xs$=W.object({name:W.string(),availability:$t2,order:W.number(),slug:W.string()}),wt2=Qt2.extend({entityType:W.literal("product"),metadata:Xs$,frontmatter:ws$,body:Bs$,labels:W.record(W.string(),W.string()),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()}),MO0=W.object({title:W.string(),description:W.string()}),Ys$=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Zs$=W.object({headline:W.string(),tagline:W.string()}),Ws$=W.object({vision:W.string(),pillars:W.array(MO0).min(1).max(6),approach:W.array(MO0).min(1).max(6),productsIntro:W.string(),technologies:W.array(MO0).min(1).max(6),benefits:W.array(MO0).min(1).max(6),cta:Ys$}),Hs$=W.object({headline:W.string(),slug:W.string()}),Ks$=Qt2.extend({entityType:W.literal("products-overview"),metadata:Hs$,frontmatter:Zs$,body:Ws$,labels:W.record(W.string(),W.string())}),Us$=W.object({overview:Ks$,products:W.array(wt2)}),Gs$=W.object({product:wt2});class vLA extends c6{entityType=NO0.entityType;schema=er;adapter=NO0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",At2,A,fLA)}getTemplates(){return{"product-list":G2({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:Us$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ra2}}),"product-detail":G2({name:"product-detail",description:"Individual product detail page",schema:Gs$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:oa2}})}}getDataSources(){return[new PO0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",bO0,new xLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",jO0,new RLA(A)),A.entities.register("products-overview",Qo,OLA)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function T90(A={}){return new vLA(A)}zA();h0();h0();var Ds$=W.enum(["public","shared","restricted"]),Bt2=W.object({includeEntityTypes:W.array(W.string()).default([]),minRelevanceScore:W.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:W.number().min(0).max(1).default(0.85),autoMerge:W.boolean().default(!0),extractableStatuses:W.array(W.string()).default(["published"]),enableAutoExtraction:W.boolean().default(!0),extractionVisibility:Ds$.default("public"),sourceChangeBatchDelayMs:W.number().int().min(0).default(1000)});zA();h0();zA();var KBB=W.object({}),qs$=W.record(W.string(),W.unknown()).transform(()=>({})),wo=U6.extend({entityType:W.literal("topic"),metadata:qs$}),UBB=W.object({content:W.string()}),Xt2=W.object({title:W.string().describe("Topic title")});var Cy="topics",bw="topic",CLA="topics-projection",Yt2="topic:project",kO0="topics-plugin",Zt2="topics:batch-completed",Wt2="topics-source-batch";class rV extends zQ{constructor(){super({entityType:bw,purpose:"A recurring theme or subject derived from the user's content.",schema:wo,frontmatterSchema:Xt2})}buildFrontmatter(A){return{title:A}}toMarkdown(A){let Q=this.parseTopicBody(A.content);return this.buildMarkdown(Q.content,this.buildFrontmatter(Q.title))}fromMarkdown(A){return{content:A,entityType:bw}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),w=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return w?w[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),formatted:A,title:Q.title}}catch{return{content:A,formatted:A,title:"Unknown Topic"}}return{content:A,formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title))}}zA();h0();h0();var zs$=W.object({title:W.string().max(100),content:W.string(),relevanceScore:W.number().min(0).max(1)}),Ht2=W.array(zs$);var Vs$=W.object({topics:Ht2}),Kt2=G2({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:Vs$,basePrompt:`You are an expert at analyzing content and extracting key topics.
8038
8038
 
8039
8039
  Analyze the provided content and extract meaningful topics discussed.
8040
8040
 
@@ -8137,13 +8137,13 @@ ${A.incomingTopic.content}`})}}function Os$(A){if(A.length===0)return"";return A
8137
8137
 
8138
8138
  ${Q.content}`}).join(`
8139
8139
 
8140
- `)}async function hy(A,Q,$,w={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let B=w.minRelevanceScore??0,X=w.autoMerge??!1,Y=w.mergeSimilarityThreshold??0.85,Z=w.targetVisibility??"public",H=Nt2(A),K=new oV(Q.entityService,$),U=w.topicMergeSynthesizer??new SLA(Q,$),G=await vO0(Q.entityService,void 0,Z),D=new Map,q=0,J=0,F=0;for(let _ of H){$.info(`Processing batch of ${_.length} entities`);let j=Os$(_),b=CO0({entityTitle:`Batch of ${_.length} entities`,entityType:"batch",content:j,existingTopicTitles:G});try{let v=(await Q.ai.generate({prompt:b,templateName:"topics:extraction"})).topics.filter((R)=>R.relevanceScore>=B);for(let R of v)try{if(X){let u=await K.findMergeCandidate({incoming:R,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(u){let i=await U.synthesize({existingTopic:u.topic,incomingTopic:R}),a=await K.applySynthesizedMerge({existingId:u.topic.id,synthesized:{...i,title:u.title},visibility:Z});if(!a)throw Error(`Failed to merge topic: ${R.title}`);D.set(a.id,a),J++;continue}}let O=K.getTopicIdForTitle(R.title,Z);if(D.has(O)){F++;continue}let S=await K.createTopicOptimistic({title:R.title,content:R.content,visibility:Z});if(S.topic)D.set(S.topic.id,S.topic);if(S.created)q++;else F++}catch(O){$.error("Topic batch item failed",{title:R.title,error:eA(O)})}}catch(f){$.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:eA(f)})}}let L={created:q,merged:J,skipped:F,batches:H.length};if(q>0||J>0)await Q.messaging.send({type:Zt2,payload:L,broadcast:!0});return L}zA();h0();var fs$=W.discriminatedUnion("mode",[W.object({mode:W.literal("derive"),reason:W.string().optional()}),W.object({mode:W.literal("rebuild"),reason:W.string().optional()}),W.object({mode:W.literal("source-batch"),minRelevanceScore:W.number().min(0).max(1).optional()})]);class mLA{refs=new Map;add(A){this.refs.set(`${A.entityType}:${A.entityId}`,A)}drain(){let A=Array.from(this.refs.values());return this.refs.clear(),A}}function kt2(A){let{context:Q,logger:$,config:w}=A;return{process:async(B)=>{if(B.mode==="derive")return await A.extractAllTopics(),{success:!0};if(B.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return xs$({context:Q,logger:$,config:w,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??w.minRelevanceScore})},validateAndParse:(B)=>{let X=fs$.safeParse(B??{});return X.success?X.data:null}}}async function xs$(A){let Q=A.sourceBatch.drain(),$=await Promise.all(Q.map(async(K)=>({ref:K,entity:await A.context.entityService.getEntity({entityType:K.entityType,id:K.entityId})}))),w=0,B=0,X=0,Y=0,Z=[];for(let{ref:K,entity:U}of $){if(!U){B++;continue}if(U.contentHash!==K.contentHash){w++;continue}if(!A.isEntityPublished(U)){X++;continue}if(!Qk(U.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(U)}if(Z.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:w,missing:B,unpublished:X,hidden:Y};let H=await hy(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...H,stale:w,missing:B,unpublished:X,hidden:Y}}function Ot2(){return{priority:5,source:kO0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Cy}}}async function ft2(A){let Q=await Rt2(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let $=await hy(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",$)}async function xt2(A){let Q=await Rt2(A),$=await uLA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",$)}async function uLA(A,Q,$,w){let B=new oV(Q.entityService,$),X=await B.listTopics({visibility:w.extractionVisibility});for(let Z of X)await B.deleteTopic(Z.id);if(A.length===0)return{deleted:X.length,created:0,merged:0,skipped:0,batches:0};let Y=await hy(A,Q,$,{minRelevanceScore:w.minRelevanceScore,autoMerge:w.autoMerge,mergeSimilarityThreshold:w.mergeSimilarityThreshold,targetVisibility:w.extractionVisibility});return{deleted:X.length,...Y}}async function Rt2(A){let Q=Rs$(A),$=[];for(let w of Q){let B=await A.context.entityService.listEntities({entityType:w,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let X of B){if(!A.isEntityPublished(X))continue;$.push(X)}}return $}function Rs$(A){return A.context.entityService.getEntityTypes().filter(($)=>A.shouldProcessEntityType($))}var Yo=W.object({entityType:W.string(),content:W.string(),metadata:W.record(W.string(),W.unknown()).optional()}),vs$=Yo.extend({minRelevanceScore:W.number().optional()}),Cs$=W.object({contentA:Yo,contentB:Yo,minRelevanceScore:W.number().optional(),threshold:W.number().min(0).max(1).optional()}),m90=W.object({title:W.string(),content:W.string()}),hs$=W.object({existingTopics:W.array(m90),incomingTopic:m90,threshold:W.number().optional()}),Es$=W.object({existingTopics:W.array(m90).default([]),incomingTopic:m90.extend({relevanceScore:W.number().min(0).max(1).optional()}),threshold:W.number().optional()}),Ts$=W.object({entities:W.array(Yo).min(1),minRelevanceScore:W.number().optional()}),ys$=W.object({existingTopics:W.array(m90).optional(),entities:W.array(Yo)}),gs$=W.object({entities:W.array(Yo)});function Xo(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:u6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function vt2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function Ss$(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function ms$(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:Ss$(Q)}]}}async function Ey(A){let Q=await A.entityService.listEntities({entityType:bw});await Promise.all(Q.map(($)=>A.entityService.deleteEntity({entityType:bw,id:$.id})))}async function us$(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise(($)=>setTimeout($,100))}}function Ct2(A){let{context:Q,logger:$,config:w}=A,B=new gLA(Q,$),X=async(Y,Z,H="")=>{let K=Xo(Y,H);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await Ey(Q);let Z=vs$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Xo(Z);return(await B.extractFromEntity(K,H)).map((G)=>ms$(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await Ey(Q);let Z=Cs$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Z.threshold??w.mergeSimilarityThreshold,[U,G]=await Promise.all([X(Z.contentA,H,"-a"),X(Z.contentB,H,"-b")]),D=new oV(Q.entityService,$),q=[];for(let L of U){let _=await D.createTopic(L);if(_)q.push(_)}let J=(await Promise.all(G.map(async(L)=>{let _=await D.findMergeCandidate({incoming:L,threshold:K,additionalCandidates:q});if(!_)return null;return{incomingTitle:L.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((L)=>L!==null),F=J.map((L)=>L.candidateTitle);return{topicsA:U.map(vt2),topicsB:G.map(vt2),matchingTitles:F,mergeCandidates:J,wouldMerge:J.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await Ey(Q);let Z=hs$.parse(Y),H=Z.threshold??w.mergeSimilarityThreshold,K=new oV(Q.entityService,$),U=[];for(let D of Z.existingTopics){let q=await K.createTopic(D);if(q)U.push(q)}let G=await K.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:H,additionalCandidates:U});return{found:G!==null,candidateTitle:G?.title,candidateScore:G?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await Ey(Q);let Z=Es$.parse(Y),H=new oV(Q.entityService,$);for(let D of Z.existingTopics)await H.createTopic({title:D.title,content:D.content});await us$(Q);let K=Xo({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await hy([K],Q,$,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??w.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:bw});return{...U,topicCount:G.length,topics:G.map(TLA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await Ey(Q);let Z=ys$.parse(Y),H=new oV(Q.entityService,$);for(let D of Z.existingTopics??[])await H.createTopic(D);let K=Z.entities.map((D,q)=>Xo(D,`-rebuild-${q}`)),U=await uLA(K,Q,$,w),G=await Q.entityService.listEntities({entityType:bw});return{...U,topicCount:G.length,topics:G.map(TLA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await Ey(Q);let Z=Ts$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=new oV(Q.entityService,$),U=[];for(let[D,q]of Z.entities.entries()){let J=Xo(q,`-sequential-${D}`),F=await B.extractFromEntity(J,H);for(let L of F)await K.createTopic({title:L.title,content:L.content});U.push({extractedTitles:F.map((L)=>L.title)})}let G=await Q.entityService.listEntities({entityType:bw});return{totalTopics:G.length,perEntity:U,topics:G.map(Bo)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await Ey(Q);let H=gs$.parse(Y).entities.map((G,D)=>Xo(G,`-batch-${D}`)),K=await hy(H,Q,$,{minRelevanceScore:w.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:bw});return{...K,topics:U.map(Bo)}})}var cs$=new rV;async function ht2({entity:A,config:Q}){let $=wo.parse(A),w=cs$.parseTopicBody($.content);return{$type:"ai.rizom.brain.topic",title:w.title,body:w.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function cLA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:i8["ai.rizom.brain.topic"],validate:!1,buildRecord:ht2}}var Et2={name:"@brains/topics",version:"0.2.0-alpha.195",description:"Extract and manage topics from conversations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var ls$=new rV,is$=W.looseObject({status:W.unknown().optional()});class Tt2 extends c6{entityType=bw;schema=wo;adapter=ls$;unregisterAtprotoProjection;sourceBatch=new mLA;constructor(A={}){super(Cy,Et2,A,Bt2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:Kt2,"merge-synthesis":Ut2,"topic-list":Gt2,"topic-detail":Dt2}}getDataSources(){return[new yLA(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:CLA,targetType:bw,job:{type:Yt2,handler:kt2({context:A,logger:this.logger,config:this.config,extractAllTopics:()=>this.extractAllTopics(A),rebuildAllTopics:()=>this.rebuildAllTopics(A),sourceBatch:this.sourceBatch,isEntityPublished:(Q)=>this.isEntityPublished(Q)})},initialSync:{shouldEnqueue:async()=>!await OC(A,bw,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Ot2()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let $=Q.entity;if(!$)return null;if(!this.shouldProcessEntityType($.entityType,A.entityService))return null;if(!this.isEntityPublished($))return null;if(!Qk($.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:$.id,entityType:$.entityType,contentHash:$.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:kO0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:Wt2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Cy}})}}]}async onRegister(A){A.insights.register("topic-distribution",Vt2()),Jt2({context:A,pluginId:this.id}),Ct2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=D9.getInstance().register(cLA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(CLA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===bw)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=is$.safeParse(A.metadata),$=Q.success?Q.data.status:void 0;if($===void 0||$===null)return!0;if(typeof $!=="string")return!1;return this.config.extractableStatuses.includes($)}async extractAllTopics(A){await ft2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await xt2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function hO0(A={}){return new Tt2(A)}zA();h0();zA();var pLA=W.enum(["linkedin"]),yt2=W.enum(["linkedin"]),lLA=W.enum(["generating","draft","queued","published","failed"]),gt2=W.enum(["generating","draft","queued","published","failed"]),St2=W.enum(["post","deck"]),ds$=W.enum(["post","deck"]),mt2=W.object({id:W.string().min(1).describe("Document entity ID")}),ns$=W.object({id:W.string().min(1)}),sV=W.object({title:W.string().describe("Short descriptive title (3-6 words) for file naming"),platform:pLA.describe("Target platform"),status:lLA,coverImageId:W.string().optional().describe("Image entity ID for post image"),documents:W.array(mt2).optional().describe("Document attachments for publishing"),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional().describe("ID from platform after publishing"),sourceEntityId:W.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:St2.optional().describe("Source entity type (post, deck)")}),ut2=sV.extend({platform:pLA.optional(),status:lLA.optional()}),rs$=sV.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:W.string().describe("URL-friendly identifier: {platform}-{title}"),error:W.string().optional()}),os$=W.object({title:W.string(),platform:yt2,status:gt2,publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),ss$=W.object({title:W.string(),platform:yt2,status:gt2,coverImageId:W.string().optional(),documents:W.array(ns$).optional(),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:ds$.optional()}),Gx=U6.extend({entityType:W.literal("social-post"),metadata:os$}),EO0=Gx.extend({frontmatter:ss$,body:W.string()}),as$=EO0.extend({url:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});zA();p2();class iLA extends zQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:Gx,frontmatterSchema:sV,supportsCoverImage:!0})}toMarkdown(A){let Q,$={};try{$=this.parseFrontMatter(A.content,sV),Q=this.extractBody(A.content)}catch{Q=A.content}let w={...$,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,ut2),$=Q.platform??"linkedin",w=Q.status??"draft",B=`${$}-${O1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:$,status:w,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,sV)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let $={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",$),metadata:{title:A.title,slug:`linkedin-${O1(A.title)}`,platform:"linkedin",status:"generating"}}}}var oY=new iLA;zA();zA();h0();var ts$=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),platform:W.enum(["linkedin"]).optional(),status:W.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:W.boolean().optional(),nextInQueue:W.boolean().optional()}),es$=W.looseObject({entityType:W.string().optional(),query:ts$.optional()});function ct2(A){let Q=MQ(A.content,sV);return EO0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class TO0 extends n7{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=es$.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return ct2(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,$){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:$.baseUrl}}async fetch(A,Q,$){let{query:w}=this.parseQuery(A),B=$.entityService;if(w.nextInQueue)return this.fetchNextInQueue(Q,B);if(w.id){let{item:U}=await this.fetchDetail(w.id,B);return Q.parse(this.buildDetailResult(U,null))}let X={};if(w.platform)X.platform=w.platform;if(w.status)X.status=w.status;let Y=Object.keys(X).length>0,Z=w.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:H,pagination:K}=await this.fetchList(w,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(H,K,w))}async fetchNextInQueue(A,Q){let w=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],B=w?ct2(w):null;return A.parse({post:B})}}h0();var pt2=W.object({accessToken:W.string().optional(),refreshToken:W.string().optional(),organizationId:W.string().optional(),apiVersion:W.string().regex(/^\d{6}$/).optional()}),dLA=W.object({linkedin:pt2.optional(),publishInterval:W.number().default(3600000),enabled:W.boolean().default(!0),defaultPrompt:W.string().default("Create an engaging social media post that drives engagement"),maxRetries:W.number().default(3),autoGenerateOnBlogPublish:W.boolean().default(!1)});zA();p2();h0();Uw();rLA();import{jsxDEV as L7,Fragment as $a$}from"preact/jsx-dev-runtime";function Aa$(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Qa$(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var gO0=({posts:A,pageTitle:Q,pagination:$,baseUrl:w="/social-posts"})=>{let B=Q??"Social Posts",X=$?.totalItems??A.length,Y=`Browse all ${X} social ${X===1?"post":"posts"}`;return L7($a$,{children:[L7(E6,{title:B,description:Y},void 0,!1,void 0,this),L7("div",{className:"social-post-list bg-theme",children:L7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[L7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?L7("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):L7("ul",{className:"space-y-6",children:A.map((Z)=>L7("li",{children:L7(v8,{href:Z.url,variant:"horizontal",children:L7("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&L7("img",{src:Z.coverImageUrl,alt:Z.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),L7("div",{className:"flex-1 min-w-0",children:[L7("div",{className:"flex items-start justify-between gap-4 mb-2",children:[L7("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),L7("time",{className:"text-sm text-theme-muted shrink-0",children:Qa$(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),L7("div",{className:"flex items-center gap-2 mb-3",children:[L7(sK,{status:Z.frontmatter.status},void 0,!1,void 0,this),L7("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),L7("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),L7("p",{className:"text-theme leading-relaxed",children:Aa$(Z.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)},Z.id,!1,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&L7(Ub,{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)};import{jsxDEV as I7,Fragment as wa$}from"preact/jsx-dev-runtime";function lt2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var SO0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,$=A.body.slice(0,160),w=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return I7(wa$,{children:[I7(E6,{title:Q,description:$},void 0,!1,void 0,this),I7("section",{className:"social-post-detail",children:I7("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:I7("div",{className:"max-w-3xl mx-auto",children:[I7(yL,{items:w},void 0,!1,void 0,this),I7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),I7("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[I7(sK,{status:A.frontmatter.status},void 0,!1,void 0,this),I7("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),I7("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&&I7(Hb,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),I7(v8,{className:"p-8 mb-8",children:I7("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),I7("div",{className:"space-y-4 text-sm text-theme-muted",children:[I7("div",{children:[I7("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",lt2(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&I7("div",{children:[I7("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",lt2(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&I7("div",{children:I7("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 u90(A){return`social-media:${A}`}var Ba$=W.union([W.boolean(),W.object({generate:W.boolean().optional(),prompt:W.string().optional()})]),oLA=W.object({prompt:W.string().optional(),platform:W.enum(["linkedin"]).optional(),sourceEntityType:W.enum(["post","deck"]).optional(),sourceEntityId:W.string().optional(),title:W.string().optional().describe("Required when content is provided directly"),content:W.string().optional(),addToQueue:W.boolean().optional(),generateImage:W.boolean().optional().describe("Auto-generate cover image for post"),coverImage:Ba$.optional().describe("Generic cover image generation request")}),Xa$=xU.extend({slug:W.string().optional()});class Ty extends yZ{constructor(A,Q){super(A,Q,{schema:oLA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let $=A.platform??"linkedin",w=A.addToQueue??!1,{prompt:B,sourceEntityType:X,sourceEntityId:Y}=A,{content:Z,title:H}=A;if(Z&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:Z,templateName:u90($)});H=L.title,Z=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let L=await this.context.entityService.getEntity({entityType:X,id:Y});if(!L)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let j=W.looseObject({slug:W.string()}).safeParse(L.metadata),b=j.success?j.data.slug:Y,f=await this.context.ai.generate({prompt:`Create an engaging ${$} post to promote this ${X}:
8140
+ `)}async function hy(A,Q,$,w={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let B=w.minRelevanceScore??0,X=w.autoMerge??!1,Y=w.mergeSimilarityThreshold??0.85,Z=w.targetVisibility??"public",H=Nt2(A),K=new oV(Q.entityService,$),U=w.topicMergeSynthesizer??new SLA(Q,$),G=await vO0(Q.entityService,void 0,Z),D=new Map,q=0,J=0,F=0;for(let _ of H){$.info(`Processing batch of ${_.length} entities`);let j=Os$(_),b=CO0({entityTitle:`Batch of ${_.length} entities`,entityType:"batch",content:j,existingTopicTitles:G});try{let v=(await Q.ai.generate({prompt:b,templateName:"topics:extraction"})).topics.filter((R)=>R.relevanceScore>=B);for(let R of v)try{if(X){let u=await K.findMergeCandidate({incoming:R,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(u){let i=await U.synthesize({existingTopic:u.topic,incomingTopic:R}),a=await K.applySynthesizedMerge({existingId:u.topic.id,synthesized:{...i,title:u.title},visibility:Z});if(!a)throw Error(`Failed to merge topic: ${R.title}`);D.set(a.id,a),J++;continue}}let O=K.getTopicIdForTitle(R.title,Z);if(D.has(O)){F++;continue}let S=await K.createTopicOptimistic({title:R.title,content:R.content,visibility:Z});if(S.topic)D.set(S.topic.id,S.topic);if(S.created)q++;else F++}catch(O){$.error("Topic batch item failed",{title:R.title,error:eA(O)})}}catch(f){$.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:eA(f)})}}let L={created:q,merged:J,skipped:F,batches:H.length};if(q>0||J>0)await Q.messaging.send({type:Zt2,payload:L,broadcast:!0});return L}zA();h0();var fs$=W.discriminatedUnion("mode",[W.object({mode:W.literal("derive"),reason:W.string().optional()}),W.object({mode:W.literal("rebuild"),reason:W.string().optional()}),W.object({mode:W.literal("source-batch"),minRelevanceScore:W.number().min(0).max(1).optional()})]);class mLA{refs=new Map;add(A){this.refs.set(`${A.entityType}:${A.entityId}`,A)}drain(){let A=Array.from(this.refs.values());return this.refs.clear(),A}}function kt2(A){let{context:Q,logger:$,config:w}=A;return{process:async(B)=>{if(B.mode==="derive")return await A.extractAllTopics(),{success:!0};if(B.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return xs$({context:Q,logger:$,config:w,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??w.minRelevanceScore})},validateAndParse:(B)=>{let X=fs$.safeParse(B??{});return X.success?X.data:null}}}async function xs$(A){let Q=A.sourceBatch.drain(),$=await Promise.all(Q.map(async(K)=>({ref:K,entity:await A.context.entityService.getEntity({entityType:K.entityType,id:K.entityId})}))),w=0,B=0,X=0,Y=0,Z=[];for(let{ref:K,entity:U}of $){if(!U){B++;continue}if(U.contentHash!==K.contentHash){w++;continue}if(!A.isEntityPublished(U)){X++;continue}if(!Qk(U.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(U)}if(Z.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:w,missing:B,unpublished:X,hidden:Y};let H=await hy(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...H,stale:w,missing:B,unpublished:X,hidden:Y}}function Ot2(){return{priority:5,source:kO0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Cy}}}async function ft2(A){let Q=await Rt2(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let $=await hy(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",$)}async function xt2(A){let Q=await Rt2(A),$=await uLA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",$)}async function uLA(A,Q,$,w){let B=new oV(Q.entityService,$),X=await B.listTopics({visibility:w.extractionVisibility});for(let Z of X)await B.deleteTopic(Z.id);if(A.length===0)return{deleted:X.length,created:0,merged:0,skipped:0,batches:0};let Y=await hy(A,Q,$,{minRelevanceScore:w.minRelevanceScore,autoMerge:w.autoMerge,mergeSimilarityThreshold:w.mergeSimilarityThreshold,targetVisibility:w.extractionVisibility});return{deleted:X.length,...Y}}async function Rt2(A){let Q=Rs$(A),$=[];for(let w of Q){let B=await A.context.entityService.listEntities({entityType:w,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let X of B){if(!A.isEntityPublished(X))continue;$.push(X)}}return $}function Rs$(A){return A.context.entityService.getEntityTypes().filter(($)=>A.shouldProcessEntityType($))}var Yo=W.object({entityType:W.string(),content:W.string(),metadata:W.record(W.string(),W.unknown()).optional()}),vs$=Yo.extend({minRelevanceScore:W.number().optional()}),Cs$=W.object({contentA:Yo,contentB:Yo,minRelevanceScore:W.number().optional(),threshold:W.number().min(0).max(1).optional()}),m90=W.object({title:W.string(),content:W.string()}),hs$=W.object({existingTopics:W.array(m90),incomingTopic:m90,threshold:W.number().optional()}),Es$=W.object({existingTopics:W.array(m90).default([]),incomingTopic:m90.extend({relevanceScore:W.number().min(0).max(1).optional()}),threshold:W.number().optional()}),Ts$=W.object({entities:W.array(Yo).min(1),minRelevanceScore:W.number().optional()}),ys$=W.object({existingTopics:W.array(m90).optional(),entities:W.array(Yo)}),gs$=W.object({entities:W.array(Yo)});function Xo(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:u6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function vt2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function Ss$(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function ms$(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:Ss$(Q)}]}}async function Ey(A){let Q=await A.entityService.listEntities({entityType:bw});await Promise.all(Q.map(($)=>A.entityService.deleteEntity({entityType:bw,id:$.id})))}async function us$(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise(($)=>setTimeout($,100))}}function Ct2(A){let{context:Q,logger:$,config:w}=A,B=new gLA(Q,$),X=async(Y,Z,H="")=>{let K=Xo(Y,H);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await Ey(Q);let Z=vs$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Xo(Z);return(await B.extractFromEntity(K,H)).map((G)=>ms$(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await Ey(Q);let Z=Cs$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Z.threshold??w.mergeSimilarityThreshold,[U,G]=await Promise.all([X(Z.contentA,H,"-a"),X(Z.contentB,H,"-b")]),D=new oV(Q.entityService,$),q=[];for(let L of U){let _=await D.createTopic(L);if(_)q.push(_)}let J=(await Promise.all(G.map(async(L)=>{let _=await D.findMergeCandidate({incoming:L,threshold:K,additionalCandidates:q});if(!_)return null;return{incomingTitle:L.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((L)=>L!==null),F=J.map((L)=>L.candidateTitle);return{topicsA:U.map(vt2),topicsB:G.map(vt2),matchingTitles:F,mergeCandidates:J,wouldMerge:J.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await Ey(Q);let Z=hs$.parse(Y),H=Z.threshold??w.mergeSimilarityThreshold,K=new oV(Q.entityService,$),U=[];for(let D of Z.existingTopics){let q=await K.createTopic(D);if(q)U.push(q)}let G=await K.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:H,additionalCandidates:U});return{found:G!==null,candidateTitle:G?.title,candidateScore:G?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await Ey(Q);let Z=Es$.parse(Y),H=new oV(Q.entityService,$);for(let D of Z.existingTopics)await H.createTopic({title:D.title,content:D.content});await us$(Q);let K=Xo({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await hy([K],Q,$,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??w.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:bw});return{...U,topicCount:G.length,topics:G.map(TLA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await Ey(Q);let Z=ys$.parse(Y),H=new oV(Q.entityService,$);for(let D of Z.existingTopics??[])await H.createTopic(D);let K=Z.entities.map((D,q)=>Xo(D,`-rebuild-${q}`)),U=await uLA(K,Q,$,w),G=await Q.entityService.listEntities({entityType:bw});return{...U,topicCount:G.length,topics:G.map(TLA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await Ey(Q);let Z=Ts$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=new oV(Q.entityService,$),U=[];for(let[D,q]of Z.entities.entries()){let J=Xo(q,`-sequential-${D}`),F=await B.extractFromEntity(J,H);for(let L of F)await K.createTopic({title:L.title,content:L.content});U.push({extractedTitles:F.map((L)=>L.title)})}let G=await Q.entityService.listEntities({entityType:bw});return{totalTopics:G.length,perEntity:U,topics:G.map(Bo)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await Ey(Q);let H=gs$.parse(Y).entities.map((G,D)=>Xo(G,`-batch-${D}`)),K=await hy(H,Q,$,{minRelevanceScore:w.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:bw});return{...K,topics:U.map(Bo)}})}var cs$=new rV;async function ht2({entity:A,config:Q}){let $=wo.parse(A),w=cs$.parseTopicBody($.content);return{$type:"ai.rizom.brain.topic",title:w.title,body:w.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function cLA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:i8["ai.rizom.brain.topic"],validate:!1,buildRecord:ht2}}var Et2={name:"@brains/topics",version:"0.2.0-alpha.196",description:"Extract and manage topics from conversations",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/content-formatters":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var ls$=new rV,is$=W.looseObject({status:W.unknown().optional()});class Tt2 extends c6{entityType=bw;schema=wo;adapter=ls$;unregisterAtprotoProjection;sourceBatch=new mLA;constructor(A={}){super(Cy,Et2,A,Bt2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:Kt2,"merge-synthesis":Ut2,"topic-list":Gt2,"topic-detail":Dt2}}getDataSources(){return[new yLA(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:CLA,targetType:bw,job:{type:Yt2,handler:kt2({context:A,logger:this.logger,config:this.config,extractAllTopics:()=>this.extractAllTopics(A),rebuildAllTopics:()=>this.rebuildAllTopics(A),sourceBatch:this.sourceBatch,isEntityPublished:(Q)=>this.isEntityPublished(Q)})},initialSync:{shouldEnqueue:async()=>!await OC(A,bw,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Ot2()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let $=Q.entity;if(!$)return null;if(!this.shouldProcessEntityType($.entityType,A.entityService))return null;if(!this.isEntityPublished($))return null;if(!Qk($.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:$.id,entityType:$.entityType,contentHash:$.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:kO0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:Wt2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Cy}})}}]}async onRegister(A){A.insights.register("topic-distribution",Vt2()),Jt2({context:A,pluginId:this.id}),Ct2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=D9.getInstance().register(cLA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(CLA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===bw)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=is$.safeParse(A.metadata),$=Q.success?Q.data.status:void 0;if($===void 0||$===null)return!0;if(typeof $!=="string")return!1;return this.config.extractableStatuses.includes($)}async extractAllTopics(A){await ft2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await xt2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function hO0(A={}){return new Tt2(A)}zA();h0();zA();var pLA=W.enum(["linkedin"]),yt2=W.enum(["linkedin"]),lLA=W.enum(["generating","draft","queued","published","failed"]),gt2=W.enum(["generating","draft","queued","published","failed"]),St2=W.enum(["post","deck"]),ds$=W.enum(["post","deck"]),mt2=W.object({id:W.string().min(1).describe("Document entity ID")}),ns$=W.object({id:W.string().min(1)}),sV=W.object({title:W.string().describe("Short descriptive title (3-6 words) for file naming"),platform:pLA.describe("Target platform"),status:lLA,coverImageId:W.string().optional().describe("Image entity ID for post image"),documents:W.array(mt2).optional().describe("Document attachments for publishing"),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional().describe("ID from platform after publishing"),sourceEntityId:W.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:St2.optional().describe("Source entity type (post, deck)")}),ut2=sV.extend({platform:pLA.optional(),status:lLA.optional()}),rs$=sV.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:W.string().describe("URL-friendly identifier: {platform}-{title}"),error:W.string().optional()}),os$=W.object({title:W.string(),platform:yt2,status:gt2,publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),ss$=W.object({title:W.string(),platform:yt2,status:gt2,coverImageId:W.string().optional(),documents:W.array(ns$).optional(),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:ds$.optional()}),Gx=U6.extend({entityType:W.literal("social-post"),metadata:os$}),EO0=Gx.extend({frontmatter:ss$,body:W.string()}),as$=EO0.extend({url:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});zA();p2();class iLA extends zQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:Gx,frontmatterSchema:sV,supportsCoverImage:!0})}toMarkdown(A){let Q,$={};try{$=this.parseFrontMatter(A.content,sV),Q=this.extractBody(A.content)}catch{Q=A.content}let w={...$,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,ut2),$=Q.platform??"linkedin",w=Q.status??"draft",B=`${$}-${O1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:$,status:w,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,sV)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let $={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",$),metadata:{title:A.title,slug:`linkedin-${O1(A.title)}`,platform:"linkedin",status:"generating"}}}}var oY=new iLA;zA();zA();h0();var ts$=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),platform:W.enum(["linkedin"]).optional(),status:W.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:W.boolean().optional(),nextInQueue:W.boolean().optional()}),es$=W.looseObject({entityType:W.string().optional(),query:ts$.optional()});function ct2(A){let Q=MQ(A.content,sV);return EO0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class TO0 extends n7{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=es$.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return ct2(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,$){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:$.baseUrl}}async fetch(A,Q,$){let{query:w}=this.parseQuery(A),B=$.entityService;if(w.nextInQueue)return this.fetchNextInQueue(Q,B);if(w.id){let{item:U}=await this.fetchDetail(w.id,B);return Q.parse(this.buildDetailResult(U,null))}let X={};if(w.platform)X.platform=w.platform;if(w.status)X.status=w.status;let Y=Object.keys(X).length>0,Z=w.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:H,pagination:K}=await this.fetchList(w,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(H,K,w))}async fetchNextInQueue(A,Q){let w=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],B=w?ct2(w):null;return A.parse({post:B})}}h0();var pt2=W.object({accessToken:W.string().optional(),refreshToken:W.string().optional(),organizationId:W.string().optional(),apiVersion:W.string().regex(/^\d{6}$/).optional()}),dLA=W.object({linkedin:pt2.optional(),publishInterval:W.number().default(3600000),enabled:W.boolean().default(!0),defaultPrompt:W.string().default("Create an engaging social media post that drives engagement"),maxRetries:W.number().default(3),autoGenerateOnBlogPublish:W.boolean().default(!1)});zA();p2();h0();Uw();rLA();import{jsxDEV as L7,Fragment as $a$}from"preact/jsx-dev-runtime";function Aa$(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Qa$(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var gO0=({posts:A,pageTitle:Q,pagination:$,baseUrl:w="/social-posts"})=>{let B=Q??"Social Posts",X=$?.totalItems??A.length,Y=`Browse all ${X} social ${X===1?"post":"posts"}`;return L7($a$,{children:[L7(E6,{title:B,description:Y},void 0,!1,void 0,this),L7("div",{className:"social-post-list bg-theme",children:L7("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[L7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?L7("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):L7("ul",{className:"space-y-6",children:A.map((Z)=>L7("li",{children:L7(v8,{href:Z.url,variant:"horizontal",children:L7("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&L7("img",{src:Z.coverImageUrl,alt:Z.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),L7("div",{className:"flex-1 min-w-0",children:[L7("div",{className:"flex items-start justify-between gap-4 mb-2",children:[L7("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),L7("time",{className:"text-sm text-theme-muted shrink-0",children:Qa$(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),L7("div",{className:"flex items-center gap-2 mb-3",children:[L7(sK,{status:Z.frontmatter.status},void 0,!1,void 0,this),L7("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),L7("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),L7("p",{className:"text-theme leading-relaxed",children:Aa$(Z.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)},Z.id,!1,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&L7(Ub,{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)};import{jsxDEV as I7,Fragment as wa$}from"preact/jsx-dev-runtime";function lt2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var SO0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,$=A.body.slice(0,160),w=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return I7(wa$,{children:[I7(E6,{title:Q,description:$},void 0,!1,void 0,this),I7("section",{className:"social-post-detail",children:I7("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:I7("div",{className:"max-w-3xl mx-auto",children:[I7(yL,{items:w},void 0,!1,void 0,this),I7("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),I7("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[I7(sK,{status:A.frontmatter.status},void 0,!1,void 0,this),I7("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),I7("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&&I7(Hb,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),I7(v8,{className:"p-8 mb-8",children:I7("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),I7("div",{className:"space-y-4 text-sm text-theme-muted",children:[I7("div",{children:[I7("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",lt2(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&I7("div",{children:[I7("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",lt2(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&I7("div",{children:I7("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 u90(A){return`social-media:${A}`}var Ba$=W.union([W.boolean(),W.object({generate:W.boolean().optional(),prompt:W.string().optional()})]),oLA=W.object({prompt:W.string().optional(),platform:W.enum(["linkedin"]).optional(),sourceEntityType:W.enum(["post","deck"]).optional(),sourceEntityId:W.string().optional(),title:W.string().optional().describe("Required when content is provided directly"),content:W.string().optional(),addToQueue:W.boolean().optional(),generateImage:W.boolean().optional().describe("Auto-generate cover image for post"),coverImage:Ba$.optional().describe("Generic cover image generation request")}),Xa$=xU.extend({slug:W.string().optional()});class Ty extends yZ{constructor(A,Q){super(A,Q,{schema:oLA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let $=A.platform??"linkedin",w=A.addToQueue??!1,{prompt:B,sourceEntityType:X,sourceEntityId:Y}=A,{content:Z,title:H}=A;if(Z&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let L=await this.context.ai.generate({prompt:Z,templateName:u90($)});H=L.title,Z=L.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let L=await this.context.entityService.getEntity({entityType:X,id:Y});if(!L)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let j=W.looseObject({slug:W.string()}).safeParse(L.metadata),b=j.success?j.data.slug:Y,f=await this.context.ai.generate({prompt:`Create an engaging ${$} post to promote this ${X}:
8141
8141
 
8142
8142
  Source: ${X}/${b}
8143
8143
 
8144
8144
  ${L.content}`,templateName:u90($)});H=f.title,Z=f.content,await this.reportProgress(Q,{progress:50,message:"Social post generated from source"})}else if(B){await this.reportProgress(Q,{progress:10,message:"Generating social post with AI"});let L=await this.context.ai.generate({prompt:B,templateName:u90($)});H=L.title,Z=L.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!Z||!H)this.failEarly("Content or title was not generated");let U={title:H,platform:$,status:w?"queued":"draft",...Y&&{sourceEntityId:Y},...X&&{sourceEntityType:X}},G=oY.createPostContent(U,Z),q=oY.fromMarkdown(G).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let J=await x3({entityType:"social-post",title:H,deriveId:(L)=>`${$}-${O1(L)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),F=G;if(J!==H){q.title=J,q.slug=`${$}-${O1(J)}`;let L={...U,title:J};F=oY.createPostContent(L,Z)}return{id:q.slug,content:F,metadata:q,title:J,resultExtras:{slug:q.slug},createOptions:{deduplicateId:!0}}}async onGenerationFailure(A,Q){await this.context.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:Q}})}async afterCreate(A,Q,$,w){if(A.generateImage){await this.reportProgress($,{progress:90,message:"Queueing image generation"});let B=w.title??"Social Post";await this.context.jobs.enqueue({type:"image:image-generate",data:{prompt:`Social media graphic for: ${B}`,title:`${B} Image`,aspectRatio:"16:9",targetEntityType:"social-post",targetEntityId:Q},toolContext:{interfaceType:"job",userId:"system"}})}await this.context.messaging.send({type:"generate:report:success",payload:{entityType:"social-post",entityId:Q}})}summarizeDataForLog(A){return{platform:A.platform??"linkedin",hasPrompt:!!A.prompt,sourceEntityType:A.sourceEntityType,addToQueue:A.addToQueue??!1,generateImage:A.generateImage??!1,coverImage:!!A.coverImage}}}h0();var it2=200,dt2="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function c90(A){if(A.length<=it2)return A;return`${A.slice(0,it2)}\u2026 (truncated, ${A.length} bytes)`}var Ya$=W.looseObject({sub:W.string()}),Za$=W.looseObject({id:W.string()}),Wa$=W.looseObject({value:W.looseObject({asset:W.string(),uploadMechanism:W.looseObject({[dt2]:W.looseObject({uploadUrl:W.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[dt2].uploadUrl,assetUrn:A.value.asset})),Ha$=W.looseObject({value:W.looseObject({uploadUrl:W.url(),document:W.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function Ka$(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function Ua$(A){let Q=Wa$.safeParse(A);return Q.success?Q.data:null}function Ga$(A){let Q=Ha$.safeParse(A);return Q.success?Q.data:null}var Da$="202604";class sLA{config;logger;name="linkedin";apiBaseUrl="https://api.linkedin.com/v2";restApiBaseUrl="https://api.linkedin.com/rest";fetch;cachedUserId=null;constructor(A,Q,$={}){this.config=A,this.logger=Q,this.fetch=$.fetch??globalThis.fetch.bind(globalThis)}async publish(A,Q,$,w){if(!this.config.accessToken)throw Error("LinkedIn access token not configured");let B=await this.getAuthor(),X=w?.[0];if(w&&w.length>1)this.logger.warn("LinkedIn document publishing supports one PDF",{count:w.length});let Y=null;if(X){let G=await this.uploadDocument(B,X);return this.publishDocumentPost(B,A,G,X.filename)}else if($){let G=await this.uploadImage(B,$);if(G)Y={category:"IMAGE",urn:G}}let Z={shareCommentary:{text:A},shareMediaCategory:Y?.category??"NONE",...Y&&{media:[Ka$(Y)]}},H=await this.fetch(`${this.apiBaseUrl}/ugcPosts`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({author:B,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":Z},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!H.ok){let G=c90(await H.text());throw this.logger.error("LinkedIn API error",{status:H.status,error:G}),Error(`LinkedIn API error: ${H.status} - ${G}`)}let K=H.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:K,mediaCategory:Y?.category??"NONE"});let U={id:K};if(K)U.url=`https://www.linkedin.com/feed/update/${K}`;return U}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??Da$,"X-Restli-Protocol-Version":"2.0.0"}}async uploadImage(A,Q){try{let $=await this.fetch(`${this.apiBaseUrl}/assets?action=registerUpload`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({registerUploadRequest:{recipes:["urn:li:digitalmediaRecipe:feedshare-image"],owner:A,serviceRelationships:[{relationshipType:"OWNER",identifier:"urn:li:userGeneratedContent"}]}})});if(!$.ok){let Z=c90(await $.text());return this.logger.warn("LinkedIn image upload registration failed",{status:$.status,error:Z}),null}let w=Ua$(await $.json());if(!w)return this.logger.warn("LinkedIn image upload registration was malformed"),null;let{uploadUrl:B,assetUrn:X}=w,Y=await this.fetch(B,{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:X}),X}catch($){return this.logger.warn("LinkedIn image upload error",{error:$}),null}}async uploadDocument(A,Q){let $=await this.fetch(`${this.restApiBaseUrl}/documents?action=initializeUpload`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({initializeUploadRequest:{owner:A}})});if(!$.ok){let X=c90(await $.text());throw Error(`LinkedIn document upload initialization failed: ${$.status} - ${X}`)}let w=Ga$(await $.json());if(!w)throw Error("LinkedIn document upload initialization was malformed");let B=await this.fetch(w.uploadUrl,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!B.ok)throw Error(`LinkedIn document binary upload failed: ${B.status}`);return this.logger.info("LinkedIn document uploaded",{documentUrn:w.documentUrn,filename:Q.filename}),w.documentUrn}async publishDocumentPost(A,Q,$,w){let B=await this.fetch(`${this.restApiBaseUrl}/posts`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({author:A,commentary:Q,visibility:"PUBLIC",distribution:{feedDistribution:"MAIN_FEED",targetEntities:[],thirdPartyDistributionChannels:[]},content:{media:{id:$,title:w}},lifecycleState:"PUBLISHED",isReshareDisabledByAuthor:!1})});if(!B.ok){let Z=c90(await B.text());throw this.logger.error("LinkedIn document post API error",{status:B.status,error:Z}),Error(`LinkedIn document post API error: ${B.status} - ${Z}`)}let X=B.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn document post created",{postId:X,documentUrn:$});let Y={id:X};if(X)Y.url=`https://www.linkedin.com/feed/update/${X}`;return Y}async validateCredentials(){if(!this.config.accessToken)return!1;try{if(this.config.organizationId)return(await this.fetch(`${this.apiBaseUrl}/organizations/${this.config.organizationId}`,{headers:{Authorization:`Bearer ${this.config.accessToken}`}})).ok;return await this.getUserId(),!0}catch{return!1}}async getAuthor(){if(this.config.organizationId)return`urn:li:organization:${this.config.organizationId}`;return this.getUserId()}async getUserId(){if(this.cachedUserId)return this.cachedUserId;if(!this.config.accessToken)throw Error("LinkedIn access token not configured");try{let $=await this.fetch("https://api.linkedin.com/v2/userinfo",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if($.ok){let w=Ya$.safeParse(await $.json());if(w.success)return this.cachedUserId=`urn:li:person:${w.data.sub}`,this.cachedUserId}}catch{}let A=await this.fetch("https://api.linkedin.com/v2/me",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(!A.ok){let $=c90(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${$}`)}let Q=Za$.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function aLA(A,Q,$={}){return new sLA(A,Q,$)}h0();D5();rLA();var qa$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),za$=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),nt2=W.enum(["linkedin"]),rt2=W.enum(["generating","draft","queued","published","failed"]),Va$=W.enum(["post","deck"]),Ja$=W.object({id:W.string().min(1)}),Fa$=W.object({title:W.string(),platform:nt2,status:rt2,coverImageId:W.string().optional(),documents:W.array(Ja$).optional(),publishedAt:W.string().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:Va$.optional()}),La$=W.object({title:W.string(),platform:nt2,status:rt2,publishedAt:W.string().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),ot2=W.object({id:W.string(),entityType:W.literal("social-post"),content:W.string(),created:W.string(),updated:W.string(),visibility:za$,metadata:La$,contentHash:W.string(),frontmatter:Fa$,body:W.string(),url:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),typeLabel:W.string().optional(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Ia$=W.object({posts:W.array(ot2),totalCount:W.number().optional(),pagination:qa$.nullable(),baseUrl:W.string().optional()}),Na$=W.object({post:ot2});function st2(){return{linkedin:yO0,"social-post-list":G2({name:"social-post-list",description:"Social post list page template",schema:Ia$,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:gO0}}),"social-post-detail":G2({name:"social-post-detail",description:"Individual social post template",schema:Na$,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:SO0}})}}h0();var _a$=W.object({prompt:W.string().optional(),content:W.string().optional(),platform:W.enum(["linkedin"]).default("linkedin")}),Pa$=W.object({prompt:W.string().optional(),content:W.string().optional(),title:W.string().optional(),platform:W.enum(["linkedin"]).optional()});function at2(A){A.eval.registerHandler("generation",async(Q)=>{let $=_a$.parse(Q),w=$.content?`Create an engaging LinkedIn post to share this content:
8145
8145
 
8146
- ${$.content}`:$.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${$.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let $=Pa$.parse(Q),w=[],B=EW.from(async(K)=>{let U={progress:K.progress};if(K.message!==void 0)U.message=K.message;w.push(U)});if(!B)throw Error("Failed to create progress reporter");let Y=await new Ty(A.logger,A).process($,`eval-${Date.now()}`,B),Z=!1,H;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!K,H=K?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:H,progressSteps:w}})}zA();class p90{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:$}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:$});try{let w=await this.entityService.getEntity({entityType:"social-post",id:$});if(!w){await this.reportFailure(Q,$,`Post not found: ${$}`);return}let B=w;if(B.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:$});return}let X=B.metadata.platform,Y=this.providers.get(X);if(!Y){await this.reportFailure(Q,$,`No provider configured for platform: ${X}`);return}let Z=MQ(B.content,sV),H;if(Z.metadata.coverImageId)H=await this.fetchImageData(Z.metadata.coverImageId);let K=Z.metadata.documents??[],U=await this.fetchDocumentData(K);try{if(K.length>0&&U.length===0)throw Error(`Refusing to publish: ${K.length} document(s) referenced but none could be fetched`);let G=K.length===0?await this.resolveSourceAttachment(Z.metadata):[],D=U.length>0?U:G,q=D.length?await Y.publish(Z.content,B.metadata,H,D):await Y.publish(Z.content,B.metadata,H),J=new Date().toISOString(),F=q.id||void 0,L={...Z.metadata,status:"published",publishedAt:J,...F&&{platformPostId:F}},_=oY.createPostContent(L,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:J,platformPostId:F}}}),await this.reportSuccess(Q,$,q.id),this.logger.info(`Post published successfully: ${$}`,{platform:X,platformPostId:F})}catch(G){let D=G instanceof Error?G.message:String(G),q={...Z.metadata,status:"failed"},J=oY.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:J,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,$,D),this.logger.error(`Post publish failed: ${$}`,{platform:X,error:D})}}catch(w){let B=eA(w);this.logger.error("Unexpected error in publish handler",{entityId:$,error:B}),await this.reportFailure(Q,$,B)}}async reportSuccess(A,Q,$){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:$}}})}async reportFailure(A,Q,$){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:$}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let $ of A){let w=await this.fetchSingleDocumentData($.id);if(w)Q.push(w)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let $=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!$?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let w=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from($[1],"base64"),mimeType:"application/pdf",filename:w}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let w=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!w?.[1]||!w[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let B=w[1],X=w[2];return{data:Buffer.from(X,"base64"),mimeType:B}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function tt2(A,Q,$){if(Q.size===0){$.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let w=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:w,config:{publishResultIdField:"platformPostId"}}}),$.info("Registered social-post with publish-pipeline"),{success:!0}})}function et2(A,Q,$){let w=new p90({sendMessage:A.messaging.send,logger:$.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async(B)=>{return await w.handle(B.payload),{success:!0}}),$.debug("Subscribed to publish:execute messages")}function Ae2(A,Q){A.messaging.subscribe("entity:updated",async($)=>{let{entityType:w,entityId:B,entity:X}=$.payload;if(w!=="post")return{success:!0};if(X.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:B}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${B}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:w,sourceEntityId:B,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${B}`),{success:!0}}catch(Z){let H=eA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Qe2(A,Q){A.messaging.subscribe("social:auto-generate",async($)=>{let{sourceEntityType:w,sourceEntityId:B,platform:X}=$.payload;try{let Y=await A.jobs.enqueue({type:`${oY.entityType}:generation`,data:{sourceEntityType:w,sourceEntityId:B,platform:X,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${w}/${B}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let Z=eA(Y);return Q.error(`Failed to enqueue social post generation for ${B}:`,{error:Z}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function $e2(A,Q){A.messaging.subscribe("generate:execute",async($)=>{let{entityType:w}=$.payload;if(w!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let B=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if(B.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let X=null;for(let Z of B)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Z.id}},limit:1}})).length===0){X=Z;break}if(!X)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${oY.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:X.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:X.id}),{success:!0}}catch(B){let X=eA(B);return Q.error("Failed to handle generate:execute:",{error:X}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:X}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function we2({entity:A,config:Q}){let $=Gx.parse(A),w=oY.parsePostFrontmatter($),B=oY.getPostContent($);return{$type:"ai.rizom.brain.socialPost",title:w.title,platform:w.platform,body:B,format:"text/markdown",status:w.status,...w.publishedAt&&{publishedAt:w.publishedAt},...w.platformPostId&&{platformPostId:w.platformPostId},...w.sourceEntityType&&{sourceLocalEntityType:w.sourceEntityType},...w.sourceEntityId&&{sourceLocalEntityId:w.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function tLA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:i8["ai.rizom.brain.socialPost"],validate:!1,buildRecord:we2}}var Be2={name:"@brains/social-media",version:"0.2.0-alpha.195",description:"Multi-provider social media posting with queue-based publishing",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class eLA extends c6{entityType=oY.entityType;schema=Gx;adapter=oY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",Be2,A,dLA)}createGenerationHandler(A){return new Ty(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return st2()}getDataSources(){return[new TO0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),tt2(A,this.providers,this.logger),et2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Ae2(A,this.logger),Qe2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");$e2(A,this.logger),at2(A),this.unregisterAtprotoProjection=D9.getInstance().register(tLA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=aLA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function l90(A={}){return new eLA(A)}h0();var ja$=W.enum(["draft","queued","published","failed"]),Xe2=W.object({status:ja$.default("draft"),queueOrder:W.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:W.string().datetime().optional()});class AIA{name="internal";async publish(A,Q){return{id:"internal"}}}var xb={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},sY={REGISTER:"publish:register",QUEUE:"publish:queue",DIRECT:"publish:direct",REMOVE:"publish:remove",REORDER:"publish:reorder",LIST:"publish:list",REPORT_SUCCESS:"publish:report:success",REPORT_FAILURE:"publish:report:failure",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},Dx={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"},Ye2={REGISTER:"publish-assets:register"};h0();var Ma$=W.enum(["provider"]),Ze2=W.object({executionMode:Ma$.optional(),publishResultIdField:W.string().min(1).optional(),publishTimestampField:W.string().min(1).optional(),enabled:W.boolean().optional()}).strict();var ka$=W.object({skipIfDraftExists:W.boolean().optional(),minSourceEntities:W.number().optional(),maxUnpublishedDrafts:W.number().optional(),sourceEntityType:W.string().optional()}),We2=W.object({entitySchedules:W.record(W.string(),W.string()).optional(),generationSchedules:W.record(W.string(),W.string()).optional(),generationConditions:W.record(W.string(),ka$).optional()});class YI{static instance=null;queues=new Map;static getInstance(){return YI.instance??=new YI,YI.instance}static resetInstance(){YI.instance=null}static createFresh(){return new YI}constructor(){}async add(A,Q,$=xb){let w=this.getOrCreateQueue(A),B=w.find((Z)=>Z.entityId===Q);if(B)return{position:B.position};let X=w.length+1,Y={entityId:Q,entityType:A,position:X,queuedAt:new Date().toISOString(),authContext:{...$}};return w.push(Y),{position:X}}async remove(A,Q){let $=this.queues.get(A);if(!$)return;let w=$.findIndex((B)=>B.entityId===Q);if(w===-1)return;$.splice(w,1),this.recalculatePositions($)}async reorder(A,Q,$){let w=this.queues.get(A);if(!w)return;let B=w.findIndex((Z)=>Z.entityId===Q);if(B===-1)return;let[X]=w.splice(B,1);if(!X)return;let Y=Math.max(0,Math.min($-1,w.length));w.splice(Y,0,X),this.recalculatePositions(w)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let $=Q[0];if(!$)continue;if(!A||$.queuedAt<A.queuedAt)A=$}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let $=Q.shift()??null;if($)this.recalculatePositions(Q);return $}replace(A){this.queues.clear();let Q=[...A].sort(($,w)=>$.entityType.localeCompare(w.entityType)||$.position-w.position);for(let $ of Q)this.getOrCreateQueue($.entityType).push({...$,authContext:{...$.authContext}});for(let $ of this.queues.values())this.recalculatePositions($)}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,$]of this.queues.entries())if($.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,$)=>{Q.position=$+1})}}class ZI{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new AIA;static getInstance(){return ZI.instance??=new ZI,ZI.instance}static resetInstance(){ZI.instance=null}static createFresh(){return new ZI}constructor(){}register(A,Q,$){let w=this.providers.get(A);if(w&&w.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,$?.executionMode??"provider"),$?.publishResultIdField)this.publishResultIdFields.set(A,$.publishResultIdField);else this.publishResultIdFields.delete(A);if($?.publishTimestampField)this.publishTimestampFields.set(A,$.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function He2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await Oa$(A,Q)}async function Oa$(A,Q){if(!Q.publishExecutor)return;try{let $=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in $){let w={entityType:A.entityType,entityId:A.entityId,error:$.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:sY.FAILED,payload:w,sender:"publish-service",broadcast:!0});Q.onFailed?.(w);return}QIA(A.entityType,A.entityId,$.result,Q)}catch($){let w=eA($);Q.retryTracker.recordFailure(A.entityId,w);let B=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:w,retryCount:B?.retryCount??1,willRetry:!1})}}function QIA(A,Q,$,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send({type:sY.COMPLETED,payload:{entityType:A,entityId:Q,result:$},sender:"publish-service",broadcast:!0});w.onPublish?.({entityType:A,entityId:Q,result:$})}function Ke2(A,Q,$,w){w.retryTracker.recordFailure(Q,$);let B=w.retryTracker.getRetryInfo(Q),X={entityType:A,entityId:Q,error:$,retryCount:B?.retryCount??1,willRetry:!1};if(w.messageBus)w.messageBus.send({type:sY.FAILED,payload:X,sender:"publish-service",broadcast:!0});w.onFailed?.(X)}async function Ue2(A,Q){let $=Q.generationConditions[A];if($&&Q.onCheckGenerationConditions){let B=await Q.onCheckGenerationConditions(A,$);if(!B.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:Dx.SKIPPED,payload:{entityType:A,reason:B.reason??"Conditions not met"},sender:"content-pipeline"});return}}let w={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:Dx.EXECUTE,payload:w,sender:"content-pipeline"});Q.onGenerate?.(w)}function Ge2(A,Q,$){if($)$.send({type:Dx.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function De2(A,Q,$){if($)$.send({type:Dx.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var fa$=1000;class $IA{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let $=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,$)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(fa$,()=>this.processUnscheduledTypes())}async stop(){let A=Array.from(this.publishJobs.values());if(this.publishJobs.clear(),this.immediateIntervalJob)A.push(this.immediateIntervalJob),this.immediateIntervalJob=null;await Promise.all(A.map((Q)=>Q.stop()))}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let $=await this.deps.config.queueManager.getNext(Q);if($){await this.processEntry($);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await He2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class wIA{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let $=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,$)}}async stop(){let A=Array.from(this.generationJobs.values());this.generationJobs.clear(),await Promise.all(A.map((Q)=>Q.stop()))}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await Ue2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}class WI{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return WI.instance??=new WI(A),WI.instance}static async resetInstance(){let A=WI.instance;if(WI.instance=null,A)await A.stop()}static createFresh(A){return new WI(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new $IA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new wIA({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}stop(){if(this.stopPromise)return this.stopPromise;return this.running=!1,this.stopPromise=Promise.all([this.publishRunner.stop(),this.generationRunner.stop()]).then(()=>{return}),this.stopPromise}isRunning(){return this.running}completePublish(A,Q,$){QIA(A,Q,$,this.publishDeps)}failPublish(A,Q,$){Ke2(A,Q,$,this.publishDeps)}completeGeneration(A,Q){Ge2(A,Q,this.config.messageBus)}failGeneration(A,Q){De2(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,$){try{this.config.backend.validateCron(Q)}catch(w){throw Error(`Invalid ${$} cron expression for ${A}: "${Q}" - ${eA(w)}`,{cause:w})}}}class HI{static instance=null;retries=new Map;static getInstance(){return HI.instance??=new HI,HI.instance}static resetInstance(){HI.instance=null}static createFresh(){return new HI}constructor(){}recordFailure(A,Q){let w=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:w,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}LAA();h0();var qe2=W.union([W.string().min(1),W.object({location:W.enum(["metadata","frontmatter"]),field:W.string().min(1)})]),mO0=W.object({entityType:W.string().min(1),attachmentType:W.string().min(1),mediaEntityType:W.enum(["image","document"]),targetEntityField:qe2.optional(),requiredWhen:W.object({status:W.string().min(1).optional(),visibility:W.string().min(1).optional()}).optional(),autoGenerate:W.boolean().optional(),requiredForPublish:W.boolean().optional(),jobType:W.string().min(1).optional()});function BIA(A){return`${A.entityType}:${A.attachmentType}`}class KI{static instance=null;definitions=new Map;static getInstance(){return KI.instance??=new KI,KI.instance}static resetInstance(){KI.instance=null}static createFresh(){return new KI}constructor(){}register(A){let Q=mO0.parse(A),$=BIA(Q);return this.definitions.set($,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(BIA({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter(($)=>$.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(BIA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}u4();p2();class uO0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let $=this.deps.registry.list(A.entityType).filter((B)=>B.autoGenerate===!0).filter((B)=>!Q.attachmentType||B.attachmentType===Q.attachmentType),w={checked:$.length,enqueued:0,skipped:0};for(let B of $)if(await this.ensureDefinition(A,B))w.enqueued+=1;else w.skipped+=1;return w}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let $=this.resolveJobType(Q);if(!$)return!1;let w=this.getPredictedMediaId(A,Q),B=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:$,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:w,dedupKey:B,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:B}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:$}),!0}matchesPolicy(A,Q){let{requiredWhen:$}=Q;if(!$)return!0;if($.status&&A.metadata.status!==$.status)return!1;if($.visibility&&A.visibility!==$.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return XIA(A.metadata[Q]);if(Q.location==="metadata")return XIA(A.metadata[Q.field]);let{frontmatter:$}=t8(A.content);return XIA($[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let $=Q.attachmentType==="og-image"?"og":Q.attachmentType;return O1(`${$}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function XIA(A){return typeof A==="string"?A.length>0:A!==void 0}zA();h0();var Ra$=W.object({id:W.string().min(1)});async function Ve2(A,Q){let{bodyContent:$,coverImageId:w,documents:B,sourceEntityType:X,sourceEntityId:Y}=va$(Q.content),Z=w?await Ea$(A,w):void 0,H;if(B&&B.length>0){let U=await Ta$(A,B);if(U.length>0)H=U}H??=await ha$(A,X,Y);let K={bodyContent:$};if(Z)K.imageData=Z;if(H&&H.length>0)K.documentData=H;return K}function va$(A){try{let Q=MQ(A,W.record(W.string(),W.unknown())),$=Q.metadata.coverImageId,w=typeof $==="string"?$:void 0,B=Ca$(Q.metadata.documents),X=ze2(Q.metadata.sourceEntityType),Y=ze2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...w&&{coverImageId:w},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function Ca$(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let $=Ra$.safeParse(Q);return $.success?[$.data]:[]})}function ze2(A){return typeof A==="string"&&A.length>0?A:void 0}async function ha$(A,Q,$){if(!Q||!$)return;let w=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:$,attachmentType:"carousel"});return w?[w]:void 0}async function Ea$(A,Q){let $=await A.entityService.getEntity({entityType:"image",id:Q});if(!$?.content)return;let w=Je2($.content);if(!w?.mimeType.startsWith("image/"))return;return{data:w.data,mimeType:w.mimeType}}async function Ta$(A,Q){return(await Promise.all(Q.map((w)=>ya$(A,w)))).filter((w)=>w!==void 0)}async function ya$(A,Q){let $=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!$?.content)return;let w=Je2($.content);if(w?.mimeType!=="application/pdf")return;return{type:"document",data:w.data,mimeType:"application/pdf",filename:ga$($,Q.id)}}function Je2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function ga$(A,Q){let $=A.metadata.filename;return typeof $==="string"&&$.length>0?$:`${Q}.pdf`}u4();var Sa$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function YIA(A,Q,$,w={}){let B=w.publishTimestampField??"publishedAt",X=Q.metadata[B],Y=w.publishedAt??(typeof X==="string"?X:void 0)??new Date().toISOString(),Z={...Q.metadata,status:"published",[B]:Y,platformId:$.id,...ma$($.id,w.publishResultIdField)},H={...Q,content:Fe2(Q.content,Y,$.id,w.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function Fe2(A,Q,$,w,B="publishedAt"){if(!Sa$.test(A))return A;let X=hX(hX(A,"status","published"),B,Q);if(!$||!w)return X;return hX(X,w,$)}function ma$(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Zo{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:$,slug:w}=A;if(!$&&!w)return{error:"Either 'id' or 'slug' must be provided"};let B=await this.findPublishableEntity(Q,$,w);if(!B)return{error:`Entity not found: ${Q}:${$??w}`};if(B.visibility!=="public")return{error:`Cannot publish ${Q}:${B.id} to a public provider because visibility is ${B.visibility}`};if(B.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:B}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:$}=Q,{entityType:w}=A,B=this.deps.providerRegistry.get(w),{bodyContent:X,imageData:Y,documentData:Z}=await Ve2(this.deps.context,$),H=await B.publish(X,$.metadata,Y,Z),K=this.deps.providerRegistry.getPublishResultIdField(w),U=this.deps.providerRegistry.getPublishTimestampField(w),G=await YIA(this.deps.context,$,H,{...K?{publishResultIdField:K}:{},...U?{publishTimestampField:U}:{}});return await this.runPublishAssetPreflight(G),{entity:G,result:H}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,$){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!$)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:$}},limit:1}}))[0]??null}}zA();h0();var ZIA=W.object({action:W.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:W.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:W.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:W.number().optional().describe("New position for reorder action (1-based)")}),WIA=W.object({position:W.number(),entityType:W.string(),entityId:W.string(),queuedAt:W.string()}),ua$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({queue:W.array(WIA).optional(),entityType:W.string().optional(),entityId:W.string().optional(),position:W.number().optional()}).optional()}),ca$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),HIA=W.union([ua$,ca$]);function cO0(A,Q,$,w){let B=w??$;return{...e8(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",ZIA,async(Y,Z)=>{let{action:H,entityType:K,entityId:U,position:G}=Y;switch(H){case"list":return pa$($,K);case"add":return la$(A,B,K,U,Z);case"remove":return ia$(A,B,K,U,Z);case"reorder":return da$(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${H}`}}},{sideEffects:"writes"}),outputSchema:HIA}}async function pa$(A,Q){let $=[];if(Q)$=await A.list(Q);else{let B=A.getRegisteredTypes();for(let X of B){let Y=await A.list(X);$.push(...Y)}$.sort((X,Y)=>new Date(X.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if($.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:$.map((B,X)=>({position:X+1,entityType:B.entityType,entityId:B.entityId,queuedAt:B.queuedAt}))},message:`${$.length} items in queue`}}async function la$(A,Q,$,w,B){let X=KIA("add",$,w);if(!X.success)return X.error;A.permissions.assertEntityActionAllowed(X.entityType,"publish",B??{});let Y=await Q.add(X.entityType,X.entityId,{...B,authorization:"user"});return{success:!0,data:{entityType:X.entityType,entityId:X.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function ia$(A,Q,$,w,B){let X=KIA("remove",$,w);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(X.entityType,"update",B??{}),await Q.remove(X.entityType,X.entityId),{success:!0,data:{entityType:X.entityType,entityId:X.entityId},message:"Removed from queue"}}async function da$(A,Q,$,w,B,X){let Y=KIA("reorder",$,w);if(!Y.success)return Y.error;let Z=na$(B);if(!Z.success)return Z.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",X??{}),await Q.reorder(Y.entityType,Y.entityId,Z.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:Z.position},message:`Moved to position ${Z.position}`}}function KIA(A,Q,$){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!$)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:$}}function na$(A){if(A===void 0)return{success:!1,error:{success:!1,error:"position is required for reorder action"}};if(A<1)return{success:!1,error:{success:!1,error:"position must be a positive number"}};return{success:!0,position:A}}h0();import{createHash as ra$}from"crypto";var UIA=W.object({entityType:W.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:W.string().optional().describe("Entity ID to publish"),slug:W.string().optional().describe("Entity slug to publish"),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),contentHash:W.string().optional(),expiresAt:W.string().datetime().optional()}),oa$=W.object({entityType:W.string(),id:W.string().optional(),slug:W.string().optional(),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),contentHash:W.string().optional(),expiresAt:W.string().datetime().optional()}),sa$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({entityType:W.string().optional(),entityId:W.string().optional(),platformId:W.string().optional(),url:W.string().optional()}).optional()}),aa$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),ta$=W.object({success:W.literal(!1).optional(),error:W.string().optional(),needsConfirmation:W.literal(!0),toolName:W.string(),summary:W.string(),preview:W.string().optional(),args:W.unknown()}),GIA=W.union([sa$,aa$,ta$]),ea$=900000;function Wo(A,Q,$,w){let B=w??new Zo({context:A,providerRegistry:$}),X=`${Q}_publish`;return{name:X,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:UIA.shape,outputSchema:GIA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=oa$.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((F)=>`${F.path.join(".")}: ${F.message}`).join(", ")}`};let K=H.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(F){return{success:!1,error:F instanceof Error?F.message:String(F)}}let q=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:J}=q;if(K.confirmed){let F=Qt$(X,K,J);if(F!==null)return F;let L;try{L=await B.publish({entityType:U,id:J.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in L)return{success:!1,error:L.error};let{entity:_,result:j}=L;return{success:!0,data:{entityType:U,entityId:_.id,platformId:j.id,url:j.url},message:`Published ${U}:${_.id}`}}return At$(X,K,J)}}}function At$(A,Q,$){let w=new Date(Date.now()+ea$).toISOString(),B=Le2(A,$,w),X=$t$($);return{needsConfirmation:!0,toolName:A,summary:`Publish "${X}"?`,preview:`This will publish ${$.entityType}:${$.id} to its registered public publish provider.`,args:{...Q,id:$.id,slug:void 0,confirmed:!0,confirmationToken:B,contentHash:$.contentHash,expiresAt:w}}}function Qt$(A,Q,$){let{confirmationToken:w,contentHash:B,expiresAt:X}=Q;if(!w||!X)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(X);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if(B&&B!==$.contentHash)return{success:!1,error:`Cannot publish ${$.entityType}:${$.id} because it changed after confirmation. Review it and try again.`};if(w!==Le2(A,$,X))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function Le2(A,Q,$){return ra$("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update($).digest("hex")}function $t$(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let $=A.metadata.subject;if(typeof $==="string"&&$.length>0)return $;let w=A.metadata.slug;if(typeof w==="string"&&w.length>0)return w;return A.id}zA();h0();var DIA=W.object({entityType:W.string().min(1).describe("Entity type to reconcile"),status:W.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:W.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),qIA=W.object({success:W.literal(!0),data:W.object({entityType:W.string(),assetType:W.string().optional(),checkedEntities:W.number(),checkedAssets:W.number(),enqueued:W.number(),skipped:W.number()}),message:W.string().optional()});function pO0(A,Q,$,w){return{...e8(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",DIA,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),$.list(X.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!X.assetType||D.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let H=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),K=0,U=0,G=0;for(let D of H){let q=await w.ensureForEntity(D,{...X.assetType&&{attachmentType:X.assetType}});K+=q.checked,U+=q.enqueued,G+=q.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:H.length,checkedAssets:K,enqueued:U,skipped:G},message:`Queued ${U} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:qIA}}zA();u4();h0();var wt$="content-pipeline.queue.v1",zIA=1024,Bt$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,Xt$=W.object({interfaceType:W.string().optional(),userId:W.string().optional(),userPermissionLevel:W.enum(["public","trusted","anchor"]).optional(),authorization:W.enum(["user","system"]).optional()}),Yt$=W.object({entityType:W.string(),entityId:W.string(),rank:W.number().int().positive(),queuedAt:W.string().datetime(),contentHashAtEnqueue:W.string(),authContext:Xt$,revision:W.number().int().positive()});class VIA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:wt$,schema:Yt$})}async add(A,Q,$=xb){return this.enqueue(A,Q,$)}async enqueue(A,Q,$=xb){return this.runExclusive(async()=>{let w=await this.requireEntity(A,Q);await this.persistStatus(w,"queued");let B=await this.queueManager.add(A,Q,$);if(!await this.store.get(jz(A,Q))){let Y=(await this.queueManager.list(A)).find((H)=>H.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set(jz(A,Q),{entityType:A,entityId:Q,rank:B.position*zIA,queuedAt:Y?.queuedAt??new Date().toISOString(),contentHashAtEnqueue:Z.contentHash,authContext:{...$},revision:1})}return B})}async remove(A,Q){await this.runExclusive(async()=>{let $=await this.requireEntity(A,Q);if($.metadata.status==="queued")await this.persistStatus($,"draft");await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async reorder(A,Q,$){await this.runExclusive(async()=>{await this.requireEntity(A,Q),await this.queueManager.reorder(A,Q,$),await this.persistCurrentOrder(A)})}async complete(A,Q){await this.runExclusive(async()=>{await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async fail(A,Q,$){await this.runExclusive(async()=>{let w=await this.context.entityService.getEntity({entityType:A,id:Q});if(w)await this.persistStatus(w,"failed",$);await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async reconcile(A){await this.runExclusive(async()=>{let Q=new Map;for(let H of A){let K=await this.context.entityService.listEntities({entityType:H,options:{filter:{metadata:{status:"queued"}}}});for(let U of K)Q.set(jz(H,U.id),U)}let $=await this.listStored();for(let H of $)if(!Q.has(jz(H.entityType,H.entityId)))await this.store.delete(jz(H.entityType,H.entityId));let w=(await this.listStored()).filter((H)=>Q.has(jz(H.entityType,H.entityId))),B=new Map;for(let H of w)B.set(H.entityType,Math.max(B.get(H.entityType)??0,H.rank));for(let[H,K]of Q){if(w.some((G)=>jz(G.entityType,G.entityId)===H))continue;let U=(B.get(K.entityType)??0)+zIA;B.set(K.entityType,U),await this.store.set(H,{entityType:K.entityType,entityId:K.id,rank:U,queuedAt:typeof K.updated==="string"?K.updated:new Date().toISOString(),contentHashAtEnqueue:K.contentHash,authContext:{...xb},revision:1})}let X=await this.listStored(),Y=new Map,Z=X.map((H)=>{let K=(Y.get(H.entityType)??0)+1;return Y.set(H.entityType,K),{entityType:H.entityType,entityId:H.entityId,position:K,queuedAt:H.queuedAt,authContext:{...H.authContext}}});this.queueManager.replace(Z)})}async listStored(A){return(await this.store.list()).map((Q)=>Q.value).filter((Q)=>!A||Q.entityType===A).sort((Q,$)=>Q.entityType.localeCompare($.entityType)||Q.rank-$.rank||Q.queuedAt.localeCompare($.queuedAt)||Q.entityId.localeCompare($.entityId))}async deleteStored(A,Q){return this.store.delete(jz(A,Q))}async persistCurrentOrder(A){let Q=new Map((await this.listStored(A)).map(($)=>[$.entityId,$]));for(let $ of await this.queueManager.list(A)){let w=Q.get($.entityId);if(!w)continue;let B=$.position*zIA;if(w.rank===B)continue;await this.store.set(jz(A,$.entityId),{...w,rank:B,revision:w.revision+1})}}async persistStatus(A,Q,$){let w={...A.metadata,status:Q};if($)w.error=$;else delete w.error;let B=Bt$.test(A.content)?hX(A.content,"status",Q):A.content;await this.context.entityService.updateEntity({entity:{...A,metadata:w,content:B}})}async requireEntity(A,Q){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Entity not found: ${A}:${Q}`);return $}runExclusive(A){let Q=this.mutationTail.then(A);return this.mutationTail=Q.then(()=>{return},()=>{return}),Q}}function jz(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function Ie2(A,Q){Zt$(A,Q),Wt$(A,Q),Ht$(A,Q),Kt$(A,Q)}function Zt$(A,Q){A.messaging.subscribe(sY.REGISTER,async($)=>Ut$(Q,$.payload)),A.messaging.subscribe(sY.QUEUE,async($)=>zt$(A,Q,$.payload)),A.messaging.subscribe(sY.DIRECT,async($)=>Vt$(A,Q,$.payload)),A.messaging.subscribe(sY.REMOVE,async($)=>Jt$(Q,$.payload)),A.messaging.subscribe(sY.REORDER,async($)=>Ft$(Q,$.payload)),A.messaging.subscribe(sY.LIST,async($)=>Lt$(A,Q,$.payload)),A.messaging.subscribe(sY.REPORT_SUCCESS,async($)=>It$(Q,$.payload)),A.messaging.subscribe(sY.REPORT_FAILURE,async($)=>Nt$(Q,$.payload)),A.messaging.subscribe(sY.COMPLETED,async($)=>{return await Q.publicationQueueService.complete($.payload.entityType,$.payload.entityId),{success:!0}}),A.messaging.subscribe(sY.FAILED,async($)=>{return await Q.publicationQueueService.fail($.payload.entityType,$.payload.entityId,$.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function Wt$(A,Q){A.messaging.subscribe(Dx.REPORT_SUCCESS,async($)=>_t$(Q,$.payload)),A.messaging.subscribe(Dx.REPORT_FAILURE,async($)=>Pt$(Q,$.payload)),Q.logger.debug("Subscribed to generation messages")}function Ht$(A,Q){A.messaging.subscribe(Ye2.REGISTER,async($)=>Gt$(Q,$.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Kt$(A,Q){let $=async(w)=>Dt$(A,Q,w.payload);A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function Ut$(A,Q){let{entityType:$,provider:w,config:B}=Q;try{let X=B?Ze2.safeParse(B):void 0;if(X&&!X.success)return A.logger.warn("Invalid publish provider config",{entityType:$,error:X.error.message}),{success:!1};if(w)A.providerRegistry.register($,w,X?.data),A.logger.info(`Registered provider for entity type: ${$}`,{providerName:w.name,executionMode:A.providerRegistry.getExecutionMode($)});return{success:!0}}catch(X){let Y=eA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Gt$(A,Q){let $=mO0.safeParse(Q);if(!$.success)return A.logger.warn("Invalid publish asset registration",{error:$.error.message}),{success:!1};return A.publishAssetRegistry.register($.data),A.logger.info("Registered publish asset",{entityType:$.data.entityType,attachmentType:$.data.attachmentType,mediaEntityType:$.data.mediaEntityType}),{success:!0}}async function Dt$(A,Q,$){try{if(Q.publishAssetRegistry.list($.entityType).length===0)return{success:!0};let w=$.entity??await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(!qt$(w))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(w),{success:!0}}catch(w){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:$.entityType,entityId:$.entityId,error:eA(w)}),{success:!1}}}function qt$(A){if(!A)return!1;let Q=Xe2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function zt$(A,Q,$){let{entityType:w,entityId:B}=$;try{let X=$.authContext??xb;A.permissions.assertEntityActionAllowed(w,"publish",X);let Y=await Q.publicationQueueService.enqueue(w,B,X);return await A.messaging.send({type:sY.QUEUED,payload:{entityType:w,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:w,position:Y.position}),{success:!0}}catch(X){let Y=eA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Vt$(A,Q,$){let{entityType:w,entityId:B}=$,X=$.authContext??xb;try{if(A.permissions.assertEntityActionAllowed(w,"publish",X),!Q.providerRegistry.has(w))return Q.scheduler.failPublish(w,B,`No publish provider registered for ${w}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:w,id:B});if("error"in Y)return Q.scheduler.failPublish(w,B,Y.error),{success:!1};return Q.scheduler.completePublish(w,B,Y.result),Q.logger.debug(`Direct publish completed: ${B}`,{entityType:w}),{success:!0}}catch(Y){let Z=eA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function Jt$(A,Q){let{entityType:$,entityId:w}=Q;try{return await A.publicationQueueService.remove($,w),A.logger.debug(`Entity removed from queue: ${w}`,{entityType:$}),{success:!0}}catch(B){let X=eA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function Ft$(A,Q){let{entityType:$,entityId:w,position:B}=Q;try{return await A.publicationQueueService.reorder($,w,B),A.logger.debug(`Entity reordered: ${w}`,{entityType:$,newPosition:B}),{success:!0}}catch(X){let Y=eA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function Lt$(A,Q,$){let{entityType:w}=$;try{let B=await Q.queueManager.list(w);return await A.messaging.send({type:sY.LIST_RESPONSE,payload:{entityType:w,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=eA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function It$(A,Q){let{entityType:$,entityId:w,result:B}=Q;return A.scheduler.completePublish($,w,B),A.logger.info(`Publish reported success: ${w}`,{entityType:$}),{success:!0}}async function Nt$(A,Q){let{entityType:$,entityId:w,error:B}=Q;A.scheduler.failPublish($,w,B);let X=A.retryTracker.getRetryInfo(w);return A.logger.info(`Publish reported failure: ${w}`,{entityType:$,error:B,retryCount:X?.retryCount}),{success:!0}}async function _t$(A,Q){let{entityType:$,entityId:w}=Q;return A.scheduler.completeGeneration($,w),A.logger.info("Generation completed",{entityType:$,entityId:w}),{success:!0}}async function Pt$(A,Q){let{entityType:$,error:w}=Q;return A.scheduler.failGeneration($,w),A.logger.warn("Generation failed",{entityType:$,error:w}),{success:!0}}async function Ne2(A,Q,$,w){try{if(w.skipIfDraftExists!==!1){if((await A.listEntities({entityType:$,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(w.maxUnpublishedDrafts!==void 0){let B=await A.listEntities({entityType:$,options:{filter:{metadata:{status:"draft"}},limit:w.maxUnpublishedDrafts+1}});if(B.length>=w.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${B.length}/${w.maxUnpublishedDrafts})`}}if(w.minSourceEntities!==void 0&&w.sourceEntityType){let B=await A.listEntities({entityType:w.sourceEntityType,options:{publishedOnly:!0,limit:w.minSourceEntities}});if(B.length<w.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${B.length}/${w.minSourceEntities} ${w.sourceEntityType})`}}return{shouldGenerate:!0}}catch(B){return Q.error("Failed to check generation conditions",{entityType:$,error:eA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${eA(B)}`}}}function _e2(A){let{context:Q,config:$,queueManager:w,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=bt$(Q);return WI.createFresh({queueManager:w,providerRegistry:B,retryTracker:X,logger:Z,backend:new wh({onOverlapSkipped:(K)=>{Z.debug("Skipping overlapping content scheduler cycle",{jobKey:K})},onCallbackError:(K,U)=>{Z.error("Unhandled content scheduler callback error",{jobKey:K,error:U})}}),...$.entitySchedules&&{entitySchedules:$.entitySchedules},...$.generationSchedules&&{generationSchedules:$.generationSchedules},...$.generationConditions&&{generationConditions:$.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(K,U)=>Ne2(Q.entityService,Z,K,U)})}function bt$(A){return{send:async(B)=>{return A.messaging.send({type:B.type,payload:B.payload,...B.target!==void 0?{target:B.target}:{},...B.metadata!==void 0?{metadata:B.metadata}:{},...B.broadcast!==void 0?{broadcast:B.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}h0();h0();var jt$=W.enum(["draft","queued","published","failed"]),Mt$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),position:W.number().int().positive(),queuedAt:W.string(),destination:W.string(),scheduledFor:W.string().optional()}),kt$=W.object({id:W.string(),label:W.string(),target:W.string(),status:W.enum(["pending","processing"])}),Ot$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),error:W.string(),retryCount:W.number().int().nonnegative()}),ft$=W.object({summary:W.object({draft:W.number().int().nonnegative(),queued:W.number().int().nonnegative(),generating:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),published:W.number().int().nonnegative(),needsOperator:W.number().int().nonnegative()}),queue:W.array(Mt$),generating:W.array(kt$),failures:W.array(Ot$),publishableEntityTypes:W.array(W.string())}),xt$=W.object({sourceEntityType:W.string(),sourceEntityId:W.string(),attachmentType:W.string().optional()});async function lO0(A,Q,$,w){let B=Q.getRegisteredTypes().sort(),X=new Map,Y={draft:0,queued:0,generating:0,failed:0,published:0,needsOperator:0};for(let U of B){let G=await A.entityService.listEntities({entityType:U});for(let D of G){let q=jt$.safeParse(D.metadata.status);if(!q.success)continue;Y[q.data]+=1;let J=D.metadata.scheduledFor,F=D.metadata.error;X.set(Pe2(U,D.id),{entityId:D.id,entityType:U,title:vt$(D.id,D.metadata),status:q.data,...typeof J==="string"?{scheduledFor:J}:{},...typeof F==="string"?{error:F}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await $.list(U)){let q=X.get(Pe2(U,D.entityId));if(!q)continue;Z.push({entityId:D.entityId,entityType:U,title:q.title,position:D.position,queuedAt:D.queuedAt,destination:G,...q.scheduledFor?{scheduledFor:q.scheduledFor}:{}})}}let H=await Rt$(A);Y.generating=H.length;let K=Array.from(X.values()).filter((U)=>U.status==="failed").map((U)=>{let G=w.getRetryInfo(U.entityId);return{entityId:U.entityId,entityType:U.entityType,title:U.title,error:U.error??G?.lastError??"Publication failed",retryCount:G?.retryCount??0}}).sort((U,G)=>U.title.localeCompare(G.title));return Y.needsOperator=Y.draft+Y.failed,ft$.parse({summary:Y,queue:Z,generating:H,failures:K,publishableEntityTypes:B})}async function Rt$(A){let Q=[];for(let $ of await A.jobs.getActiveJobs()){if($.source!=="content-pipeline")continue;if($.status!=="pending"&&$.status!=="processing")continue;let w;try{w=JSON.parse($.data)}catch{continue}let B=xt$.safeParse(w);if(!B.success)continue;Q.push({id:$.id,label:B.data.attachmentType??$.type,target:`${B.data.sourceEntityType}/${B.data.sourceEntityId}`,status:$.status})}return Q}function Pe2(A,Q){return`${A}\x00${Q}`}function vt$(A,Q){for(let $ of["title","subject","slug"]){let w=Q[$];if(typeof w==="string"&&w.length>0)return w}return A}async function be2(A,Q,$){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"primary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:async()=>({...await lO0(A,$.providerRegistry,$.queueManager,$.retryTracker),...$.managementUrl?{managementUrl:$.managementUrl}:{}}),digestProvider:ht$}})}var Ct$=W.object({summary:W.object({draft:W.number(),queued:W.number(),generating:W.number(),published:W.number(),failed:W.number(),needsOperator:W.number()})});function ht$(A){let{summary:Q}=Ct$.parse(A),$=Q.queued+Q.generating,w=$===0?"idle":`${Q.queued} queued \xB7 ${Q.generating} generating`,B=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`;return{digest:[{label:"Pipeline",value:w,...$>0?{tone:"warn"}:{}},{label:"Awaiting review",value:B,...Q.needsOperator>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Q.needsOperator}}zA();h0();var Et$=W.object({workspaceUrl:W.string()}),Tt$=W.object({confirmed:W.literal(!0),confirmationToken:W.string().min(1),contentHash:W.string().min(1),expiresAt:W.string().datetime()}),yt$=W.discriminatedUnion("type",[W.object({type:W.literal("queue"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("remove"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("retry"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("reorder"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1),position:W.number().int().positive()}),W.object({type:W.literal("publish"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1),confirmation:Tt$.optional()})]);async function je2(A,Q,$){let w=Wo(A,Q,$.providerRegistry,$.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",priority:40,entityTypes:$.providerRegistry.getRegisteredTypes(),dataProvider:()=>lO0(A,$.providerRegistry,$.queueManager,$.retryTracker),actionHandler:async(Z,H)=>{let K=yt$.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return gt$(A,$,w,K.data,H)}},X=await A.messaging.send({type:v_,payload:B});if(!("success"in X)||!X.success)return;let Y=Et$.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function gt$(A,Q,$,w,B){if(!Q.providerRegistry.has(w.entityType))throw Error(`No publish provider registered for ${w.entityType}`);let X=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!X)throw Error(`Entity not found: ${w.entityType}:${w.entityId}`);if(w.type==="publish"){let H=await $.handler({entityType:w.entityType,id:w.entityId,...w.confirmation??{}},B);if("success"in H&&H.success===!0)await Q.publicationQueueService.complete(w.entityType,w.entityId),Q.retryTracker.clearRetries(w.entityId);return H}let Y=w.type==="queue"||w.type==="retry"?"publish":"update";A.permissions.assertEntityActionAllowed(w.entityType,Y,B);let Z=X.metadata.status;switch(w.type){case"queue":if(Z!=="draft")throw Error("Only draft entities can be queued");return Q.publicationQueueService.enqueue(w.entityType,w.entityId,{...B,authorization:"user"});case"remove":if(Z!=="queued")throw Error("Only queued entities can be removed from the queue");return await Q.publicationQueueService.remove(w.entityType,w.entityId),{success:!0};case"retry":if(Z!=="failed")throw Error("Only failed publications can be retried");return await Q.publicationQueueService.enqueue(w.entityType,w.entityId,{...B,authorization:"user"}),{success:!0};case"reorder":if(Z!=="queued")throw Error("Only queued entities can be reordered");return await Q.publicationQueueService.reorder(w.entityType,w.entityId,w.position),{success:!0}}}var Me2={name:"@brains/content-pipeline",version:"0.2.0-alpha.195",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/scheduler":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class JIA extends d6{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",Me2,A,We2)}async onRegister(A){this.pluginContext=A,this.queueManager=YI.createFresh(),this.publicationQueueService=new VIA(A,this.queueManager),this.providerRegistry=ZI.createFresh(),this.retryTracker=HI.createFresh(),this.publishAssetRegistry=KI.createFresh(),this.publishAssetPreflight=new uO0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Zo({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=_e2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),Ie2(A,{queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await this.publicationQueueService.reconcile(this.providerRegistry.getRegisteredTypes());let Q=await je2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await be2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,retryTracker:this.retryTracker,...Q?{managementUrl:Q}:{}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[cO0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),Wo(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),pO0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getPublicationQueueService(){return this.publicationQueueService}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),YI.resetInstance(),ZI.resetInstance(),HI.resetInstance(),KI.resetInstance()}}function FIA(A={}){return new JIA(A)}zA();h0();var ke2=W.object({accountId:W.string().describe("Cloudflare account ID"),apiToken:W.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:W.string().describe("Cloudflare Web Analytics site tag")}),LIA=W.object({cloudflare:ke2.optional()});zA();h0();var mt$=W.object({date:W.string().describe("Single date in YYYY-MM-DD format").optional(),days:W.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:W.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:W.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:W.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function ut$(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 Oe2(A,Q,$){let w=[];if(!$)return w;return w.push(e8(A,"query",`Query website analytics from Cloudflare.
8146
+ ${$.content}`:$.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${$.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let $=Pa$.parse(Q),w=[],B=EW.from(async(K)=>{let U={progress:K.progress};if(K.message!==void 0)U.message=K.message;w.push(U)});if(!B)throw Error("Failed to create progress reporter");let Y=await new Ty(A.logger,A).process($,`eval-${Date.now()}`,B),Z=!1,H;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!K,H=K?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:H,progressSteps:w}})}zA();class p90{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:$}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:$});try{let w=await this.entityService.getEntity({entityType:"social-post",id:$});if(!w){await this.reportFailure(Q,$,`Post not found: ${$}`);return}let B=w;if(B.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:$});return}let X=B.metadata.platform,Y=this.providers.get(X);if(!Y){await this.reportFailure(Q,$,`No provider configured for platform: ${X}`);return}let Z=MQ(B.content,sV),H;if(Z.metadata.coverImageId)H=await this.fetchImageData(Z.metadata.coverImageId);let K=Z.metadata.documents??[],U=await this.fetchDocumentData(K);try{if(K.length>0&&U.length===0)throw Error(`Refusing to publish: ${K.length} document(s) referenced but none could be fetched`);let G=K.length===0?await this.resolveSourceAttachment(Z.metadata):[],D=U.length>0?U:G,q=D.length?await Y.publish(Z.content,B.metadata,H,D):await Y.publish(Z.content,B.metadata,H),J=new Date().toISOString(),F=q.id||void 0,L={...Z.metadata,status:"published",publishedAt:J,...F&&{platformPostId:F}},_=oY.createPostContent(L,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:J,platformPostId:F}}}),await this.reportSuccess(Q,$,q.id),this.logger.info(`Post published successfully: ${$}`,{platform:X,platformPostId:F})}catch(G){let D=G instanceof Error?G.message:String(G),q={...Z.metadata,status:"failed"},J=oY.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:J,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,$,D),this.logger.error(`Post publish failed: ${$}`,{platform:X,error:D})}}catch(w){let B=eA(w);this.logger.error("Unexpected error in publish handler",{entityId:$,error:B}),await this.reportFailure(Q,$,B)}}async reportSuccess(A,Q,$){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:$}}})}async reportFailure(A,Q,$){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:$}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let $ of A){let w=await this.fetchSingleDocumentData($.id);if(w)Q.push(w)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let $=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!$?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let w=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from($[1],"base64"),mimeType:"application/pdf",filename:w}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let w=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!w?.[1]||!w[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let B=w[1],X=w[2];return{data:Buffer.from(X,"base64"),mimeType:B}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function tt2(A,Q,$){if(Q.size===0){$.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let w=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:w,config:{publishResultIdField:"platformPostId"}}}),$.info("Registered social-post with publish-pipeline"),{success:!0}})}function et2(A,Q,$){let w=new p90({sendMessage:A.messaging.send,logger:$.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async(B)=>{return await w.handle(B.payload),{success:!0}}),$.debug("Subscribed to publish:execute messages")}function Ae2(A,Q){A.messaging.subscribe("entity:updated",async($)=>{let{entityType:w,entityId:B,entity:X}=$.payload;if(w!=="post")return{success:!0};if(X.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:B}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${B}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:w,sourceEntityId:B,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${B}`),{success:!0}}catch(Z){let H=eA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Qe2(A,Q){A.messaging.subscribe("social:auto-generate",async($)=>{let{sourceEntityType:w,sourceEntityId:B,platform:X}=$.payload;try{let Y=await A.jobs.enqueue({type:`${oY.entityType}:generation`,data:{sourceEntityType:w,sourceEntityId:B,platform:X,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${w}/${B}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let Z=eA(Y);return Q.error(`Failed to enqueue social post generation for ${B}:`,{error:Z}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function $e2(A,Q){A.messaging.subscribe("generate:execute",async($)=>{let{entityType:w}=$.payload;if(w!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let B=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if(B.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let X=null;for(let Z of B)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Z.id}},limit:1}})).length===0){X=Z;break}if(!X)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${oY.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:X.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:X.id}),{success:!0}}catch(B){let X=eA(B);return Q.error("Failed to handle generate:execute:",{error:X}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:X}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function we2({entity:A,config:Q}){let $=Gx.parse(A),w=oY.parsePostFrontmatter($),B=oY.getPostContent($);return{$type:"ai.rizom.brain.socialPost",title:w.title,platform:w.platform,body:B,format:"text/markdown",status:w.status,...w.publishedAt&&{publishedAt:w.publishedAt},...w.platformPostId&&{platformPostId:w.platformPostId},...w.sourceEntityType&&{sourceLocalEntityType:w.sourceEntityType},...w.sourceEntityId&&{sourceLocalEntityId:w.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:$.id,createdAt:$.created,...$.updated&&{updatedAt:$.updated}}}function tLA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:i8["ai.rizom.brain.socialPost"],validate:!1,buildRecord:we2}}var Be2={name:"@brains/social-media",version:"0.2.0-alpha.196",description:"Multi-provider social media posting with queue-based publishing",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class eLA extends c6{entityType=oY.entityType;schema=Gx;adapter=oY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",Be2,A,dLA)}createGenerationHandler(A){return new Ty(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return st2()}getDataSources(){return[new TO0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),tt2(A,this.providers,this.logger),et2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Ae2(A,this.logger),Qe2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");$e2(A,this.logger),at2(A),this.unregisterAtprotoProjection=D9.getInstance().register(tLA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=aLA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function l90(A={}){return new eLA(A)}h0();var ja$=W.enum(["draft","queued","published","failed"]),Xe2=W.object({status:ja$.default("draft"),queueOrder:W.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:W.string().datetime().optional()});class AIA{name="internal";async publish(A,Q){return{id:"internal"}}}var xb={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},sY={REGISTER:"publish:register",QUEUE:"publish:queue",DIRECT:"publish:direct",REMOVE:"publish:remove",REORDER:"publish:reorder",LIST:"publish:list",REPORT_SUCCESS:"publish:report:success",REPORT_FAILURE:"publish:report:failure",QUEUED:"publish:queued",COMPLETED:"publish:completed",FAILED:"publish:failed",LIST_RESPONSE:"publish:list:response"},Dx={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"},Ye2={REGISTER:"publish-assets:register"};h0();var Ma$=W.enum(["provider"]),Ze2=W.object({executionMode:Ma$.optional(),publishResultIdField:W.string().min(1).optional(),publishTimestampField:W.string().min(1).optional(),enabled:W.boolean().optional()}).strict();var ka$=W.object({skipIfDraftExists:W.boolean().optional(),minSourceEntities:W.number().optional(),maxUnpublishedDrafts:W.number().optional(),sourceEntityType:W.string().optional()}),We2=W.object({entitySchedules:W.record(W.string(),W.string()).optional(),generationSchedules:W.record(W.string(),W.string()).optional(),generationConditions:W.record(W.string(),ka$).optional()});class YI{static instance=null;queues=new Map;static getInstance(){return YI.instance??=new YI,YI.instance}static resetInstance(){YI.instance=null}static createFresh(){return new YI}constructor(){}async add(A,Q,$=xb){let w=this.getOrCreateQueue(A),B=w.find((Z)=>Z.entityId===Q);if(B)return{position:B.position};let X=w.length+1,Y={entityId:Q,entityType:A,position:X,queuedAt:new Date().toISOString(),authContext:{...$}};return w.push(Y),{position:X}}async remove(A,Q){let $=this.queues.get(A);if(!$)return;let w=$.findIndex((B)=>B.entityId===Q);if(w===-1)return;$.splice(w,1),this.recalculatePositions($)}async reorder(A,Q,$){let w=this.queues.get(A);if(!w)return;let B=w.findIndex((Z)=>Z.entityId===Q);if(B===-1)return;let[X]=w.splice(B,1);if(!X)return;let Y=Math.max(0,Math.min($-1,w.length));w.splice(Y,0,X),this.recalculatePositions(w)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let $=Q[0];if(!$)continue;if(!A||$.queuedAt<A.queuedAt)A=$}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let $=Q.shift()??null;if($)this.recalculatePositions(Q);return $}replace(A){this.queues.clear();let Q=[...A].sort(($,w)=>$.entityType.localeCompare(w.entityType)||$.position-w.position);for(let $ of Q)this.getOrCreateQueue($.entityType).push({...$,authContext:{...$.authContext}});for(let $ of this.queues.values())this.recalculatePositions($)}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,$]of this.queues.entries())if($.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,$)=>{Q.position=$+1})}}class ZI{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new AIA;static getInstance(){return ZI.instance??=new ZI,ZI.instance}static resetInstance(){ZI.instance=null}static createFresh(){return new ZI}constructor(){}register(A,Q,$){let w=this.providers.get(A);if(w&&w.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,$?.executionMode??"provider"),$?.publishResultIdField)this.publishResultIdFields.set(A,$.publishResultIdField);else this.publishResultIdFields.delete(A);if($?.publishTimestampField)this.publishTimestampFields.set(A,$.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function He2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await Oa$(A,Q)}async function Oa$(A,Q){if(!Q.publishExecutor)return;try{let $=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in $){let w={entityType:A.entityType,entityId:A.entityId,error:$.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:sY.FAILED,payload:w,sender:"publish-service",broadcast:!0});Q.onFailed?.(w);return}QIA(A.entityType,A.entityId,$.result,Q)}catch($){let w=eA($);Q.retryTracker.recordFailure(A.entityId,w);let B=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:w,retryCount:B?.retryCount??1,willRetry:!1})}}function QIA(A,Q,$,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send({type:sY.COMPLETED,payload:{entityType:A,entityId:Q,result:$},sender:"publish-service",broadcast:!0});w.onPublish?.({entityType:A,entityId:Q,result:$})}function Ke2(A,Q,$,w){w.retryTracker.recordFailure(Q,$);let B=w.retryTracker.getRetryInfo(Q),X={entityType:A,entityId:Q,error:$,retryCount:B?.retryCount??1,willRetry:!1};if(w.messageBus)w.messageBus.send({type:sY.FAILED,payload:X,sender:"publish-service",broadcast:!0});w.onFailed?.(X)}async function Ue2(A,Q){let $=Q.generationConditions[A];if($&&Q.onCheckGenerationConditions){let B=await Q.onCheckGenerationConditions(A,$);if(!B.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:Dx.SKIPPED,payload:{entityType:A,reason:B.reason??"Conditions not met"},sender:"content-pipeline"});return}}let w={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:Dx.EXECUTE,payload:w,sender:"content-pipeline"});Q.onGenerate?.(w)}function Ge2(A,Q,$){if($)$.send({type:Dx.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function De2(A,Q,$){if($)$.send({type:Dx.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var fa$=1000;class $IA{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let $=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,$)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(fa$,()=>this.processUnscheduledTypes())}async stop(){let A=Array.from(this.publishJobs.values());if(this.publishJobs.clear(),this.immediateIntervalJob)A.push(this.immediateIntervalJob),this.immediateIntervalJob=null;await Promise.all(A.map((Q)=>Q.stop()))}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let $=await this.deps.config.queueManager.getNext(Q);if($){await this.processEntry($);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await He2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class wIA{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let $=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,$)}}async stop(){let A=Array.from(this.generationJobs.values());this.generationJobs.clear(),await Promise.all(A.map((Q)=>Q.stop()))}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await Ue2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}class WI{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return WI.instance??=new WI(A),WI.instance}static async resetInstance(){let A=WI.instance;if(WI.instance=null,A)await A.stop()}static createFresh(A){return new WI(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new $IA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new wIA({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}stop(){if(this.stopPromise)return this.stopPromise;return this.running=!1,this.stopPromise=Promise.all([this.publishRunner.stop(),this.generationRunner.stop()]).then(()=>{return}),this.stopPromise}isRunning(){return this.running}completePublish(A,Q,$){QIA(A,Q,$,this.publishDeps)}failPublish(A,Q,$){Ke2(A,Q,$,this.publishDeps)}completeGeneration(A,Q){Ge2(A,Q,this.config.messageBus)}failGeneration(A,Q){De2(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,$){try{this.config.backend.validateCron(Q)}catch(w){throw Error(`Invalid ${$} cron expression for ${A}: "${Q}" - ${eA(w)}`,{cause:w})}}}class HI{static instance=null;retries=new Map;static getInstance(){return HI.instance??=new HI,HI.instance}static resetInstance(){HI.instance=null}static createFresh(){return new HI}constructor(){}recordFailure(A,Q){let w=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:w,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}LAA();h0();var qe2=W.union([W.string().min(1),W.object({location:W.enum(["metadata","frontmatter"]),field:W.string().min(1)})]),mO0=W.object({entityType:W.string().min(1),attachmentType:W.string().min(1),mediaEntityType:W.enum(["image","document"]),targetEntityField:qe2.optional(),requiredWhen:W.object({status:W.string().min(1).optional(),visibility:W.string().min(1).optional()}).optional(),autoGenerate:W.boolean().optional(),requiredForPublish:W.boolean().optional(),jobType:W.string().min(1).optional()});function BIA(A){return`${A.entityType}:${A.attachmentType}`}class KI{static instance=null;definitions=new Map;static getInstance(){return KI.instance??=new KI,KI.instance}static resetInstance(){KI.instance=null}static createFresh(){return new KI}constructor(){}register(A){let Q=mO0.parse(A),$=BIA(Q);return this.definitions.set($,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(BIA({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter(($)=>$.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(BIA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}u4();p2();class uO0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let $=this.deps.registry.list(A.entityType).filter((B)=>B.autoGenerate===!0).filter((B)=>!Q.attachmentType||B.attachmentType===Q.attachmentType),w={checked:$.length,enqueued:0,skipped:0};for(let B of $)if(await this.ensureDefinition(A,B))w.enqueued+=1;else w.skipped+=1;return w}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let $=this.resolveJobType(Q);if(!$)return!1;let w=this.getPredictedMediaId(A,Q),B=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:$,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:w,dedupKey:B,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:B}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:$}),!0}matchesPolicy(A,Q){let{requiredWhen:$}=Q;if(!$)return!0;if($.status&&A.metadata.status!==$.status)return!1;if($.visibility&&A.visibility!==$.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return XIA(A.metadata[Q]);if(Q.location==="metadata")return XIA(A.metadata[Q.field]);let{frontmatter:$}=t8(A.content);return XIA($[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let $=Q.attachmentType==="og-image"?"og":Q.attachmentType;return O1(`${$}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function XIA(A){return typeof A==="string"?A.length>0:A!==void 0}zA();h0();var Ra$=W.object({id:W.string().min(1)});async function Ve2(A,Q){let{bodyContent:$,coverImageId:w,documents:B,sourceEntityType:X,sourceEntityId:Y}=va$(Q.content),Z=w?await Ea$(A,w):void 0,H;if(B&&B.length>0){let U=await Ta$(A,B);if(U.length>0)H=U}H??=await ha$(A,X,Y);let K={bodyContent:$};if(Z)K.imageData=Z;if(H&&H.length>0)K.documentData=H;return K}function va$(A){try{let Q=MQ(A,W.record(W.string(),W.unknown())),$=Q.metadata.coverImageId,w=typeof $==="string"?$:void 0,B=Ca$(Q.metadata.documents),X=ze2(Q.metadata.sourceEntityType),Y=ze2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...w&&{coverImageId:w},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function Ca$(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let $=Ra$.safeParse(Q);return $.success?[$.data]:[]})}function ze2(A){return typeof A==="string"&&A.length>0?A:void 0}async function ha$(A,Q,$){if(!Q||!$)return;let w=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:$,attachmentType:"carousel"});return w?[w]:void 0}async function Ea$(A,Q){let $=await A.entityService.getEntity({entityType:"image",id:Q});if(!$?.content)return;let w=Je2($.content);if(!w?.mimeType.startsWith("image/"))return;return{data:w.data,mimeType:w.mimeType}}async function Ta$(A,Q){return(await Promise.all(Q.map((w)=>ya$(A,w)))).filter((w)=>w!==void 0)}async function ya$(A,Q){let $=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!$?.content)return;let w=Je2($.content);if(w?.mimeType!=="application/pdf")return;return{type:"document",data:w.data,mimeType:"application/pdf",filename:ga$($,Q.id)}}function Je2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function ga$(A,Q){let $=A.metadata.filename;return typeof $==="string"&&$.length>0?$:`${Q}.pdf`}u4();var Sa$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function YIA(A,Q,$,w={}){let B=w.publishTimestampField??"publishedAt",X=Q.metadata[B],Y=w.publishedAt??(typeof X==="string"?X:void 0)??new Date().toISOString(),Z={...Q.metadata,status:"published",[B]:Y,platformId:$.id,...ma$($.id,w.publishResultIdField)},H={...Q,content:Fe2(Q.content,Y,$.id,w.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function Fe2(A,Q,$,w,B="publishedAt"){if(!Sa$.test(A))return A;let X=hX(hX(A,"status","published"),B,Q);if(!$||!w)return X;return hX(X,w,$)}function ma$(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Zo{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:$,slug:w}=A;if(!$&&!w)return{error:"Either 'id' or 'slug' must be provided"};let B=await this.findPublishableEntity(Q,$,w);if(!B)return{error:`Entity not found: ${Q}:${$??w}`};if(B.visibility!=="public")return{error:`Cannot publish ${Q}:${B.id} to a public provider because visibility is ${B.visibility}`};if(B.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:B}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:$}=Q,{entityType:w}=A,B=this.deps.providerRegistry.get(w),{bodyContent:X,imageData:Y,documentData:Z}=await Ve2(this.deps.context,$),H=await B.publish(X,$.metadata,Y,Z),K=this.deps.providerRegistry.getPublishResultIdField(w),U=this.deps.providerRegistry.getPublishTimestampField(w),G=await YIA(this.deps.context,$,H,{...K?{publishResultIdField:K}:{},...U?{publishTimestampField:U}:{}});return await this.runPublishAssetPreflight(G),{entity:G,result:H}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,$){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!$)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:$}},limit:1}}))[0]??null}}zA();h0();var ZIA=W.object({action:W.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:W.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:W.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:W.number().optional().describe("New position for reorder action (1-based)")}),WIA=W.object({position:W.number(),entityType:W.string(),entityId:W.string(),queuedAt:W.string()}),ua$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({queue:W.array(WIA).optional(),entityType:W.string().optional(),entityId:W.string().optional(),position:W.number().optional()}).optional()}),ca$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),HIA=W.union([ua$,ca$]);function cO0(A,Q,$,w){let B=w??$;return{...e8(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",ZIA,async(Y,Z)=>{let{action:H,entityType:K,entityId:U,position:G}=Y;switch(H){case"list":return pa$($,K);case"add":return la$(A,B,K,U,Z);case"remove":return ia$(A,B,K,U,Z);case"reorder":return da$(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${H}`}}},{sideEffects:"writes"}),outputSchema:HIA}}async function pa$(A,Q){let $=[];if(Q)$=await A.list(Q);else{let B=A.getRegisteredTypes();for(let X of B){let Y=await A.list(X);$.push(...Y)}$.sort((X,Y)=>new Date(X.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if($.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:$.map((B,X)=>({position:X+1,entityType:B.entityType,entityId:B.entityId,queuedAt:B.queuedAt}))},message:`${$.length} items in queue`}}async function la$(A,Q,$,w,B){let X=KIA("add",$,w);if(!X.success)return X.error;A.permissions.assertEntityActionAllowed(X.entityType,"publish",B??{});let Y=await Q.add(X.entityType,X.entityId,{...B,authorization:"user"});return{success:!0,data:{entityType:X.entityType,entityId:X.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function ia$(A,Q,$,w,B){let X=KIA("remove",$,w);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(X.entityType,"update",B??{}),await Q.remove(X.entityType,X.entityId),{success:!0,data:{entityType:X.entityType,entityId:X.entityId},message:"Removed from queue"}}async function da$(A,Q,$,w,B,X){let Y=KIA("reorder",$,w);if(!Y.success)return Y.error;let Z=na$(B);if(!Z.success)return Z.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",X??{}),await Q.reorder(Y.entityType,Y.entityId,Z.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:Z.position},message:`Moved to position ${Z.position}`}}function KIA(A,Q,$){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!$)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:$}}function na$(A){if(A===void 0)return{success:!1,error:{success:!1,error:"position is required for reorder action"}};if(A<1)return{success:!1,error:{success:!1,error:"position must be a positive number"}};return{success:!0,position:A}}h0();import{createHash as ra$}from"crypto";var UIA=W.object({entityType:W.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:W.string().optional().describe("Entity ID to publish"),slug:W.string().optional().describe("Entity slug to publish"),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),contentHash:W.string().optional(),expiresAt:W.string().datetime().optional()}),oa$=W.object({entityType:W.string(),id:W.string().optional(),slug:W.string().optional(),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),contentHash:W.string().optional(),expiresAt:W.string().datetime().optional()}),sa$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({entityType:W.string().optional(),entityId:W.string().optional(),platformId:W.string().optional(),url:W.string().optional()}).optional()}),aa$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),ta$=W.object({success:W.literal(!1).optional(),error:W.string().optional(),needsConfirmation:W.literal(!0),toolName:W.string(),summary:W.string(),preview:W.string().optional(),args:W.unknown()}),GIA=W.union([sa$,aa$,ta$]),ea$=900000;function Wo(A,Q,$,w){let B=w??new Zo({context:A,providerRegistry:$}),X=`${Q}_publish`;return{name:X,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:UIA.shape,outputSchema:GIA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=oa$.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((F)=>`${F.path.join(".")}: ${F.message}`).join(", ")}`};let K=H.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(F){return{success:!1,error:F instanceof Error?F.message:String(F)}}let q=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:J}=q;if(K.confirmed){let F=Qt$(X,K,J);if(F!==null)return F;let L;try{L=await B.publish({entityType:U,id:J.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in L)return{success:!1,error:L.error};let{entity:_,result:j}=L;return{success:!0,data:{entityType:U,entityId:_.id,platformId:j.id,url:j.url},message:`Published ${U}:${_.id}`}}return At$(X,K,J)}}}function At$(A,Q,$){let w=new Date(Date.now()+ea$).toISOString(),B=Le2(A,$,w),X=$t$($);return{needsConfirmation:!0,toolName:A,summary:`Publish "${X}"?`,preview:`This will publish ${$.entityType}:${$.id} to its registered public publish provider.`,args:{...Q,id:$.id,slug:void 0,confirmed:!0,confirmationToken:B,contentHash:$.contentHash,expiresAt:w}}}function Qt$(A,Q,$){let{confirmationToken:w,contentHash:B,expiresAt:X}=Q;if(!w||!X)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(X);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if(B&&B!==$.contentHash)return{success:!1,error:`Cannot publish ${$.entityType}:${$.id} because it changed after confirmation. Review it and try again.`};if(w!==Le2(A,$,X))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function Le2(A,Q,$){return ra$("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update($).digest("hex")}function $t$(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let $=A.metadata.subject;if(typeof $==="string"&&$.length>0)return $;let w=A.metadata.slug;if(typeof w==="string"&&w.length>0)return w;return A.id}zA();h0();var DIA=W.object({entityType:W.string().min(1).describe("Entity type to reconcile"),status:W.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:W.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),qIA=W.object({success:W.literal(!0),data:W.object({entityType:W.string(),assetType:W.string().optional(),checkedEntities:W.number(),checkedAssets:W.number(),enqueued:W.number(),skipped:W.number()}),message:W.string().optional()});function pO0(A,Q,$,w){return{...e8(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",DIA,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),$.list(X.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!X.assetType||D.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let H=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),K=0,U=0,G=0;for(let D of H){let q=await w.ensureForEntity(D,{...X.assetType&&{attachmentType:X.assetType}});K+=q.checked,U+=q.enqueued,G+=q.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:H.length,checkedAssets:K,enqueued:U,skipped:G},message:`Queued ${U} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:qIA}}zA();u4();h0();var wt$="content-pipeline.queue.v1",zIA=1024,Bt$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,Xt$=W.object({interfaceType:W.string().optional(),userId:W.string().optional(),userPermissionLevel:W.enum(["public","trusted","anchor"]).optional(),authorization:W.enum(["user","system"]).optional()}),Yt$=W.object({entityType:W.string(),entityId:W.string(),rank:W.number().int().positive(),queuedAt:W.string().datetime(),contentHashAtEnqueue:W.string(),authContext:Xt$,revision:W.number().int().positive()});class VIA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:wt$,schema:Yt$})}async add(A,Q,$=xb){return this.enqueue(A,Q,$)}async enqueue(A,Q,$=xb){return this.runExclusive(async()=>{let w=await this.requireEntity(A,Q);await this.persistStatus(w,"queued");let B=await this.queueManager.add(A,Q,$);if(!await this.store.get(jz(A,Q))){let Y=(await this.queueManager.list(A)).find((H)=>H.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set(jz(A,Q),{entityType:A,entityId:Q,rank:B.position*zIA,queuedAt:Y?.queuedAt??new Date().toISOString(),contentHashAtEnqueue:Z.contentHash,authContext:{...$},revision:1})}return B})}async remove(A,Q){await this.runExclusive(async()=>{let $=await this.requireEntity(A,Q);if($.metadata.status==="queued")await this.persistStatus($,"draft");await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async reorder(A,Q,$){await this.runExclusive(async()=>{await this.requireEntity(A,Q),await this.queueManager.reorder(A,Q,$),await this.persistCurrentOrder(A)})}async complete(A,Q){await this.runExclusive(async()=>{await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async fail(A,Q,$){await this.runExclusive(async()=>{let w=await this.context.entityService.getEntity({entityType:A,id:Q});if(w)await this.persistStatus(w,"failed",$);await this.queueManager.remove(A,Q),await this.store.delete(jz(A,Q)),await this.persistCurrentOrder(A)})}async reconcile(A){await this.runExclusive(async()=>{let Q=new Map;for(let H of A){let K=await this.context.entityService.listEntities({entityType:H,options:{filter:{metadata:{status:"queued"}}}});for(let U of K)Q.set(jz(H,U.id),U)}let $=await this.listStored();for(let H of $)if(!Q.has(jz(H.entityType,H.entityId)))await this.store.delete(jz(H.entityType,H.entityId));let w=(await this.listStored()).filter((H)=>Q.has(jz(H.entityType,H.entityId))),B=new Map;for(let H of w)B.set(H.entityType,Math.max(B.get(H.entityType)??0,H.rank));for(let[H,K]of Q){if(w.some((G)=>jz(G.entityType,G.entityId)===H))continue;let U=(B.get(K.entityType)??0)+zIA;B.set(K.entityType,U),await this.store.set(H,{entityType:K.entityType,entityId:K.id,rank:U,queuedAt:typeof K.updated==="string"?K.updated:new Date().toISOString(),contentHashAtEnqueue:K.contentHash,authContext:{...xb},revision:1})}let X=await this.listStored(),Y=new Map,Z=X.map((H)=>{let K=(Y.get(H.entityType)??0)+1;return Y.set(H.entityType,K),{entityType:H.entityType,entityId:H.entityId,position:K,queuedAt:H.queuedAt,authContext:{...H.authContext}}});this.queueManager.replace(Z)})}async listStored(A){return(await this.store.list()).map((Q)=>Q.value).filter((Q)=>!A||Q.entityType===A).sort((Q,$)=>Q.entityType.localeCompare($.entityType)||Q.rank-$.rank||Q.queuedAt.localeCompare($.queuedAt)||Q.entityId.localeCompare($.entityId))}async deleteStored(A,Q){return this.store.delete(jz(A,Q))}async persistCurrentOrder(A){let Q=new Map((await this.listStored(A)).map(($)=>[$.entityId,$]));for(let $ of await this.queueManager.list(A)){let w=Q.get($.entityId);if(!w)continue;let B=$.position*zIA;if(w.rank===B)continue;await this.store.set(jz(A,$.entityId),{...w,rank:B,revision:w.revision+1})}}async persistStatus(A,Q,$){let w={...A.metadata,status:Q};if($)w.error=$;else delete w.error;let B=Bt$.test(A.content)?hX(A.content,"status",Q):A.content;await this.context.entityService.updateEntity({entity:{...A,metadata:w,content:B}})}async requireEntity(A,Q){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Entity not found: ${A}:${Q}`);return $}runExclusive(A){let Q=this.mutationTail.then(A);return this.mutationTail=Q.then(()=>{return},()=>{return}),Q}}function jz(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function Ie2(A,Q){Zt$(A,Q),Wt$(A,Q),Ht$(A,Q),Kt$(A,Q)}function Zt$(A,Q){A.messaging.subscribe(sY.REGISTER,async($)=>Ut$(Q,$.payload)),A.messaging.subscribe(sY.QUEUE,async($)=>zt$(A,Q,$.payload)),A.messaging.subscribe(sY.DIRECT,async($)=>Vt$(A,Q,$.payload)),A.messaging.subscribe(sY.REMOVE,async($)=>Jt$(Q,$.payload)),A.messaging.subscribe(sY.REORDER,async($)=>Ft$(Q,$.payload)),A.messaging.subscribe(sY.LIST,async($)=>Lt$(A,Q,$.payload)),A.messaging.subscribe(sY.REPORT_SUCCESS,async($)=>It$(Q,$.payload)),A.messaging.subscribe(sY.REPORT_FAILURE,async($)=>Nt$(Q,$.payload)),A.messaging.subscribe(sY.COMPLETED,async($)=>{return await Q.publicationQueueService.complete($.payload.entityType,$.payload.entityId),{success:!0}}),A.messaging.subscribe(sY.FAILED,async($)=>{return await Q.publicationQueueService.fail($.payload.entityType,$.payload.entityId,$.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function Wt$(A,Q){A.messaging.subscribe(Dx.REPORT_SUCCESS,async($)=>_t$(Q,$.payload)),A.messaging.subscribe(Dx.REPORT_FAILURE,async($)=>Pt$(Q,$.payload)),Q.logger.debug("Subscribed to generation messages")}function Ht$(A,Q){A.messaging.subscribe(Ye2.REGISTER,async($)=>Gt$(Q,$.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Kt$(A,Q){let $=async(w)=>Dt$(A,Q,w.payload);A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function Ut$(A,Q){let{entityType:$,provider:w,config:B}=Q;try{let X=B?Ze2.safeParse(B):void 0;if(X&&!X.success)return A.logger.warn("Invalid publish provider config",{entityType:$,error:X.error.message}),{success:!1};if(w)A.providerRegistry.register($,w,X?.data),A.logger.info(`Registered provider for entity type: ${$}`,{providerName:w.name,executionMode:A.providerRegistry.getExecutionMode($)});return{success:!0}}catch(X){let Y=eA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Gt$(A,Q){let $=mO0.safeParse(Q);if(!$.success)return A.logger.warn("Invalid publish asset registration",{error:$.error.message}),{success:!1};return A.publishAssetRegistry.register($.data),A.logger.info("Registered publish asset",{entityType:$.data.entityType,attachmentType:$.data.attachmentType,mediaEntityType:$.data.mediaEntityType}),{success:!0}}async function Dt$(A,Q,$){try{if(Q.publishAssetRegistry.list($.entityType).length===0)return{success:!0};let w=$.entity??await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(!qt$(w))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(w),{success:!0}}catch(w){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:$.entityType,entityId:$.entityId,error:eA(w)}),{success:!1}}}function qt$(A){if(!A)return!1;let Q=Xe2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function zt$(A,Q,$){let{entityType:w,entityId:B}=$;try{let X=$.authContext??xb;A.permissions.assertEntityActionAllowed(w,"publish",X);let Y=await Q.publicationQueueService.enqueue(w,B,X);return await A.messaging.send({type:sY.QUEUED,payload:{entityType:w,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:w,position:Y.position}),{success:!0}}catch(X){let Y=eA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Vt$(A,Q,$){let{entityType:w,entityId:B}=$,X=$.authContext??xb;try{if(A.permissions.assertEntityActionAllowed(w,"publish",X),!Q.providerRegistry.has(w))return Q.scheduler.failPublish(w,B,`No publish provider registered for ${w}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:w,id:B});if("error"in Y)return Q.scheduler.failPublish(w,B,Y.error),{success:!1};return Q.scheduler.completePublish(w,B,Y.result),Q.logger.debug(`Direct publish completed: ${B}`,{entityType:w}),{success:!0}}catch(Y){let Z=eA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function Jt$(A,Q){let{entityType:$,entityId:w}=Q;try{return await A.publicationQueueService.remove($,w),A.logger.debug(`Entity removed from queue: ${w}`,{entityType:$}),{success:!0}}catch(B){let X=eA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function Ft$(A,Q){let{entityType:$,entityId:w,position:B}=Q;try{return await A.publicationQueueService.reorder($,w,B),A.logger.debug(`Entity reordered: ${w}`,{entityType:$,newPosition:B}),{success:!0}}catch(X){let Y=eA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function Lt$(A,Q,$){let{entityType:w}=$;try{let B=await Q.queueManager.list(w);return await A.messaging.send({type:sY.LIST_RESPONSE,payload:{entityType:w,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=eA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function It$(A,Q){let{entityType:$,entityId:w,result:B}=Q;return A.scheduler.completePublish($,w,B),A.logger.info(`Publish reported success: ${w}`,{entityType:$}),{success:!0}}async function Nt$(A,Q){let{entityType:$,entityId:w,error:B}=Q;A.scheduler.failPublish($,w,B);let X=A.retryTracker.getRetryInfo(w);return A.logger.info(`Publish reported failure: ${w}`,{entityType:$,error:B,retryCount:X?.retryCount}),{success:!0}}async function _t$(A,Q){let{entityType:$,entityId:w}=Q;return A.scheduler.completeGeneration($,w),A.logger.info("Generation completed",{entityType:$,entityId:w}),{success:!0}}async function Pt$(A,Q){let{entityType:$,error:w}=Q;return A.scheduler.failGeneration($,w),A.logger.warn("Generation failed",{entityType:$,error:w}),{success:!0}}async function Ne2(A,Q,$,w){try{if(w.skipIfDraftExists!==!1){if((await A.listEntities({entityType:$,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(w.maxUnpublishedDrafts!==void 0){let B=await A.listEntities({entityType:$,options:{filter:{metadata:{status:"draft"}},limit:w.maxUnpublishedDrafts+1}});if(B.length>=w.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${B.length}/${w.maxUnpublishedDrafts})`}}if(w.minSourceEntities!==void 0&&w.sourceEntityType){let B=await A.listEntities({entityType:w.sourceEntityType,options:{publishedOnly:!0,limit:w.minSourceEntities}});if(B.length<w.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${B.length}/${w.minSourceEntities} ${w.sourceEntityType})`}}return{shouldGenerate:!0}}catch(B){return Q.error("Failed to check generation conditions",{entityType:$,error:eA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${eA(B)}`}}}function _e2(A){let{context:Q,config:$,queueManager:w,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=bt$(Q);return WI.createFresh({queueManager:w,providerRegistry:B,retryTracker:X,logger:Z,backend:new wh({onOverlapSkipped:(K)=>{Z.debug("Skipping overlapping content scheduler cycle",{jobKey:K})},onCallbackError:(K,U)=>{Z.error("Unhandled content scheduler callback error",{jobKey:K,error:U})}}),...$.entitySchedules&&{entitySchedules:$.entitySchedules},...$.generationSchedules&&{generationSchedules:$.generationSchedules},...$.generationConditions&&{generationConditions:$.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(K,U)=>Ne2(Q.entityService,Z,K,U)})}function bt$(A){return{send:async(B)=>{return A.messaging.send({type:B.type,payload:B.payload,...B.target!==void 0?{target:B.target}:{},...B.metadata!==void 0?{metadata:B.metadata}:{},...B.broadcast!==void 0?{broadcast:B.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}h0();h0();var jt$=W.enum(["draft","queued","published","failed"]),Mt$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),position:W.number().int().positive(),queuedAt:W.string(),destination:W.string(),scheduledFor:W.string().optional()}),kt$=W.object({id:W.string(),label:W.string(),target:W.string(),status:W.enum(["pending","processing"])}),Ot$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),error:W.string(),retryCount:W.number().int().nonnegative()}),ft$=W.object({summary:W.object({draft:W.number().int().nonnegative(),queued:W.number().int().nonnegative(),generating:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),published:W.number().int().nonnegative(),needsOperator:W.number().int().nonnegative()}),queue:W.array(Mt$),generating:W.array(kt$),failures:W.array(Ot$),publishableEntityTypes:W.array(W.string())}),xt$=W.object({sourceEntityType:W.string(),sourceEntityId:W.string(),attachmentType:W.string().optional()});async function lO0(A,Q,$,w){let B=Q.getRegisteredTypes().sort(),X=new Map,Y={draft:0,queued:0,generating:0,failed:0,published:0,needsOperator:0};for(let U of B){let G=await A.entityService.listEntities({entityType:U});for(let D of G){let q=jt$.safeParse(D.metadata.status);if(!q.success)continue;Y[q.data]+=1;let J=D.metadata.scheduledFor,F=D.metadata.error;X.set(Pe2(U,D.id),{entityId:D.id,entityType:U,title:vt$(D.id,D.metadata),status:q.data,...typeof J==="string"?{scheduledFor:J}:{},...typeof F==="string"?{error:F}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await $.list(U)){let q=X.get(Pe2(U,D.entityId));if(!q)continue;Z.push({entityId:D.entityId,entityType:U,title:q.title,position:D.position,queuedAt:D.queuedAt,destination:G,...q.scheduledFor?{scheduledFor:q.scheduledFor}:{}})}}let H=await Rt$(A);Y.generating=H.length;let K=Array.from(X.values()).filter((U)=>U.status==="failed").map((U)=>{let G=w.getRetryInfo(U.entityId);return{entityId:U.entityId,entityType:U.entityType,title:U.title,error:U.error??G?.lastError??"Publication failed",retryCount:G?.retryCount??0}}).sort((U,G)=>U.title.localeCompare(G.title));return Y.needsOperator=Y.draft+Y.failed,ft$.parse({summary:Y,queue:Z,generating:H,failures:K,publishableEntityTypes:B})}async function Rt$(A){let Q=[];for(let $ of await A.jobs.getActiveJobs()){if($.source!=="content-pipeline")continue;if($.status!=="pending"&&$.status!=="processing")continue;let w;try{w=JSON.parse($.data)}catch{continue}let B=xt$.safeParse(w);if(!B.success)continue;Q.push({id:$.id,label:B.data.attachmentType??$.type,target:`${B.data.sourceEntityType}/${B.data.sourceEntityId}`,status:$.status})}return Q}function Pe2(A,Q){return`${A}\x00${Q}`}function vt$(A,Q){for(let $ of["title","subject","slug"]){let w=Q[$];if(typeof w==="string"&&w.length>0)return w}return A}async function be2(A,Q,$){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"primary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:async()=>({...await lO0(A,$.providerRegistry,$.queueManager,$.retryTracker),...$.managementUrl?{managementUrl:$.managementUrl}:{}}),digestProvider:ht$}})}var Ct$=W.object({summary:W.object({draft:W.number(),queued:W.number(),generating:W.number(),published:W.number(),failed:W.number(),needsOperator:W.number()})});function ht$(A){let{summary:Q}=Ct$.parse(A),$=Q.queued+Q.generating,w=$===0?"idle":`${Q.queued} queued \xB7 ${Q.generating} generating`,B=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`;return{digest:[{label:"Pipeline",value:w,...$>0?{tone:"warn"}:{}},{label:"Awaiting review",value:B,...Q.needsOperator>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Q.needsOperator}}zA();h0();var Et$=W.object({workspaceUrl:W.string()}),Tt$=W.object({confirmed:W.literal(!0),confirmationToken:W.string().min(1),contentHash:W.string().min(1),expiresAt:W.string().datetime()}),yt$=W.discriminatedUnion("type",[W.object({type:W.literal("queue"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("remove"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("retry"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1)}),W.object({type:W.literal("reorder"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1),position:W.number().int().positive()}),W.object({type:W.literal("publish"),entityType:W.string().trim().min(1),entityId:W.string().trim().min(1),confirmation:Tt$.optional()})]);async function je2(A,Q,$){let w=Wo(A,Q,$.providerRegistry,$.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",priority:40,entityTypes:$.providerRegistry.getRegisteredTypes(),dataProvider:()=>lO0(A,$.providerRegistry,$.queueManager,$.retryTracker),actionHandler:async(Z,H)=>{let K=yt$.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return gt$(A,$,w,K.data,H)}},X=await A.messaging.send({type:v_,payload:B});if(!("success"in X)||!X.success)return;let Y=Et$.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function gt$(A,Q,$,w,B){if(!Q.providerRegistry.has(w.entityType))throw Error(`No publish provider registered for ${w.entityType}`);let X=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!X)throw Error(`Entity not found: ${w.entityType}:${w.entityId}`);if(w.type==="publish"){let H=await $.handler({entityType:w.entityType,id:w.entityId,...w.confirmation??{}},B);if("success"in H&&H.success===!0)await Q.publicationQueueService.complete(w.entityType,w.entityId),Q.retryTracker.clearRetries(w.entityId);return H}let Y=w.type==="queue"||w.type==="retry"?"publish":"update";A.permissions.assertEntityActionAllowed(w.entityType,Y,B);let Z=X.metadata.status;switch(w.type){case"queue":if(Z!=="draft")throw Error("Only draft entities can be queued");return Q.publicationQueueService.enqueue(w.entityType,w.entityId,{...B,authorization:"user"});case"remove":if(Z!=="queued")throw Error("Only queued entities can be removed from the queue");return await Q.publicationQueueService.remove(w.entityType,w.entityId),{success:!0};case"retry":if(Z!=="failed")throw Error("Only failed publications can be retried");return await Q.publicationQueueService.enqueue(w.entityType,w.entityId,{...B,authorization:"user"}),{success:!0};case"reorder":if(Z!=="queued")throw Error("Only queued entities can be reordered");return await Q.publicationQueueService.reorder(w.entityType,w.entityId,w.position),{success:!0}}}var Me2={name:"@brains/content-pipeline",version:"0.2.0-alpha.196",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/scheduler":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class JIA extends d6{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",Me2,A,We2)}async onRegister(A){this.pluginContext=A,this.queueManager=YI.createFresh(),this.publicationQueueService=new VIA(A,this.queueManager),this.providerRegistry=ZI.createFresh(),this.retryTracker=HI.createFresh(),this.publishAssetRegistry=KI.createFresh(),this.publishAssetPreflight=new uO0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Zo({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=_e2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),Ie2(A,{queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await this.publicationQueueService.reconcile(this.providerRegistry.getRegisteredTypes());let Q=await je2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await be2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,retryTracker:this.retryTracker,...Q?{managementUrl:Q}:{}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[cO0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),Wo(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),pO0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getPublicationQueueService(){return this.publicationQueueService}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),YI.resetInstance(),ZI.resetInstance(),HI.resetInstance(),KI.resetInstance()}}function FIA(A={}){return new JIA(A)}zA();h0();var ke2=W.object({accountId:W.string().describe("Cloudflare account ID"),apiToken:W.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:W.string().describe("Cloudflare Web Analytics site tag")}),LIA=W.object({cloudflare:ke2.optional()});zA();h0();var mt$=W.object({date:W.string().describe("Single date in YYYY-MM-DD format").optional(),days:W.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:W.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:W.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:W.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function ut$(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 Oe2(A,Q,$){let w=[];if(!$)return w;return w.push(e8(A,"query",`Query website analytics from Cloudflare.
8147
8147
 
8148
8148
  Date range options (use only one):
8149
8149
  - No params: yesterday only
@@ -8281,7 +8281,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,mt$,
8281
8281
  }
8282
8282
  }
8283
8283
  }
8284
- `,{...this.baseVariables(A),limit:A.limit??20})).map((w)=>({country:w.dimensions.countryName,visits:w.sum.visits}))}}var NIA=7,ct$=10;function xe2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=hV0(),$=QL1(NIA),w=Ql($),B=Ql(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:B}),A.getTopPages({startDate:w,endDate:B,limit:ct$})]);return{days:NIA,startDate:w,endDate:B,pageviews:X.pageviews,visitors:X.visitors,topPages:Y}}catch(X){return{error:X instanceof Error?X.message:"Failed to fetch analytics",days:NIA}}}}var Re2={name:"@brains/analytics",version:"0.2.0-alpha.195",description:"Analytics plugin for collecting website and social media metrics",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class ve2 extends d6{cloudflareClient;constructor(A={}){super("analytics",Re2,A,LIA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new IIA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",xe2(this.cloudflareClient))}async onReady(A){let Q=this.config.cloudflare?.siteTag;if(!Q)return;await A.messaging.send({type:"plugin:site-builder:head-script:register",payload:{pluginId:this.id,script:fe2(Q)}})}async getTools(){return Oe2(this.id,this.getContext(),this.cloudflareClient)}}function lt$(A={}){return new ve2(A)}var iO0=lt$;zA();h0();zA();h0();import{join as et$}from"path";p2();var Ce2="note",it$=new Set(["description","excerpt","summary","tagline","story"]);function dt$(A){if(A.endsWith("s"))return A;return $3(A)}function n90(A){return A===Ce2}function he2(A,Q){let $=A===Ce2?"Note":sj(A),w=Q?.label??$;return{label:w,pluralLabel:Q?.pluralName??dt$(w)}}function i90(A){return typeof A==="object"&&A!==null}function yy(A){if(!i90(A))return;let Q=A.def;return i90(Q)?Q:void 0}function Ee2(A){let Q=yy(A)?.type;return typeof Q==="string"?Q:void 0}function nt$(A){return typeof A==="function"?A():A}function _IA(A,Q=!1,$){let w=Ee2(A),B=yy(A);if(w==="optional"||w==="nullable")return _IA(B?.innerType,!0,$);if(w==="default")return _IA(B?.innerType,!0,nt$(B?.defaultValue));let X={inner:A,isOptional:Q};if($!==void 0)X.defaultValue=$;return X}function rt$(A){let Q=yy(A)?.entries;if(!i90(Q))return;let $=Object.values(Q);return $.every((w)=>typeof w==="string")?$:void 0}function ot$(A){let Q=yy(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function st$(A){let Q=yy(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some(($)=>{return yy($)?.format==="datetime"})}function at$(A){return A==="imageId"||A.endsWith("ImageId")}function tt$(A){if(!i90(A))return;let Q=A.shape;return i90(Q)?Q:void 0}function d90(A,Q){let{inner:$,isOptional:w,defaultValue:B}=_IA(Q),X=Ee2($),Y=B??ot$($),Z={name:A,label:sj(A),widget:"string",...w&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(at$(A))return{...Z,widget:"image"};if(st$($))return{...Z,widget:"datetime"};if(it$.has(A))return{...Z,widget:"text"};return{...Z,widget:"string"}}case"number":return{...Z,widget:"number"};case"boolean":return{...Z,widget:"boolean"};case"enum":{let H=rt$($);return{...Z,widget:"select",...H?{options:H}:{}}}case"array":{let H=yy($)?.element,K=d90("item",H);if(K.widget==="object"&&K.fields)return{...Z,widget:"list",fields:K.fields};return{...Z,widget:"list",field:{name:A,label:sj(A),widget:K.widget}}}case"object":{let H=Object.entries(tt$($)??{}).map(([K,U])=>d90(K,U));return{...Z,widget:"object",fields:H}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function Te2(A){return`<!doctype html>
8284
+ `,{...this.baseVariables(A),limit:A.limit??20})).map((w)=>({country:w.dimensions.countryName,visits:w.sum.visits}))}}var NIA=7,ct$=10;function xe2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=hV0(),$=QL1(NIA),w=Ql($),B=Ql(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:B}),A.getTopPages({startDate:w,endDate:B,limit:ct$})]);return{days:NIA,startDate:w,endDate:B,pageviews:X.pageviews,visitors:X.visitors,topPages:Y}}catch(X){return{error:X instanceof Error?X.message:"Failed to fetch analytics",days:NIA}}}}var Re2={name:"@brains/analytics",version:"0.2.0-alpha.196",description:"Analytics plugin for collecting website and social media metrics",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};class ve2 extends d6{cloudflareClient;constructor(A={}){super("analytics",Re2,A,LIA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new IIA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",xe2(this.cloudflareClient))}async onReady(A){let Q=this.config.cloudflare?.siteTag;if(!Q)return;await A.messaging.send({type:"plugin:site-builder:head-script:register",payload:{pluginId:this.id,script:fe2(Q)}})}async getTools(){return Oe2(this.id,this.getContext(),this.cloudflareClient)}}function lt$(A={}){return new ve2(A)}var iO0=lt$;zA();h0();zA();h0();import{join as et$}from"path";p2();var Ce2="note",it$=new Set(["description","excerpt","summary","tagline","story"]);function dt$(A){if(A.endsWith("s"))return A;return $3(A)}function n90(A){return A===Ce2}function he2(A,Q){let $=A===Ce2?"Note":sj(A),w=Q?.label??$;return{label:w,pluralLabel:Q?.pluralName??dt$(w)}}function i90(A){return typeof A==="object"&&A!==null}function yy(A){if(!i90(A))return;let Q=A.def;return i90(Q)?Q:void 0}function Ee2(A){let Q=yy(A)?.type;return typeof Q==="string"?Q:void 0}function nt$(A){return typeof A==="function"?A():A}function _IA(A,Q=!1,$){let w=Ee2(A),B=yy(A);if(w==="optional"||w==="nullable")return _IA(B?.innerType,!0,$);if(w==="default")return _IA(B?.innerType,!0,nt$(B?.defaultValue));let X={inner:A,isOptional:Q};if($!==void 0)X.defaultValue=$;return X}function rt$(A){let Q=yy(A)?.entries;if(!i90(Q))return;let $=Object.values(Q);return $.every((w)=>typeof w==="string")?$:void 0}function ot$(A){let Q=yy(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function st$(A){let Q=yy(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some(($)=>{return yy($)?.format==="datetime"})}function at$(A){return A==="imageId"||A.endsWith("ImageId")}function tt$(A){if(!i90(A))return;let Q=A.shape;return i90(Q)?Q:void 0}function d90(A,Q){let{inner:$,isOptional:w,defaultValue:B}=_IA(Q),X=Ee2($),Y=B??ot$($),Z={name:A,label:sj(A),widget:"string",...w&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(at$(A))return{...Z,widget:"image"};if(st$($))return{...Z,widget:"datetime"};if(it$.has(A))return{...Z,widget:"text"};return{...Z,widget:"string"}}case"number":return{...Z,widget:"number"};case"boolean":return{...Z,widget:"boolean"};case"enum":{let H=rt$($);return{...Z,widget:"select",...H?{options:H}:{}}}case"array":{let H=yy($)?.element,K=d90("item",H);if(K.widget==="object"&&K.fields)return{...Z,widget:"list",fields:K.fields};return{...Z,widget:"list",field:{name:A,label:sj(A),widget:K.widget}}}case"object":{let H=Object.entries(tt$($)??{}).map(([K,U])=>d90(K,U));return{...Z,widget:"object",fields:H}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function Te2(A){return`<!doctype html>
8285
8285
  <html lang="en" data-climate="paper">
8286
8286
  <head>
8287
8287
  <meta charset="utf-8" />
@@ -8339,7 +8339,7 @@ ${Zn}
8339
8339
  </html>`}var Ae$=et$(import.meta.dir,"..","dist","ui","cms-app.js"),Qe$=W.object({entityType:W.string(),id:W.string(),frontmatter:W.record(W.string(),W.unknown()),body:W.string().optional(),baseContentHash:W.string().optional()}),$e$=W.object({entityType:W.string(),frontmatter:W.record(W.string(),W.unknown()),body:W.string().optional()}),we$=W.object({id:W.string().trim().min(1),action:W.unknown()}),PIA={entityType:W.string(),body:W.string(),frontmatter:W.record(W.string(),W.unknown())},Be$=W.union([W.object({...PIA,variant:W.literal("rewrite").optional(),instruction:W.string().trim().min(1),selection:W.string().min(1).max(8000)}),W.object({...PIA,variant:W.literal("summarise"),targetField:W.string().trim().min(1),body:W.string().min(1)}),W.object({...PIA,variant:W.literal("tag-suggest"),targetField:W.string().trim().min(1),body:W.string().min(1)})]),ye2=W.object({suggestion:W.string()}),Xe$=W.object({suggestions:W.array(W.string().trim().min(1)).max(12)}),Ye$=W.object({selection:W.string().min(1).max(8000),instruction:W.string().trim().min(1).max(2000),agent:W.string().trim().min(1).max(253)}),Ze$=W.looseObject({response:W.string()}),We$=W.object({agents:W.array(W.object({id:W.string(),label:W.string()}))}),He$="file",ge2=10485760,Ke$=W.object({watchEnabled:W.boolean(),lastSync:W.string().nullable(),git:W.object({branch:W.string(),hasChanges:W.boolean(),ahead:W.number(),behind:W.number(),lastCommit:W.string().nullable(),remote:W.string().nullable()}).nullable()});function Se2(A){let{routePath:Q,getContext:$,resolveOperatorSession:w,getEntityDisplay:B,workspaceRegistry:X}=A,Y=`${Q}/assets/app.js`,Z=(K)=>`${Q}/api/${K}`,H=async(K)=>await w(K)?null:PQ({error:"Operator session required"},401);return[{path:Q,method:"GET",public:!0,handler:async(K)=>{if(!await w(K))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(Q)}`,"Cache-Control":"no-store"}});return new Response(Te2({assetPath:Y,surfaces:If($().webRoutes.getRoutes(),{activeId:"cms",self:{id:"cms",href:Q}}),sessionHref:`/logout?return_to=${encodeURIComponent(Q)}`}),{headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}},{path:Y,method:"GET",public:!0,handler:async()=>{let K=Bun.file(Ae$);if(!await K.exists())return new Response("CMS editor UI asset not built",{status:404});return new Response(K,{headers:{"Content-Type":"text/javascript; charset=utf-8","Cache-Control":"no-cache"}})}},{path:Z("types"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Ge$($(),B(),X)}},{path:Z("workspace"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return De$(X,K)}},{path:Z("workspace"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return qe$(X,K)}},{path:Z("schema"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return ze$($(),K)}},{path:Z("entities"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Ve$($(),K)}},{path:Z("entities"),method:"PUT",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Je$($(),K)}},{path:Z("entities"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Fe$($(),K)}},{path:Z("entities"),method:"DELETE",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Le$($(),K)}},{path:Z("upload"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Pe$($(),K,Z("upload"))}},{path:Z("assist"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Ie$($(),K)}},{path:Z("agents"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Ne$($())}},{path:Z("ask-agent"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return _e$($(),K)}},{path:Z("sync-status"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Ue$($())}}]}async function Ue$(A){let Q={directorySync:null,git:null},$=await A.messaging.send({type:"sync:status:request",payload:{}});if(!("success"in $)||!$.success)return PQ(Q);let w=Ke$.safeParse($.data);if(!w.success)return PQ(Q);return PQ({directorySync:{lastSync:w.data.lastSync,watching:w.data.watchEnabled},git:w.data.git})}async function Ge$(A,Q,$){let w=new Map((await A.entityService.getEntityCounts()).map((X)=>[X.entityType,X.count])),B=A.entityService.getEntityTypes().flatMap((X)=>{if(!A.entities.getEffectiveFrontmatterSchema(X))return[];let Z=A.entities.getAdapter(X);return[{entityType:X,label:he2(X,Q?.[X]).pluralLabel,isSingleton:Z?.isSingleton===!0,hasBody:Z?.hasBody!==!1,count:w.get(X)??0}]});return PQ({types:B,workspaces:$.listDescriptors()})}async function De$(A,Q){let $=new URL(Q.url).searchParams.get("id");if(!$)return PQ({error:"id query parameter is required"},400);let w=A.get($);if(!w)return PQ({error:`Unknown CMS workspace: ${$}`},404);try{return PQ({workspace:{id:w.id,rendererName:w.rendererName,data:await w.dataProvider()}})}catch(B){return PQ({error:B instanceof Error?B.message:"CMS workspace data provider failed"},502)}}async function qe$(A,Q){let $;try{$=we$.parse(await Q.json())}catch{return PQ({error:"Invalid workspace action payload"},400)}let w=A.get($.id);if(!w)return PQ({error:`Unknown CMS workspace: ${$.id}`},404);if(!w.actionHandler)return PQ({error:`CMS workspace ${$.id} does not provide actions`},405);let B={interfaceType:"cms",userId:"operator",userPermissionLevel:"anchor"};try{return PQ({result:await w.actionHandler($.action,B)})}catch(X){return PQ({error:X instanceof Error?X.message:"CMS workspace action failed"},400)}}function ze$(A,Q){let $=new URL(Q.url).searchParams.get("type");if(!$)return PQ({error:"type query parameter is required"},400);let w=A.entities.getEffectiveFrontmatterSchema($);if(!w)return PQ({error:`Unknown entity type: ${$}`},404);let B=A.entities.getAdapter($),X=n90($),Y=X?[]:Object.entries(w.shape).map(([Z,H])=>d90(Z,H));return PQ({entityType:$,format:X?"raw":"frontmatter",isSingleton:B?.isSingleton===!0,hasBody:X||B?.hasBody!==!1,fields:Y})}async function Ve$(A,Q){let $=new URL(Q.url).searchParams,w=$.get("type");if(!w)return PQ({error:"type query parameter is required"},400);if(!A.entities.getEffectiveFrontmatterSchema(w))return PQ({error:`Unknown entity type: ${w}`},404);let B=$.get("id");if(B){let Y=await A.entityService.getEntity({entityType:w,id:B});if(!Y)return PQ({error:`Entity not found: ${B}`},404);let{frontmatter:Z,body:H}=bIA(w,Y.content);return PQ({entity:{id:Y.id,entityType:Y.entityType,frontmatter:Z,body:H,contentHash:Y.contentHash,created:Y.created,updated:Y.updated}})}let X=await A.entityService.listEntities({entityType:w});return PQ({entities:X.map((Y)=>({id:Y.id,entityType:Y.entityType,frontmatter:bIA(w,Y.content).frontmatter,updated:Y.updated}))})}async function Je$(A,Q){let $;try{$=Qe$.parse(await Q.json())}catch{return PQ({error:"Invalid update payload"},400)}let{entityType:w,id:B}=$,X=A.entities.getEffectiveFrontmatterSchema(w);if(!X)return PQ({error:`Unknown entity type: ${w}`},404);let Y=me2(A,w,$.body);if(Y)return Y;let Z=n90(w);if(Z&&Object.keys($.frontmatter).length>0)return PQ({error:`Entity type ${w} is raw markdown without frontmatter`},400);let H=Z?{success:!0,data:{}}:X.safeParse($.frontmatter);if(!H.success)return PQ({error:"Invalid frontmatter",issues:H.error.issues},400);let K=await A.entityService.getEntity({entityType:w,id:B});if(!K)return PQ({error:`Entity not found: ${B}`},404);if($.baseContentHash!==void 0&&$.baseContentHash!==K.contentHash)return PQ({error:"This entry changed since it was opened \u2014 likely updated by "+"another writer (an agent, or a git import via directory-sync). Reload to review before saving again.",currentContentHash:K.contentHash},409);let U=$.body??bIA(w,K.content).body,G=Z?U:i7(U,H.data),D=A.entities.getAdapter(w)?.fromMarkdown(G),q={...K,...D,id:K.id,entityType:K.entityType,content:G},J=await A.entityService.updateEntity({entity:q});return PQ({entityId:J.entityId,jobId:J.jobId,skipped:J.skipped})}async function Fe$(A,Q){let $;try{$=$e$.parse(await Q.json())}catch{return PQ({error:"Invalid create payload"},400)}let{entityType:w}=$,B=A.entities.getEffectiveFrontmatterSchema(w);if(!B)return PQ({error:`Unknown entity type: ${w}`},404);let X=me2(A,w,$.body);if(X)return X;let Y=n90(w);if(Y&&Object.keys($.frontmatter).length>0)return PQ({error:`Entity type ${w} is raw markdown without frontmatter`},400);let Z=Y?{success:!0,data:{}}:B.safeParse($.frontmatter);if(!Z.success)return PQ({error:"Invalid frontmatter",issues:Z.error.issues},400);let H=Y?$.body??"":i7($.body??"",Z.data),K=A.entities.getAdapter(w)?.fromMarkdown(H),U=await A.entityService.createEntity({entity:{...K,entityType:w,content:H,metadata:K?.metadata??{}}});return PQ({entityId:U.entityId,jobId:U.jobId},201)}async function Le$(A,Q){let $=new URL(Q.url).searchParams,w=$.get("type"),B=$.get("id");if(!w||!B)return PQ({error:"type and id query parameters are required"},400);if(!await A.entityService.getEntity({entityType:w,id:B}))return PQ({error:`Entity not found: ${B}`},404);let Y=await A.entityService.deleteEntity({entityType:w,id:B});return PQ({deleted:Y})}async function Ie$(A,Q){let $;try{$=Be$.parse(await Q.json())}catch{return PQ({error:"Invalid assist payload or selection length"},400)}let w=A.entities.getEffectiveFrontmatterSchema($.entityType);if(!w)return PQ({error:`Unknown entity type: ${$.entityType}`},404);if($.variant==="summarise"||$.variant==="tag-suggest"){let Y=w.shape[$.targetField];if(!Y)return PQ({error:`Unknown frontmatter field: ${$.targetField}`},400);let Z=d90($.targetField,Y);if(!($.variant==="summarise"?Z.widget==="string"||Z.widget==="text":Z.widget==="list"&&Z.field?.widget==="string"))return PQ({error:`Field ${$.targetField} is incompatible with ${$.variant}`},400);let K=["You are editing CMS frontmatter from an existing markdown body.",`Entity type: ${$.entityType}`,`Target field: ${$.targetField}`,`Existing frontmatter JSON: ${JSON.stringify($.frontmatter)}`,"","Full markdown body:",$.body];if($.variant==="summarise"){let{object:G}=await A.ai.generateObject(["Summarise the body for the target frontmatter field.","Return only the field value in the suggestion field.",...K].join(`
8340
8340
  `),ye2);return PQ({variant:$.variant,targetField:$.targetField,suggestion:G.suggestion})}let{object:U}=await A.ai.generateObject(["Suggest tags for the target frontmatter field.","Return concise tag strings in the suggestions field without duplicates.",...K].join(`
8341
8341
  `),Xe$);return PQ({variant:$.variant,targetField:$.targetField,suggestions:[...new Set(U.suggestions)]})}let B=["You are editing markdown for the CMS.","Rewrite only the selected text according to the instruction.","Return only replacement markdown in the suggestion field.","Do not include commentary, code fences, or unchanged surrounding body text.","",`Entity type: ${$.entityType}`,`Frontmatter JSON: ${JSON.stringify($.frontmatter)}`,`Instruction: ${$.instruction}`,"","Selected markdown:",$.selection,"","Full body for context:",$.body].join(`
8342
- `),{object:X}=await A.ai.generateObject(B,ye2);return PQ({suggestion:X.suggestion})}async function Ne$(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return PQ({agents:[]});let $=We$.safeParse(Q.data);return PQ($.success?$.data:{agents:[]})}async function _e$(A,Q){let $;try{$=Ye$.parse(await Q.json())}catch{return PQ({error:"Invalid agent ask payload or selection length"},400)}let w=await A.messaging.send({type:"a2a:call:request",payload:$});if(!("success"in w)||!w.success){let X="error"in w&&typeof w.error==="string"?w.error:"Agent call failed",Y=X.startsWith("No handler found");return PQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if(w.data===void 0)return PQ({error:"Agent asking is unavailable"},503);let B=Ze$.safeParse(w.data);if(!B.success)return PQ({error:"Invalid response from agent"},502);return PQ({agentId:$.agent,response:B.data.response})}async function Pe$(A,Q,$){let w=Number(Q.headers.get("content-length"));if(Number.isFinite(w)&&w>ge2)return PQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return PQ({error:"Invalid multipart upload"},400)}let X=B.get(He$);if(!(X instanceof File))return PQ({error:"Missing upload file"},400);if(X.size>ge2)return PQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return PQ({error:`No handler accepts uploads of type ${X.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:$}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),K=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!K.success)return PQ({error:K.error},502);return PQ({entityId:K.data.entityId,jobId:K.data.jobId},201)}function me2(A,Q,$){if($===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return PQ({error:`Entity type ${Q} does not have a body`},400);return null}function bIA(A,Q){if(n90(A))return{frontmatter:{},body:Q};try{let $=MQ(Q,W.record(W.string(),W.unknown()));return{frontmatter:$.metadata,body:$.content}}catch{return{frontmatter:{},body:Q}}}function PQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}h0();var be$=W.object({id:W.string().trim().min(1),pluginId:W.string().trim().min(1),label:W.string().trim().min(1),rendererName:W.enum(["PublishingWorkspace","SiteWorkspace","DirectorySyncWorkspace"]),priority:W.number().int(),entityTypes:W.array(W.string().trim().min(1)).default([]),dataProvider:W.custom((A)=>typeof A==="function",{message:"Expected CMS workspace data provider function"}),actionHandler:W.custom((A)=>typeof A==="function",{message:"Expected CMS workspace action handler function"}).optional()});class jIA{workspaces=new Map;register(A){let Q=be$.parse(A);if(this.workspaces.has(Q.id))throw Error(`CMS workspace already registered: ${Q.id}`);let $={id:Q.id,pluginId:Q.pluginId,label:Q.label,rendererName:Q.rendererName,priority:Q.priority,entityTypes:Q.entityTypes,dataProvider:Q.dataProvider,...Q.actionHandler?{actionHandler:Q.actionHandler}:{}};return this.workspaces.set($.id,$),$}get(A){return this.workspaces.get(A)}listDescriptors(){return Array.from(this.workspaces.values()).sort((A,Q)=>A.priority-Q.priority||A.id.localeCompare(Q.id)).map(({id:A,pluginId:Q,label:$,rendererName:w,priority:B,entityTypes:X})=>({id:A,pluginId:Q,label:$,rendererName:w,priority:B,entityTypes:X}))}}var ue2={name:"@brains/cms",version:"0.2.0-alpha.195",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@codemirror/lang-markdown":"^6.5.0","@codemirror/language":"^6.12.4","@codemirror/state":"^6.7.1","@codemirror/view":"^6.43.6","@lezer/highlight":"^1.2.3","@tanstack/react-query":"^5.0.0",react:"^19.2.7","react-dom":"^19.2.7",streamdown:"^2.5.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};var Me$=W.looseObject({label:W.string().optional(),pluralName:W.string().optional()}),ke$=W.object({entityDisplay:W.record(W.string(),Me$).optional(),routePath:W.string().default("/cms")});class MIA extends d6{workspaceRegistry=new jIA;constructor(A={}){super("cms",ue2,A,ke$)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"}),A.messaging.subscribe(v_,async(Q)=>{try{let $=this.workspaceRegistry.register(Q.payload);return{success:!0,data:{workspaceUrl:`${this.config.routePath}#/workspace/${encodeURIComponent($.id)}`}}}catch($){return{success:!1,error:$ instanceof Error?$.message:String($)}}})}getWebRoutes(){return Se2({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:Oe$,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay,workspaceRegistry:this.workspaceRegistry})}}function gy(A={}){return new MIA(A)}async function Oe$(A){return Boolean(await xY()?.getOperatorSession(A))}zA();h0();zA();h0();var dO0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],fe$=new Set(dO0),xe$=W.enum(["public","trusted","anchor"]);function kIA(A){return fe$.has(A)}var ce2=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),pe2=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number().default(50),section:W.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:W.string(),visibility:xe$.default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(ce2).max(4).optional()});class nO0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let $={...pe2.parse(A),dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{},...A.component?{component:A.component}:{},...A.clientStyles?{clientStyles:A.clientStyles}:{},...A.clientScript?{clientScript:A.clientScript}:{}},w=`${$.pluginId}:${$.id}`;this.widgets.set(w,$),this.logger.debug("Dashboard widget registered",{key:w,title:$.title,rendererName:$.rendererName,group:$.group})}unregister(A,Q){if(Q){this.widgets.delete(`${A}:${Q}`);return}for(let $ of this.widgets.keys())if($.startsWith(`${A}:`))this.widgets.delete($)}get(A,Q){return this.widgets.get(`${A}:${Q}`)}list(A={}){let Q=typeof A==="string"?{section:A}:A,$=Q.permissionLevel??"public";return Array.from(this.widgets.values()).filter((w)=>!Q.section||w.section===Q.section).filter((w)=>$9.hasPermission($,w.visibility)).sort((w,B)=>w.priority-B.priority)}get size(){return this.widgets.size}}EZ();var le2=`/* Deprecated aliases for custom widgets authored before WidgetTabs. */
8342
+ `),{object:X}=await A.ai.generateObject(B,ye2);return PQ({suggestion:X.suggestion})}async function Ne$(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return PQ({agents:[]});let $=We$.safeParse(Q.data);return PQ($.success?$.data:{agents:[]})}async function _e$(A,Q){let $;try{$=Ye$.parse(await Q.json())}catch{return PQ({error:"Invalid agent ask payload or selection length"},400)}let w=await A.messaging.send({type:"a2a:call:request",payload:$});if(!("success"in w)||!w.success){let X="error"in w&&typeof w.error==="string"?w.error:"Agent call failed",Y=X.startsWith("No handler found");return PQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if(w.data===void 0)return PQ({error:"Agent asking is unavailable"},503);let B=Ze$.safeParse(w.data);if(!B.success)return PQ({error:"Invalid response from agent"},502);return PQ({agentId:$.agent,response:B.data.response})}async function Pe$(A,Q,$){let w=Number(Q.headers.get("content-length"));if(Number.isFinite(w)&&w>ge2)return PQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return PQ({error:"Invalid multipart upload"},400)}let X=B.get(He$);if(!(X instanceof File))return PQ({error:"Missing upload file"},400);if(X.size>ge2)return PQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return PQ({error:`No handler accepts uploads of type ${X.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:$}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),K=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!K.success)return PQ({error:K.error},502);return PQ({entityId:K.data.entityId,jobId:K.data.jobId},201)}function me2(A,Q,$){if($===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return PQ({error:`Entity type ${Q} does not have a body`},400);return null}function bIA(A,Q){if(n90(A))return{frontmatter:{},body:Q};try{let $=MQ(Q,W.record(W.string(),W.unknown()));return{frontmatter:$.metadata,body:$.content}}catch{return{frontmatter:{},body:Q}}}function PQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}h0();var be$=W.object({id:W.string().trim().min(1),pluginId:W.string().trim().min(1),label:W.string().trim().min(1),rendererName:W.enum(["PublishingWorkspace","SiteWorkspace","DirectorySyncWorkspace"]),priority:W.number().int(),entityTypes:W.array(W.string().trim().min(1)).default([]),dataProvider:W.custom((A)=>typeof A==="function",{message:"Expected CMS workspace data provider function"}),actionHandler:W.custom((A)=>typeof A==="function",{message:"Expected CMS workspace action handler function"}).optional()});class jIA{workspaces=new Map;register(A){let Q=be$.parse(A);if(this.workspaces.has(Q.id))throw Error(`CMS workspace already registered: ${Q.id}`);let $={id:Q.id,pluginId:Q.pluginId,label:Q.label,rendererName:Q.rendererName,priority:Q.priority,entityTypes:Q.entityTypes,dataProvider:Q.dataProvider,...Q.actionHandler?{actionHandler:Q.actionHandler}:{}};return this.workspaces.set($.id,$),$}get(A){return this.workspaces.get(A)}listDescriptors(){return Array.from(this.workspaces.values()).sort((A,Q)=>A.priority-Q.priority||A.id.localeCompare(Q.id)).map(({id:A,pluginId:Q,label:$,rendererName:w,priority:B,entityTypes:X})=>({id:A,pluginId:Q,label:$,rendererName:w,priority:B,entityTypes:X}))}}var ue2={name:"@brains/cms",version:"0.2.0-alpha.196",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@codemirror/lang-markdown":"^6.5.0","@codemirror/language":"^6.12.4","@codemirror/state":"^6.7.1","@codemirror/view":"^6.43.6","@lezer/highlight":"^1.2.3","@tanstack/react-query":"^5.0.0",react:"^19.2.7","react-dom":"^19.2.7",streamdown:"^2.5.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};var Me$=W.looseObject({label:W.string().optional(),pluralName:W.string().optional()}),ke$=W.object({entityDisplay:W.record(W.string(),Me$).optional(),routePath:W.string().default("/cms")});class MIA extends d6{workspaceRegistry=new jIA;constructor(A={}){super("cms",ue2,A,ke$)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"}),A.messaging.subscribe(v_,async(Q)=>{try{let $=this.workspaceRegistry.register(Q.payload);return{success:!0,data:{workspaceUrl:`${this.config.routePath}#/workspace/${encodeURIComponent($.id)}`}}}catch($){return{success:!1,error:$ instanceof Error?$.message:String($)}}})}getWebRoutes(){return Se2({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:Oe$,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay,workspaceRegistry:this.workspaceRegistry})}}function gy(A={}){return new MIA(A)}async function Oe$(A){return Boolean(await xY()?.getOperatorSession(A))}zA();h0();zA();h0();var dO0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],fe$=new Set(dO0),xe$=W.enum(["public","trusted","anchor"]);function kIA(A){return fe$.has(A)}var ce2=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),pe2=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number().default(50),section:W.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:W.string(),visibility:xe$.default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(ce2).max(4).optional()});class nO0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let $={...pe2.parse(A),dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{},...A.component?{component:A.component}:{},...A.clientStyles?{clientStyles:A.clientStyles}:{},...A.clientScript?{clientScript:A.clientScript}:{}},w=`${$.pluginId}:${$.id}`;this.widgets.set(w,$),this.logger.debug("Dashboard widget registered",{key:w,title:$.title,rendererName:$.rendererName,group:$.group})}unregister(A,Q){if(Q){this.widgets.delete(`${A}:${Q}`);return}for(let $ of this.widgets.keys())if($.startsWith(`${A}:`))this.widgets.delete($)}get(A,Q){return this.widgets.get(`${A}:${Q}`)}list(A={}){let Q=typeof A==="string"?{section:A}:A,$=Q.permissionLevel??"public";return Array.from(this.widgets.values()).filter((w)=>!Q.section||w.section===Q.section).filter((w)=>$9.hasPermission($,w.visibility)).sort((w,B)=>w.priority-B.priority)}get size(){return this.widgets.size}}EZ();var le2=`/* Deprecated aliases for custom widgets authored before WidgetTabs. */
8343
8343
  .view-tabs {
8344
8344
  display: flex;
8345
8345
  gap: 24px;
@@ -10394,7 +10394,7 @@ ${le2}`;var oO0=`(function () {
10394
10394
  `);function ge$(A){return`${A.replace(/\/+$/,"")}/assets`}class OIA{basePath;assets=new Map;dashboardStylesUrl;dashboardScriptUrl;constructor(A){this.basePath=ge$(A),this.dashboardStylesUrl=this.register("dashboard","css","text/css; charset=utf-8",rO0),this.dashboardScriptUrl=this.register("dashboard","js","text/javascript; charset=utf-8",ye$)}createRenderUrls(A){return{dashboardStyles:this.dashboardStylesUrl,dashboardScript:this.dashboardScriptUrl,...A.themeCSS!==void 0&&{themeStyles:this.register("theme","css","text/css; charset=utf-8",A.themeCSS)},widgetStyles:Array.from(new Set(A.widgetStyles)).map((Q)=>this.register("widget","css","text/css; charset=utf-8",Q)),widgetScripts:Array.from(new Set(A.widgetScripts)).map((Q)=>this.register("widget","js","text/javascript; charset=utf-8",Q))}}getRoutes(){return Array.from(this.assets.values()).map((A)=>({path:A.path,method:"GET",public:!0,handler:(Q)=>{let $={"Cache-Control":Te$,"Content-Type":A.contentType,ETag:A.etag,"X-Content-Type-Options":"nosniff"};if(Q.headers.get("If-None-Match")===A.etag)return new Response(null,{status:304,headers:$});return new Response(A.content,{headers:$})}}))}register(A,Q,$,w){let B=u6(w),X=`${this.basePath}/${A}.${B}.${Q}`;if(!this.assets.has(X))this.assets.set(X,{path:X,content:w,contentType:$,etag:`"${B}"`});return X}}class sO0{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(A={}){let Q={},$=A.widgets??this.registry.list({...A.permissionLevel!==void 0&&{permissionLevel:A.permissionLevel}}),w=await Promise.allSettled($.map(async(B)=>{let X=await B.dataProvider(),{dataProvider:Y,digestProvider:Z,component:H,clientStyles:K,clientScript:U,visibility:G="public",...D}=B;return{key:`${B.pluginId}:${B.id}`,widget:{...D,visibility:G,...this.deriveLiveDigest(B,X)},data:X}}));for(let B=0;B<w.length;B++){let X=w[B],Y=$[B];if(!X||!Y)continue;if(X.status==="fulfilled")Q[X.value.key]={widget:X.value.widget,data:X.value.data};else this.logger.error("Widget data provider failed",{widgetId:Y.id,pluginId:Y.pluginId,error:eA(X.reason)})}return{widgets:Q}}deriveLiveDigest(A,Q){if(!A.digestProvider)return{};try{let $=A.digestProvider(Q);return{...$.digest!==void 0&&{digest:$.digest},...$.needsOperator!==void 0&&{needsOperator:$.needsOperator}}}catch($){return this.logger.error("Widget digest provider failed",{widgetId:A.id,pluginId:A.pluginId,error:eA($)}),{}}}async fetch(A,Q,$){return await this.getDashboardData()}}import{render as M08}from"preact-render-to-string";p2();import{jsxDEV as aO0}from"preact/jsx-dev-runtime";function Se$(A,Q){let $=A.endpoints.find((w)=>w.label.toLowerCase().includes("doc"));if(!$)return null;return oS($.url,Q)}function oe2(A){let{title:Q,appInfo:$,baseUrl:w}=A,B=Se$($,w);return aO0("footer",{class:"colophon",children:[aO0("span",{class:"colophon-mark",children:[Q," \xB7 dashboard"]},void 0,!0,void 0,this),aO0("span",{class:"colophon-actions",children:B&&aO0("a",{href:B,target:"_blank",rel:"noopener noreferrer",children:"Docs \u2197"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as aY}from"preact/jsx-dev-runtime";function se2({dashboardPath:A,surfaces:Q,operatorAccess:$}){let w=$?.isOperator?$.logoutUrl:$?.loginUrl??"/login",B=$?.isOperator?"Operator":"Visitor",X=$?.isOperator?"Sign out":"Sign in";return aY("header",{class:"console-strip","aria-label":"Operator surfaces",children:[aY("a",{class:"console-mark",href:A,"aria-label":"Dashboard home",children:[aY("span",{class:"pulse"},void 0,!1,void 0,this),aY("span",{children:["Brain"," ",aY("span",{class:"console-mark-long",children:["\xB7 ",aY("b",{children:"Console"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),aY("nav",{class:"surface-nav","aria-label":"Console surfaces",children:Q.map((Y)=>aY("a",{class:Y.isActive?"surface-nav-link is-active":"surface-nav-link",href:Y.href,children:Y.label},Y.id,!1,void 0,this))},void 0,!1,void 0,this),aY("button",{class:"command-chip",type:"button","aria-label":"Search or jump",children:[aY("span",{class:"command-chip-hint",children:"Search or jump\u2026"},void 0,!1,void 0,this),aY("kbd",{children:"\u2318K"},void 0,!1,void 0,this),aY("span",{class:"command-chip-icon","aria-hidden":"true",children:"\u2315"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aY("button",{id:"climateToggle",class:"climate-chip",type:"button","aria-label":"Toggle climate",children:"\u25D0"},void 0,!1,void 0,this),aY("a",{class:$?.isOperator?"session-chip":"session-chip is-visitor",href:w,"aria-label":`${B} \xB7 ${X}`,children:[aY("span",{children:B},void 0,!1,void 0,this),aY("strong",{children:X},void 0,!1,void 0,this),aY("span",{class:"session-chip-avatar","aria-hidden":"true",children:$?.isOperator?"OP":"VI"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var me$=["knowledge","publishing","network","system"],ue$={knowledge:"Knowledge",publishing:"Publishing",network:"Network",system:"System"};function Ho(A){let Q=ue$[A];if(Q)return Q;return A.split(/[-_\s]+/).filter(Boolean).map(($)=>`${$.slice(0,1).toUpperCase()}${$.slice(1)}`).join(" ")}function tO0(A){let Q=new Map(me$.map(($,w)=>[$,w]));return[...A].sort(($,w)=>{let B=Q.get($),X=Q.get(w);if(B!==void 0||X!==void 0)return(B??Number.MAX_SAFE_INTEGER)-(X??Number.MAX_SAFE_INTEGER);return Ho($).localeCompare(Ho(w))})}import{jsxDEV as Ko}from"preact/jsx-dev-runtime";function fIA(){return{primary:[],secondary:[],sidebar:[]}}function eO0(A){return[...A.widgets.primary,...A.widgets.secondary,...A.widgets.sidebar]}function Af0(A){return eO0(A).length}function ce$(A){return eO0(A).reduce((Q,$)=>Q+($.widget.needsOperator??0),0)}function pe$(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function ae2(A){let Q=new Map;for(let w of Object.values(A)){let B=w.widget.group,X=Q.get(B)??fIA();X[w.widget.section].push(w),Q.set(B,X)}for(let w of Q.values())for(let B of Object.keys(w))w[B].sort((X,Y)=>X.widget.priority-Y.widget.priority);let $=new Map;for(let w of["knowledge","system"])if(!Q.has(w))Q.set(w,fIA());return tO0(Array.from(Q.keys())).map((w)=>{let B=pe$(w),X=$.get(B)??0,Y=Q.get(w)??fIA(),Z={id:X===0?B:`${B}-${X+1}`,group:w,label:Ho(w),widgets:Y,widgetCount:0,needsOperator:0};return $.set(B,X+1),{...Z,widgetCount:Af0(Z),needsOperator:ce$(Z)}})}function te2({tabs:A}){return Ko("nav",{class:"dashboard-tabs","aria-label":"Dashboard sections",role:"tablist",children:[Ko("a",{id:"dashboard-tab-overview",class:"dashboard-tab is-active",href:"#overview",role:"tab","aria-selected":"true","data-dashboard-tab-link":"overview","data-ui-tab":"overview",children:"Overview"},void 0,!1,void 0,this),A.map((Q)=>Ko("a",{id:`dashboard-tab-${Q.id}`,class:"dashboard-tab",href:`#${Q.id}`,role:"tab","aria-selected":"false","data-dashboard-tab-link":Q.id,"data-ui-tab":Q.id,children:[Ko("span",{children:Q.label},void 0,!1,void 0,this),Q.needsOperator>0?Ko("span",{class:"tab-badge tab-badge--needs",children:Q.needsOperator},void 0,!1,void 0,this):Q.widgetCount>0?Ko("span",{class:"tab-badge tab-badge--muted",children:Q.widgetCount},void 0,!1,void 0,this):null]},Q.id,!0,void 0,this))]},void 0,!0,void 0,this)}import{jsxDEV as Sy,Fragment as ee2}from"preact/jsx-dev-runtime";function le$({title:A}){let Q=A.trim(),$=Q.lastIndexOf(" ");if($<=0)return Sy(ee2,{children:Q},void 0,!1,void 0,this);return Sy(ee2,{children:[Q.slice(0,$)," ",Sy("em",{children:Q.slice($+1)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function A0Q(A){let{title:Q,tagline:$}=A;return Sy("header",{class:"masthead",children:[Sy("h1",{class:"brand",children:Sy(le$,{title:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&Sy("p",{class:"tagline",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as m$,Fragment as Q0Q}from"preact/jsx-dev-runtime";import{createElement as xIA}from"preact";function UI(...A){return A.filter(Boolean).join(" ")}function RIA(A,Q){return`widget-${`${A}-${Q}`.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"custom"}`}function DX({title:A,source:Q,subtitle:$,children:w}){return m$("div",{class:"card-head",children:[m$("span",{class:"card-title",children:A},void 0,!1,void 0,this),Q?m$("span",{class:"card-from",children:Q},void 0,!1,void 0,this):$?m$("span",{class:"card-subtitle",children:$},void 0,!1,void 0,this):w]},void 0,!0,void 0,this)}function qx({items:A}){return m$("dl",{class:"kv",children:A.map((Q,$)=>m$("div",{class:"kv-row",children:[m$("dt",{children:Q.label},void 0,!1,void 0,this),m$("dd",{children:Q.value},void 0,!1,void 0,this)]},$,!0,void 0,this))},void 0,!1,void 0,this)}function Rb({children:A="Nothing to show yet.",className:Q}){return m$("p",{class:UI("muted",Q),children:A},void 0,!1,void 0,this)}var qD=Rb;function r90({label:A,children:Q,className:$}){return m$("nav",{class:UI("widget-actions",$),"aria-label":A,children:Q},void 0,!1,void 0,this)}function o90({href:A,children:Q,external:$=!1,emphasis:w="secondary"}){return m$("a",{class:UI("widget-action",`widget-action--${w}`),href:A,...$?{target:"_blank",rel:"noreferrer"}:{},children:[m$("span",{children:Q},void 0,!1,void 0,this),m$("span",{class:"widget-action-arrow","aria-hidden":"true",children:$?"\u2197":"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Uo({id:A,label:Q,defaultValue:$,tabs:w,variant:B="line",compact:X=!1,stateAttribute:Y,rootClassName:Z,rootProps:H}){let K=B==="line"?"widget-tabs":UI("widget-filter-tabs",X&&"widget-filter-tabs--compact"),U=B==="line"?"widget-tab":"widget-filter-tab",G=B==="line"?"widget-tab-count":"widget-filter-count",D=B==="pill"?"widget-filter-label":void 0;return m$("div",{...H,class:Z,"data-ui-tabs":!0,"data-ui-tabs-default":$,...Y?{"data-ui-tabs-state-attribute":Y}:{},children:[m$("div",{class:K,role:"tablist","aria-label":Q,children:w.map((q)=>{let J=q.value===$,F=`${A}-tab-${q.value}`,L=`${A}-panel-${q.value}`;return xIA("button",{...q.triggerProps,id:F,key:q.value,class:UI(U,J&&"is-active"),type:"button",role:"tab","data-ui-tab":q.value,"aria-controls":L,"aria-selected":J?"true":"false"},B==="pill"?m$(Q0Q,{children:[q.count!==void 0&&m$("span",{class:G,children:q.count},void 0,!1,void 0,this),m$("span",{class:D,children:q.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this):m$(Q0Q,{children:[q.label,q.count!==void 0&&m$("span",{class:G,children:q.count},void 0,!1,void 0,this)]},void 0,!0,void 0,this))})},void 0,!1,void 0,this),w.map((q)=>{let J=q.value===$;return xIA("div",{...q.panelProps,id:`${A}-panel-${q.value}`,key:q.value,class:UI(q.panelClassName,J&&"is-active"),"data-ui-panel":q.value,role:"tabpanel","aria-labelledby":`${A}-tab-${q.value}`,hidden:!J},q.content)})]},void 0,!0,void 0,this)}function vIA({label:A,defaultValue:Q,options:$,children:w,emptyState:B,className:X,allValue:Y="all"}){return m$("div",{class:X,"data-ui-filter":!0,"data-ui-filter-default":Q,"data-ui-filter-all":Y,children:[m$("div",{class:"widget-filter-tabs widget-filter-tabs--compact","aria-label":A,children:$.map((Z)=>{let H=Z.value===Q;return xIA("button",{...Z.triggerProps,key:Z.value,class:UI("widget-filter-tab",H&&"is-active",Z.tone==="gap"&&"is-gap"),type:"button","data-ui-filter-value":Z.value,"aria-pressed":H?"true":"false"},Z.count!==void 0&&m$("span",{class:"widget-filter-count",children:Z.count},void 0,!1,void 0,this),m$("span",{class:"widget-filter-label",children:Z.label},void 0,!1,void 0,this))})},void 0,!1,void 0,this),w,B!==void 0&&m$("div",{"data-ui-filter-empty":!0,hidden:!0,children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function zx({children:A,className:Q}){return m$("ul",{class:UI("list",Q),children:A},void 0,!1,void 0,this)}function $0Q({segments:A}){if(A.length===0)return null;return m$("span",{class:"list-meta-text",children:A.map((Q,$)=>m$("span",{children:[$>0&&m$("span",{class:"sep",children:"\xB7"},void 0,!1,void 0,this),Q]},`${Q}:${$}`,!0,void 0,this))},void 0,!1,void 0,this)}function w0Q({tags:A}){if(A.length===0)return null;return m$("div",{class:"list-tags",children:A.map((Q,$)=>m$("span",{class:"tag",children:Q},`${Q}:${$}`,!1,void 0,this))},void 0,!1,void 0,this)}function my({children:A,tone:Q="plain"}){let $={plain:"",warn:"pill--warn",error:"pill--err",ok:"pill--ok",muted:"pill--mute"}[Q];return m$("span",{class:UI("pill",$),children:A},void 0,!1,void 0,this)}function Vx({title:A,description:Q,meta:$=[],tags:w=[],trailing:B,filterValues:X,className:Y,itemProps:Z}){return m$("li",{...Z,class:UI("list-item",Y),...X?{"data-ui-filter-values":JSON.stringify(X)}:{},children:[m$("div",{class:"list-main",children:[m$("span",{class:"list-name",children:A},void 0,!1,void 0,this),Q&&m$("span",{class:"list-desc",children:Q},void 0,!1,void 0,this),m$($0Q,{segments:$},void 0,!1,void 0,this),m$(w0Q,{tags:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B&&m$("div",{class:"list-meta",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function B0Q(A){let Q=new Date(A);if(Number.isNaN(Q.getTime()))return"\u2014";return Q.toLocaleString("en",{month:"short",day:"2-digit",hour:"2-digit",minute:"2-digit"})}function s90(A){let Q=new Date(A);if(Number.isNaN(Q.getTime()))return"\u2014";return Q.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"})}import{jsxDEV as w8}from"preact/jsx-dev-runtime";function Qf0(A){return A.indexStatus?.ready??A.indexReady??A.appInfo.embeddings>0}function ie$(A){let Q=(A.activeEmbeddingJobs??0)+(A.missingEmbeddings??0)+(A.staleEmbeddings??0);if(A.ready&&!A.degraded)return 100;if(A.ready)return 92;if(Q===0)return 50;return Math.max(8,Math.min(88,100-Q*12))}function de$(A){return["Semantic index",A.ready?A.degraded?"ready, degraded":"ready":"pending",A.activeEmbeddingJobs!==void 0?`${A.activeEmbeddingJobs} active`:void 0,A.missingEmbeddings!==void 0?`${A.missingEmbeddings} missing`:void 0,A.staleEmbeddings!==void 0?`${A.staleEmbeddings} stale`:void 0,A.failedEmbeddings!==void 0?`${A.failedEmbeddings} failed`:void 0].filter(Boolean).join(" \xB7 ")}function ne$({status:A}){let Q=ie$(A),$=A.ready?A.degraded?"Degraded":"Ready":"Indexing";return w8("div",{class:"index-gauge",style:`--index-percent: ${Q}%`,children:[w8("div",{class:"index-gauge-ring","aria-hidden":"true",children:w8("span",{children:[Q,"%"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),w8("div",{class:"index-gauge-copy",children:[w8("strong",{children:$},void 0,!1,void 0,this),w8("span",{children:de$(A)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function X0Q({input:A}){let Q=Qf0(A);return w8("section",{class:"card semantic-index-card",children:[w8(DX,{title:"Semantic index",source:"entity-service"},void 0,!1,void 0,this),A.indexStatus?w8(ne$,{status:A.indexStatus},void 0,!1,void 0,this):w8(qx,{items:[{label:"Semantic index",value:Q?"Ready":"Pending"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Y0Q({status:A}){let Q=A.totalFiles===void 0?"\u2014":A.totalFiles===1?"1 file":`${A.totalFiles} files`,$=A.byEntityType?Object.entries(A.byEntityType).sort(([,w],[,B])=>B-w).slice(0,2).map(([w,B])=>`${w} ${B}`).join(", "):void 0;return w8("section",{class:"card content-sync-card",children:[w8(DX,{title:"Content sync",source:"directory-sync"},void 0,!1,void 0,this),w8(qx,{items:[{label:"Path",value:A.syncPath},{label:"Files",value:$?`${Q} \xB7 ${$}`:Q},{label:"Watch",value:A.watchEnabled?"Watching":A.isInitialized?"Manual":"Not initialized"},{label:"Last sync",value:A.lastSync?`last sync ${B0Q(A.lastSync)}`:"\u2014"}]},void 0,!1,void 0,this),w8("div",{class:"pipeline-mini","aria-label":"Write pipeline",children:[w8("span",{class:`pipeline-step${A.isInitialized?" is-done":""}`,children:"entity db"},void 0,!1,void 0,this),w8("span",{class:"pipeline-track"},void 0,!1,void 0,this),w8("span",{class:`pipeline-step${(A.totalFiles??0)>0?" is-done":""}`,children:"exported"},void 0,!1,void 0,this),w8("span",{class:"pipeline-track"},void 0,!1,void 0,this),w8("span",{class:`pipeline-step${A.lastSync?" is-done":""}`,children:"committed"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.managementUrl&&w8(r90,{label:"Content sync actions",children:w8(o90,{href:A.managementUrl,emphasis:"primary",children:"Open in CMS"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var re$={pending:"run",processing:"run",completed:"done",failed:"fail"},oe$={pending:"pending",processing:"running",completed:"done",failed:"failed"};function Z0Q({jobs:A}){return w8("section",{class:"card widget-card--wide job-queue-card",children:[w8(DX,{title:"Job queue",source:"job-queue"},void 0,!1,void 0,this),A.length===0?w8(qD,{children:"No recent job progress observed."},void 0,!1,void 0,this):w8("table",{class:"jobs",children:[w8("thead",{children:w8("tr",{children:[w8("th",{children:"Job"},void 0,!1,void 0,this),w8("th",{children:"Type"},void 0,!1,void 0,this),w8("th",{children:"Updated"},void 0,!1,void 0,this),w8("th",{children:"Status"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),w8("tbody",{children:A.map((Q)=>w8("tr",{children:[w8("td",{class:"mono",children:Q.id.slice(0,8)},void 0,!1,void 0,this),w8("td",{children:Q.jobType??Q.kind},void 0,!1,void 0,this),w8("td",{class:"mono",children:s90(Q.updatedAt)},void 0,!1,void 0,this),w8("td",{children:w8("span",{class:`status-pill status-pill--${re$[Q.status]}`,children:[oe$[Q.status],Q.progressLabel?` \xB7 ${Q.progressLabel}`:""]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},`${Q.kind}:${Q.id}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as kQ}from"preact/jsx-dev-runtime";function se$(A,Q){if(A.group==="system"){let $=Qf0(Q);return[{label:"Runtime",value:"Active",tone:"good"},{label:"Endpoints",value:String(Q.appInfo.endpoints.length)},{label:"Semantic index",value:$?"Ready":"Pending",tone:$?"good":"warn"}]}return[{label:Af0(A)===1?"Widget":"Widgets",value:String(Af0(A))}]}function ae$(A,Q){return A.map(($)=>{let w=eO0($).flatMap((B)=>B.widget.digest??[]).slice(0,4);return{id:$.id,label:$.label,href:`#${$.id}`,lines:w.length>0?w:se$($,Q)}})}function te$({hiddenWidgetCount:A,loginUrl:Q}){return kQ("section",{class:"card operator-gate",children:[kQ("div",{children:[kQ("div",{class:"card-title",children:"Operator access"},void 0,!1,void 0,this),kQ("p",{children:[A===1?"1 private console widget is hidden.":`${A} private console widgets are hidden.`," ","","Sign in with your passkey to unlock the restricted layer."]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),kQ("a",{class:"operator-gate-link",href:Q,children:"Sign in"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ee$({input:A}){let Q=Qf0(A),$=A.activityLog?.[0],w=A.appInfo.entityCounts.length,B=A.appInfo.interactions.map((G)=>G.id).slice(0,3).join(" / "),X=A.indexStatus?.embeddedEntities??A.appInfo.embeddings,Y=A.indexStatus?.embeddableEntities,Z=A.indexStatus?(A.indexStatus.activeEmbeddingJobs??0)+(A.indexStatus.missingEmbeddings??0)+(A.indexStatus.staleEmbeddings??0):0,H=Y===void 0?`${X}`:`${X}/${Y}`,K=Z>0?`${H} embedded \xB7 ${Z} queued`:`${H} embedded`,U=(A.jobProgress??[]).some((G)=>G.status==="processing"||G.status==="pending");return kQ("section",{class:"overview-vitals","aria-label":"Runtime vitals",children:[kQ("article",{class:"vital-card",children:[kQ("span",{class:"vital-label",children:"Entities"},void 0,!1,void 0,this),kQ("strong",{class:"vital-num",children:A.appInfo.entities},void 0,!1,void 0,this),kQ("span",{class:"vital-sub",children:w===1?"1 type":`${w} types`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),kQ("article",{class:"vital-card",children:[kQ("span",{class:"vital-label",children:"Interactions"},void 0,!1,void 0,this),kQ("strong",{class:"vital-num",children:A.appInfo.interactions.length},void 0,!1,void 0,this),kQ("span",{class:"vital-sub",children:B||"no channels"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),kQ("article",{class:`vital-card ${Q?"vital-card--ok":"vital-card--warm"}`,children:[kQ("span",{class:"vital-label",children:"Semantic index"},void 0,!1,void 0,this),kQ("strong",{class:"vital-num vital-num--text",children:Q?"Ready":"Pending"},void 0,!1,void 0,this),kQ("span",{class:"vital-sub",children:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this),kQ("article",{class:`vital-card${U?" vital-card--warm":""}`,children:[kQ("span",{class:"vital-label",children:"Last write"},void 0,!1,void 0,this),kQ("strong",{class:"vital-num vital-num--text",children:$?s90($.timestamp):"\u2014"},void 0,!1,void 0,this),kQ("span",{class:"vital-sub",children:$?`${$.entityType}/${$.entityId}`:"no writes observed"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function A08({input:A}){let{role:Q,purpose:$,values:w}=A.character;if(!Q&&!$&&w.length===0)return null;return kQ("aside",{class:"card identity-capsule",children:[kQ(DX,{title:"Identity",source:"identity"},void 0,!1,void 0,this),kQ("div",{class:"identity-capsule-body",children:[Q&&kQ("span",{class:"identity-capsule-role",children:["\u201C",Q,"\u201D"]},void 0,!0,void 0,this),w.length>0&&kQ("span",{class:"values",children:w.map((B)=>kQ("span",{class:"value",children:B},B,!1,void 0,this))},void 0,!1,void 0,this),$&&kQ("span",{class:"identity-capsule-purpose",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Q08({cards:A}){if(A.length===0)return kQ("section",{class:"card overview-empty-digest",children:[kQ(DX,{title:"Group digests"},void 0,!1,void 0,this),kQ(qD,{children:"No plugin groups are visible yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return kQ("section",{class:"digests","aria-label":"Group digests",children:A.map((Q)=>kQ("a",{class:"card digest-card",href:Q.href,children:[kQ("div",{class:"digest-head",children:[kQ("h4",{children:Q.label},void 0,!1,void 0,this),kQ("span",{class:"digest-go",children:"open \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),kQ("dl",{class:"digest-lines",children:Q.lines.map(($)=>kQ("div",{class:`digest-line digest-line--${$.tone??"plain"}`,children:[kQ("dt",{children:$.label},void 0,!1,void 0,this),kQ("dd",{children:$.value},void 0,!1,void 0,this)]},`${$.label}:${$.value}`,!0,void 0,this))},void 0,!1,void 0,this)]},Q.id,!0,void 0,this))},void 0,!1,void 0,this)}var W0Q={created:{glyph:"\uFF0B",tone:""},updated:{glyph:"\u2713",tone:" ledger-glyph--ok"},deleted:{glyph:"\u2212",tone:" ledger-glyph--warn"}};function $08({events:A}){return kQ("section",{class:"card activity-ledger",children:[kQ(DX,{title:"Activity",source:"entity events"},void 0,!1,void 0,this),A.length===0?kQ(qD,{children:"No entity activity has been observed this session."},void 0,!1,void 0,this):kQ("ol",{class:"ledger",children:A.map((Q)=>kQ("li",{class:"ledger-entry",children:[kQ("time",{class:"ledger-time",dateTime:Q.timestamp,children:s90(Q.timestamp)},void 0,!1,void 0,this),kQ("span",{class:`ledger-glyph${W0Q[Q.action].tone}`,"aria-hidden":"true",children:W0Q[Q.action].glyph},void 0,!1,void 0,this),kQ("span",{class:"ledger-what",children:[kQ("b",{children:Q.entityType},void 0,!1,void 0,this)," ",Q.action," \u2014"," ",kQ("code",{children:[Q.entityType,"/",Q.entityId]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},`${Q.timestamp}:${Q.action}:${Q.entityType}:${Q.entityId}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function H0Q({input:A,tabs:Q,showOperatorGate:$}){let w=ae$(Q,A),B=A.activityLog??[];return kQ("section",{id:"overview",class:"dashboard-tab-panel is-active","data-dashboard-tab-panel":!0,"data-ui-panel":"overview",role:"tabpanel","aria-labelledby":"dashboard-tab-overview",children:[kQ(ee$,{input:A},void 0,!1,void 0,this),kQ(A08,{input:A},void 0,!1,void 0,this),$&&A.operatorAccess&&kQ(te$,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),kQ("div",{class:"overview-grid",children:[kQ(Q08,{cards:w},void 0,!1,void 0,this),kQ($08,{events:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}p2();import{jsxDEV as uy}from"preact/jsx-dev-runtime";function w08(A){try{let Q=new URL(A);return Q.host+Q.pathname.replace(/\/$/,"")}catch{return A}}function K0Q(A){let{endpoints:Q,baseUrl:$}=A;if(Q.length===0)return null;let w=[...Q].sort((B,X)=>B.priority-X.priority||B.label.localeCompare(X.label));return uy("aside",{class:"card",children:[uy(DX,{title:"Endpoints"},void 0,!1,void 0,this),uy("dl",{class:"links",children:w.map((B)=>{let X=oS(B.url,$);return uy("a",{class:"link",href:X,target:"_blank",rel:"noopener noreferrer",children:[uy("dt",{children:IW0(B.label)},void 0,!1,void 0,this),uy("dd",{children:w08(X)},void 0,!1,void 0,this),uy("span",{class:"arrow",children:"\u2197"},void 0,!1,void 0,this)]},`${B.label}:${B.url}`,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}p2();import{jsxDEV as VW}from"preact/jsx-dev-runtime";function B08({entityType:A,count:Q,max:$}){let w=Math.max(4,Math.round(Q/$*100));return VW("div",{class:"breakdown-row",children:[VW("span",{class:"breakdown-name",children:sj(A)},void 0,!1,void 0,this),VW("span",{class:"breakdown-count",children:Q},void 0,!1,void 0,this),VW("div",{class:"breakdown-bar",children:VW("i",{style:{width:`${w}%`}},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function U0Q(A){let{total:Q,entityCounts:$}=A;if($.length===0)return VW("article",{class:"card card--entity-summary",children:[VW(DX,{title:"Entities"},void 0,!1,void 0,this),VW(qD,{children:"No indexed entities yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let w=[...$].sort((X,Y)=>Y.count-X.count),B=w[0]?.count??1;return VW("article",{class:"card card--entity-summary",children:[VW(DX,{title:"Entities",subtitle:"corpus \xB7 sorted by volume"},void 0,!1,void 0,this),VW("div",{class:"entities",children:[VW("div",{children:[VW("div",{class:"entity-summary-number",children:Q},void 0,!1,void 0,this),VW("div",{class:"entity-summary-label",children:"indexed entities"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),VW("div",{class:"breakdown",children:w.map((X)=>VW(B08,{entityType:X.entityType,count:X.count,max:B},X.entityType,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}p2();import{jsxDEV as Jx}from"preact/jsx-dev-runtime";var X08={human:"Human",agent:"Agent",admin:"Admin",protocol:"Protocol"};function G0Q(A){let{interactions:Q,baseUrl:$}=A;if(Q.length===0)return null;return Jx("aside",{class:"card interactions-card",children:[Jx(DX,{title:"Ways to connect"},void 0,!1,void 0,this),Jx("div",{class:"interactions-list",children:Q.slice(0,5).map((w)=>{let B=oS(w.href,$);return Jx("a",{class:`interaction-link interaction-link--${w.kind}`,href:B,target:"_blank",rel:"noopener noreferrer",children:[Jx("span",{children:[Jx("strong",{children:IW0(w.label)},void 0,!1,void 0,this),w.description&&Jx("em",{children:w.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Jx("small",{children:X08[w.kind]},void 0,!1,void 0,this)]},`${w.pluginId}:${w.id}`,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as CIA}from"preact/jsx-dev-runtime";function Y08(A){let Q=Math.max(0,Math.floor(A)),$=Math.floor(Q/86400),w=Math.floor(Q%86400/3600),B=Math.floor(Q%3600/60);if($>0)return`${$}d ${String(w).padStart(2,"0")}h ${String(B).padStart(2,"0")}m`;if(w>0)return`${w}h ${String(B).padStart(2,"0")}m`;return`${B}m`}function Z08(A){let Q=($)=>String($).padStart(2,"0");return`${A.getFullYear()}-${Q(A.getMonth()+1)}-${Q(A.getDate())} ${Q(A.getHours())}:${Q(A.getMinutes())}`}function D0Q(A){let{appInfo:Q,now:$}=A,w=Q.daemons.length,B=Q.daemons.filter((X)=>X.health?.status==="healthy").length;return CIA("aside",{class:"card runtime-card",children:[CIA(DX,{title:"Runtime",source:"core"},void 0,!1,void 0,this),CIA(qx,{items:[{label:"Version",value:`v${Q.version}`},{label:"Daemons",value:w===0?"\u2014":`${B}/${w} healthy`},{label:"Model",value:Q.model},{label:"Uptime",value:Y08(Q.uptime)},{label:"Embeddings",value:Q.embeddings},{label:"Rendered",value:Z08($)}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}p2();h0();import{jsxDEV as q8,Fragment as b08}from"preact/jsx-dev-runtime";var W08=new Set(["rendered","version"]),H08=new Set(["StatsWidget","SystemWidget"]),K08=W.object({id:W.string(),name:W.string(),description:W.string().optional(),meta:W.array(W.string()).optional(),tags:W.array(W.string()).optional(),count:W.number().optional(),priority:W.string().optional(),status:W.string().optional()}),U08=W.object({items:W.array(K08)}),G08=W.record(W.string(),W.unknown()),D08=W.object({summary:W.object({draft:W.number().int().nonnegative(),queued:W.number().int().nonnegative(),generating:W.number().int().nonnegative(),failed:W.number().int().nonnegative(),published:W.number().int().nonnegative(),needsOperator:W.number().int().nonnegative()}),failures:W.array(W.object({entityId:W.string(),entityType:W.string(),title:W.string(),error:W.string(),retryCount:W.number().int().nonnegative()})).default([]),managementUrl:W.string().optional()}),q08={crit:"error",critical:"error",high:"warn",med:"plain",medium:"plain",low:"muted"};function z08(A){if(A===void 0||A===null||A==="")return!0;if(Array.isArray(A))return A.length===0;if(typeof A==="object")return Object.keys(A).length===0;return!1}function V08(A){if(typeof A==="object")return JSON.stringify(A);return String(A)}function q0Q(A){let Q=U08.safeParse(A);if(!Q.success||Q.data.items.length===0)return[];return Q.data.items}function J08(A){let Q=G08.safeParse(A);return Q.success?Q.data:null}function F08({widget:A}){if(A.widget.rendererName!=="ListWidget")return null;let Q=q0Q(A.data);if(Q.length===0)return null;return q8("span",{class:"tab-badge tab-badge--muted",children:Q.length},void 0,!1,void 0,this)}function L08({widget:A}){let Q=J08(A.data);if(!Q)return q8(qD,{},void 0,!1,void 0,this);let $=Object.entries(Q).filter(([w,B])=>!W08.has(w)&&!z08(B));if($.length===0)return q8(qD,{},void 0,!1,void 0,this);return q8(qx,{items:$.map(([w,B])=>({label:sj(w),value:V08(B)}))},void 0,!1,void 0,this)}function I08({item:A}){let Q=A.priority?q08[A.priority.toLowerCase()]??"plain":"plain",$=typeof A.count==="number"||Boolean(A.priority??A.status);return q8(Vx,{title:A.name,description:A.description,meta:A.meta,tags:A.tags,trailing:$?q8(b08,{children:[typeof A.count==="number"&&q8("span",{class:"list-count",children:A.count},void 0,!1,void 0,this),A.priority&&q8(my,{tone:Q,children:A.priority},void 0,!1,void 0,this),A.status&&q8(my,{tone:"ok",children:A.status},void 0,!1,void 0,this)]},void 0,!0,void 0,this):void 0},void 0,!1,void 0,this)}function N08({widget:A}){let Q=q0Q(A.data);if(Q.length===0)return q8(qD,{},void 0,!1,void 0,this);return q8(zx,{children:Q.map(($)=>q8(I08,{item:$},$.id,!1,void 0,this))},void 0,!1,void 0,this)}function $f0({label:A,value:Q,tone:$=""}){return q8("div",{class:`pipeline-metric${$?` pipeline-metric--${$}`:""}`,children:[q8("dt",{children:A},void 0,!1,void 0,this),q8("dd",{children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _08({widget:A}){let Q=D08.safeParse(A.data);if(!Q.success)return q8(qD,{},void 0,!1,void 0,this);let{summary:$,failures:w,managementUrl:B}=Q.data;return q8("div",{class:"pipeline-digest",children:[q8("dl",{class:"pipeline-metrics",children:[q8($f0,{label:"Queued",value:$.queued},void 0,!1,void 0,this),q8($f0,{label:"Generating",value:$.generating},void 0,!1,void 0,this),q8($f0,{label:"Awaiting review",value:$.needsOperator,tone:$.needsOperator>0?"warn":""},void 0,!1,void 0,this),q8($f0,{label:"Published",value:$.published,tone:"ok"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w.length>0&&q8("section",{class:"pipeline-failures","aria-label":"Publication failures",children:[q8("h4",{children:"Needs attention"},void 0,!1,void 0,this),w.slice(0,3).map((X)=>q8("div",{class:"pipeline-failure",children:[q8("strong",{children:X.title},void 0,!1,void 0,this),q8("span",{children:X.error},void 0,!1,void 0,this)]},`${X.entityType}:${X.entityId}`,!0,void 0,this))]},void 0,!0,void 0,this),B&&q8(r90,{label:"Publication actions",children:q8(o90,{href:B,emphasis:"primary",children:"Open in CMS"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function P08({widget:A}){if(A.component){let Q=A.component;return q8(Q,{title:A.widget.title,...A.widget.description?{description:A.widget.description}:{},data:A.data,pluginId:A.widget.pluginId,widgetId:A.widget.id,instanceId:RIA(A.widget.pluginId,A.widget.id)},void 0,!1,void 0,this)}switch(A.widget.rendererName){case"PipelineWidget":return q8(_08,{widget:A},void 0,!1,void 0,this);case"ListWidget":return q8(N08,{widget:A},void 0,!1,void 0,this);default:return q8(L08,{widget:A},void 0,!1,void 0,this)}}function hIA({widget:A,featured:Q=!1}){let $=H08.has(A.widget.rendererName);return q8("article",{class:Q?"card card--entity-summary":`card${$?"":" widget-card--wide"}`,children:[q8(DX,{title:A.widget.title,children:q8(F08,{widget:A},void 0,!1,void 0,this)},void 0,!1,void 0,this),q8(P08,{widget:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as tY,Fragment as z0Q}from"preact/jsx-dev-runtime";function V0Q({tab:A,input:Q,now:$}){let w=[...A.widgets.primary,...A.widgets.secondary],B=A.group==="system",X=A.group==="knowledge",Y=A.widgets.sidebar.length>0||B;return tY("section",{id:A.id,class:"dashboard-tab-panel","data-dashboard-tab-panel":!0,"data-dashboard-group":A.group,"data-ui-panel":A.id,role:"tabpanel","aria-labelledby":`dashboard-tab-${A.id}`,children:[tY("header",{class:"tab-section-head",children:tY("h2",{children:A.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),tY("div",{class:`layout tab-layout${Y?"":" tab-layout--main-only"}`,children:[tY("div",{class:"main-column",children:[X&&tY(U0Q,{total:Q.appInfo.entities,entityCounts:Q.appInfo.entityCounts},void 0,!1,void 0,this),B&&tY(z0Q,{children:[tY(X0Q,{input:Q},void 0,!1,void 0,this),Q.directorySyncStatus&&tY(Y0Q,{status:Q.directorySyncStatus},void 0,!1,void 0,this),tY(Z0Q,{jobs:Q.jobProgress??[]},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w.map((Z)=>tY(hIA,{widget:Z},`${Z.widget.pluginId}:${Z.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),Y&&tY("div",{class:"sidebar-column",children:[B&&tY(z0Q,{children:[tY(K0Q,{endpoints:Q.appInfo.endpoints,baseUrl:Q.baseUrl},void 0,!1,void 0,this),tY(D0Q,{appInfo:Q.appInfo,now:$},void 0,!1,void 0,this),tY(G0Q,{interactions:Q.appInfo.interactions,baseUrl:Q.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.widgets.sidebar.map((Z)=>tY(hIA,{widget:Z},`${Z.widget.pluginId}:${Z.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as Yw,Fragment as j08}from"preact/jsx-dev-runtime";function J0Q({input:A}){let Q=ae2(A.widgets),$=A.operatorAccess&&!A.operatorAccess.isOperator&&A.operatorAccess.hiddenWidgetCount>0,w=A.dashboardPath??"/dashboard",B=new Date;return Yw("html",{lang:"en","data-climate":"instrument",children:[Yw("head",{children:[Yw("meta",{charSet:"utf-8"},void 0,!1,void 0,this),Yw("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0, viewport-fit=cover"},void 0,!1,void 0,this),Yw("title",{children:A.title},void 0,!1,void 0,this),Yw("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),Yw("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),Yw("link",{href:sw0,rel:"stylesheet"},void 0,!1,void 0,this),A.assetUrls?.themeStyles?Yw("link",{"data-dashboard-theme":!0,rel:"stylesheet",href:A.assetUrls.themeStyles},void 0,!1,void 0,this):A.themeCSS!==void 0&&Yw("style",{"data-dashboard-theme":!0,dangerouslySetInnerHTML:{__html:A.themeCSS}},void 0,!1,void 0,this),A.assetUrls?Yw("link",{"data-dashboard-styles":!0,rel:"stylesheet",href:A.assetUrls.dashboardStyles},void 0,!1,void 0,this):Yw("style",{"data-dashboard-styles":!0,dangerouslySetInnerHTML:{__html:rO0}},void 0,!1,void 0,this),A.assetUrls?A.assetUrls.widgetStyles.map((X)=>Yw("link",{"data-dashboard-widget-styles":!0,rel:"stylesheet",href:X},X,!1,void 0,this)):A.widgetStyles&&A.widgetStyles.length>0&&Yw("style",{"data-dashboard-widget-styles":!0,dangerouslySetInnerHTML:{__html:A.widgetStyles.join(`
10395
10395
 
10396
10396
  `)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Yw("body",{children:[Yw(se2,{dashboardPath:w,surfaces:A.surfaces??[{id:"dashboard",label:"Dashboard",href:w,isActive:!0}],operatorAccess:A.operatorAccess},void 0,!1,void 0,this),Yw("main",{class:"console","data-component":"dashboard:dashboard",children:[Yw("div",{class:"frame","data-ui-tabs":!0,"data-ui-tabs-default":"overview","data-ui-tabs-hash":"true",children:[Yw(A0Q,{title:A.title,tagline:A.profile.description},void 0,!1,void 0,this),Yw(te2,{tabs:Q},void 0,!1,void 0,this),Yw("div",{class:"canvas",children:Yw("div",{class:"dashboard-tab-panels",children:[Yw(H0Q,{input:A,tabs:Q,showOperatorGate:Boolean($)},void 0,!1,void 0,this),Q.map((X)=>Yw(V0Q,{tab:X,input:A,now:B},X.id,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Yw(oe2,{title:A.title,appInfo:A.appInfo,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.assetUrls?Yw("script",{"data-dashboard-script":!0,src:A.assetUrls.dashboardScript},void 0,!1,void 0,this):Yw(j08,{children:[Yw("script",{dangerouslySetInnerHTML:{__html:rP}},void 0,!1,void 0,this),Yw("script",{dangerouslySetInnerHTML:{__html:oP}},void 0,!1,void 0,this),Yw("script",{dangerouslySetInnerHTML:{__html:oO0}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.assetUrls?A.assetUrls.widgetScripts.map((X)=>Yw("script",{"data-dashboard-widget-script":!0,src:X},X,!1,void 0,this)):A.widgetScripts.map((X,Y)=>Yw("script",{dangerouslySetInnerHTML:{__html:X}},`widget-script:${Y}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as k08}from"preact/jsx-dev-runtime";function F0Q(A){return`<!doctype html>
10397
- ${M08(k08(J0Q,{input:A},void 0,!1,void 0,this))}`}function O08(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function L0Q(A){let Q=A.query.trim().toLowerCase(),$=[];if(A.cmsPath!==void 0&&A.entities.length>0){let B=A.cmsPath;$.push({id:"entities",label:"Entities",items:A.entities.map((X)=>({id:`${X.entityType}/${X.id}`,title:X.title,sub:X.entityType,href:`${B}#/${encodeURIComponent(X.entityType)}/${encodeURIComponent(X.id)}`,tag:"edit in cms"}))})}let w=tO0([...new Set(A.groups)]).map((B)=>({group:B,label:Ho(B)})).filter(({group:B,label:X})=>Q===""||X.toLowerCase().includes(Q)||B.toLowerCase().includes(Q)).map(({group:B,label:X})=>({id:`tab/${B}`,title:X,sub:"tab",href:`${A.dashboardPath}#${O08(B)}`,tag:"dashboard"}));if(w.length>0)$.push({id:"tabs",label:"Dashboard",items:w});return $}function I0Q(A,Q){let $={},w=new Set,B=new Set;for(let[X,Y]of Object.entries(A)){let Z=Q?.get(Y.widget.pluginId,Y.widget.id);if($[X]={...Y,...Z?.component?{component:Z.component}:{}},Z?.clientStyles)w.add(Z.clientStyles);if(Z?.clientScript)B.add(Z.clientScript)}return{widgets:$,widgetStyles:Array.from(w),widgetScripts:Array.from(B)}}var N0Q={name:"@brains/dashboard",version:"0.2.0-alpha.195",description:"Dashboard plugin with extensible widget system",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0","happy-dom":"^20.10.6",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var x08=W.object({version:W.string().default("1.0.0"),routePath:W.string().default("/dashboard"),themeCSS:W.string().optional()}),R08=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number().default(50),section:W.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:W.string(),visibility:W.enum(["public","trusted","anchor"]).default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:W.custom().optional(),clientStyles:W.string().optional(),clientScript:W.string().optional(),dataProvider:W.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:W.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!kIA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),v08=W.object({pluginId:W.string(),widgetId:W.string().optional()}),C08=W.object({entityType:W.string(),entityId:W.string(),conversationId:W.string().optional()}),h08=W.object({id:W.string(),type:W.enum(["job","batch"]),status:W.enum(["pending","processing","completed","failed"]),message:W.string().optional(),progress:W.object({current:W.number(),total:W.number(),percentage:W.number()}).optional(),jobDetails:W.object({jobType:W.string(),priority:W.number(),retryCount:W.number()}).optional()}),E08=W.object({success:W.literal(!0),data:W.object({syncPath:W.string(),isInitialized:W.boolean(),watchEnabled:W.boolean(),lastSync:W.string().datetime().nullable().optional().transform((A)=>A??void 0),totalFiles:W.number().int().nonnegative().optional(),byEntityType:W.record(W.string(),W.number().int().nonnegative()).optional(),managementUrl:W.string().optional()})});function T08(A){return{id:A.id,pluginId:A.pluginId,title:A.title,...A.description?{description:A.description}:{},group:A.group,priority:A.priority,section:A.section,rendererName:A.rendererName,visibility:A.visibility,...A.needsOperator!==void 0&&{needsOperator:A.needsOperator},...A.digest?{digest:A.digest}:{},...A.component?{component:A.component}:{},...A.clientStyles?{clientStyles:A.clientStyles}:{},...A.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{}}}class EIA extends d6{assetRegistry;widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",N0Q,A,x08);this.assetRegistry=new OIA(this.config.routePath)}recordActivity(A,Q){let $=C08.safeParse(Q);if(!$.success)return;this.activityLog=[{action:A,entityType:$.data.entityType,entityId:$.data.entityId,timestamp:new Date().toISOString(),...$.data.conversationId?{conversationId:$.data.conversationId}:{}},...this.activityLog].slice(0,12)}recordJobProgress(A){let Q=h08.safeParse(A);if(!Q.success)return;let $=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,w={id:Q.data.id,kind:Q.data.type,status:Q.data.status,updatedAt:new Date().toISOString(),...Q.data.message?{message:Q.data.message}:{},...Q.data.jobDetails?.jobType?{jobType:Q.data.jobDetails.jobType}:{},...$?{progressLabel:$}:{}};this.jobProgress=[w,...this.jobProgress.filter((B)=>B.id!==w.id||B.kind!==w.kind)].slice(0,8)}async getIndexStatus(){if(!this.ctx)return;let A=this.ctx.entityService;try{if(typeof A.awaitIndexReady==="function")return await A.awaitIndexReady({timeoutMs:0,intervalMs:0});if(typeof A.isIndexReady==="function")return{ready:A.isIndexReady()}}catch(Q){this.logger.debug("Semantic index status unavailable",{error:eA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=E08.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:eA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new nO0(this.logger),this.datasource=new sO0(this.widgetRegistry,this.logger),A.entities.registerDataSource(this.datasource),A.endpoints.register({label:"Dashboard",url:this.config.routePath,priority:30,visibility:"public"}),A.interactions.register({id:"dashboard",label:"Dashboard",description:"Inspect runtime status, endpoints, and dashboard widgets.",href:this.config.routePath,kind:"admin",priority:30,visibility:"public"}),A.messaging.subscribe("entity:created",async(Q)=>{return this.recordActivity("created",Q.payload),{success:!0}}),A.messaging.subscribe("entity:updated",async(Q)=>{return this.recordActivity("updated",Q.payload),{success:!0}}),A.messaging.subscribe("entity:deleted",async(Q)=>{return this.recordActivity("deleted",Q.payload),{success:!0}}),A.messaging.subscribe("job-progress",async(Q)=>{return this.recordJobProgress(Q.payload),{success:!0}}),A.messaging.subscribe("dashboard:register-widget",async(Q)=>{try{let $=R08.parse(Q.payload),w=T08($);return this.widgetRegistry?.register(w),this.logger.debug("Widget registered via messaging",{widgetId:$.id,pluginId:$.pluginId,rendererName:$.rendererName,builtIn:dO0.includes($.rendererName)}),{success:!0}}catch($){return this.logger.error("Failed to register widget",{error:eA($),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let $=v08.parse(Q.payload);return this.widgetRegistry?.unregister($.pluginId,$.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:$.pluginId,widgetId:$.widgetId}),{success:!0}}catch($){return this.logger.error("Failed to unregister widget",{error:eA($),payload:Q.payload}),{success:!1,error:"Widget unregistration failed"}}}),this.logger.info("Dashboard plugin registered")}getWebRoutes(){return[{path:this.config.routePath,method:"GET",public:!0,handler:async(A)=>{if(!this.datasource||!this.ctx)return new Response("Dashboard unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}});let Q=this.ctx,$=await xY()?.getOperatorSession(A),w=Boolean($),B=w?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((O)=>$9.hasPermission(B,O.visibility)),Z=X.length-Y.length,[H,K,U,G]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),D=Q.identity.get(),q=Q.identity.getProfile(),J=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),F={...K,endpoints:K.endpoints.filter((O)=>$9.hasPermission(B,O.visibility)),interactions:K.interactions.filter((O)=>$9.hasPermission(B,O.visibility))},L=q.name||K.model||"Brain Dashboard",_=new URL(A.url),j=`${_.pathname}${_.search}`,b=encodeURIComponent(j),f=I0Q(H.widgets,this.widgetRegistry),v=this.assetRegistry.createRenderUrls({themeCSS:this.config.themeCSS,widgetStyles:f.widgetStyles,widgetScripts:f.widgetScripts}),R={title:L,baseUrl:J,widgets:f.widgets,widgetStyles:f.widgetStyles,widgetScripts:f.widgetScripts,assetUrls:v,dashboardPath:this.config.routePath,surfaces:If(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:q,appInfo:F,activityLog:this.activityLog,jobProgress:this.jobProgress,...G!==void 0&&{indexStatus:G},...U!==void 0&&{directorySyncStatus:U},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:w,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${b}`,logoutUrl:`/logout?return_to=${b}`}};return new Response(F0Q(R),{headers:{"Cache-Control":"private, no-store","Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await xY()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let $=this.ctx;if(!$)return Response.json({groups:[]});let w=new URL(A.url).searchParams.get("q")?.trim()??"",B=[];if(w.length>=2)try{B=(await $.entityService.search({query:w,options:{limit:6}})).map((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=If($.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:L0Q({query:w,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}},...this.assetRegistry.getRoutes()]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function Fx(A={}){return new EIA(A)}h0();var y08=W.enum(["public","trusted","anchor"]),g08=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),S08=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number(),section:W.enum(["primary","secondary","sidebar"]),rendererName:W.string(),visibility:y08,needsOperator:W.number().int().nonnegative().optional(),digest:W.array(g08).max(4).optional(),component:W.custom().optional()}),m08=W.object({widget:S08,data:W.unknown()}),u08=W.object({widgets:W.record(W.string(),m08)});zA();h0();zA();h0();import{h as XA8}from"preact";zA();EZ();p2();h0();var wf0=W.enum(["generating","draft","queued","published","failed"]),c08=W.enum(["generating","draft","queued","published","failed"]),Bf0=W.object({subject:W.string(),status:wf0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional()}),_0Q=W.object({subject:W.string(),status:wf0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional(),error:W.string().optional()}),p08=W.object({subject:W.string(),status:c08,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional(),error:W.string().optional()}),Go=U6.extend({entityType:W.literal("newsletter"),metadata:p08});zA();class P0Q extends zQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Go,frontmatterSchema:Bf0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){let Q=this.parseFrontmatter(A);return{entityType:"newsletter",content:A,metadata:Q}}buildStub(A){let Q={subject:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:Q}}}var b0Q=new P0Q;zA();zA();p2();h0();var l08=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),status:W.enum(["generating","draft","queued","published","failed"]).optional()}),i08=W.looseObject({entityType:W.string().optional(),query:l08.optional()});function j0Q(A){try{let{content:Q}=MQ(A.content,Bf0);return Q}catch{return A.content}}class TIA extends n7{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=i08.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=j0Q(A),$={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:cW(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)$.sentAt=A.metadata.sentAt;return $}buildListResult(A,Q,$){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,$){let{query:w}=this.parseQuery(A),B=$.entityService;if(w.id)return this.fetchSingleNewsletter(w.id,Q,B);let X=w.status,Y=X?{filter:{metadata:{status:X}}}:void 0,{items:Z,pagination:H}=await this.fetchList(w,B,Y);return Q.parse(this.buildListResult(Z,H,w))}async fetchSingleNewsletter(A,Q,$){let w=await $.getEntity({entityType:this.config.entityType,id:A});if(!w)throw Error(`Newsletter not found: ${A}`);let B=await this.resolveNavigation(w,$),X=[];if(w.metadata.entityIds?.length){let H=w.metadata.sourceEntityType??"post";X=(await Promise.all(w.metadata.entityIds.map(async(U)=>{let G=await $.getEntity({entityType:H,id:U});if(G){let D=G.metadata;return{id:U,title:D.title??U,url:`/${H}s/${D.slug??U}`}}return null}))).filter((U)=>U!==null)}let Y=j0Q(w),Z={id:w.id,subject:w.metadata.subject,status:w.metadata.status,content:Y,created:w.created,updated:w.updated,sentAt:w.metadata.sentAt,scheduledFor:w.metadata.scheduledFor,newsletter:w,prevNewsletter:B.prev?{id:B.prev.id,subject:B.prev.subject,url:B.prev.url}:null,nextNewsletter:B.next?{id:B.next.id,subject:B.next.subject,url:B.next.url}:null,sourceEntities:X.length>0?X:void 0};return Q.parse(Z)}}zA();p2();h0();var d08=W.object({prompt:W.string().optional().describe("AI generation prompt"),sourceEntityIds:W.array(W.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:W.enum(["post"]).optional().describe("Type of source entities"),content:W.string().optional().describe("Direct content (skip AI)"),subject:W.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:W.boolean().optional().describe("Create as queued (true) or draft (false)")});class yIA extends yZ{constructor(A,Q){super(A,Q,{schema:d08,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let $=A.addToQueue??!1,{prompt:w,sourceEntityIds:B,sourceEntityType:X}=A,{content:Y,subject:Z}=A;if(Y){if(!Z)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(B&&B.length>0){let D=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let J=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(J.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${J.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
10397
+ ${M08(k08(J0Q,{input:A},void 0,!1,void 0,this))}`}function O08(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function L0Q(A){let Q=A.query.trim().toLowerCase(),$=[];if(A.cmsPath!==void 0&&A.entities.length>0){let B=A.cmsPath;$.push({id:"entities",label:"Entities",items:A.entities.map((X)=>({id:`${X.entityType}/${X.id}`,title:X.title,sub:X.entityType,href:`${B}#/${encodeURIComponent(X.entityType)}/${encodeURIComponent(X.id)}`,tag:"edit in cms"}))})}let w=tO0([...new Set(A.groups)]).map((B)=>({group:B,label:Ho(B)})).filter(({group:B,label:X})=>Q===""||X.toLowerCase().includes(Q)||B.toLowerCase().includes(Q)).map(({group:B,label:X})=>({id:`tab/${B}`,title:X,sub:"tab",href:`${A.dashboardPath}#${O08(B)}`,tag:"dashboard"}));if(w.length>0)$.push({id:"tabs",label:"Dashboard",items:w});return $}function I0Q(A,Q){let $={},w=new Set,B=new Set;for(let[X,Y]of Object.entries(A)){let Z=Q?.get(Y.widget.pluginId,Y.widget.id);if($[X]={...Y,...Z?.component?{component:Z.component}:{}},Z?.clientStyles)w.add(Z.clientStyles);if(Z?.clientScript)B.add(Z.clientScript)}return{widgets:$,widgetStyles:Array.from(w),widgetScripts:Array.from(B)}}var N0Q={name:"@brains/dashboard",version:"0.2.0-alpha.196",description:"Dashboard plugin with extensible widget system",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2","preact-render-to-string":"^6.7.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0","happy-dom":"^20.10.6",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var x08=W.object({version:W.string().default("1.0.0"),routePath:W.string().default("/dashboard"),themeCSS:W.string().optional()}),R08=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number().default(50),section:W.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:W.string(),visibility:W.enum(["public","trusted","anchor"]).default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:W.custom().optional(),clientStyles:W.string().optional(),clientScript:W.string().optional(),dataProvider:W.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:W.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!kIA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),v08=W.object({pluginId:W.string(),widgetId:W.string().optional()}),C08=W.object({entityType:W.string(),entityId:W.string(),conversationId:W.string().optional()}),h08=W.object({id:W.string(),type:W.enum(["job","batch"]),status:W.enum(["pending","processing","completed","failed"]),message:W.string().optional(),progress:W.object({current:W.number(),total:W.number(),percentage:W.number()}).optional(),jobDetails:W.object({jobType:W.string(),priority:W.number(),retryCount:W.number()}).optional()}),E08=W.object({success:W.literal(!0),data:W.object({syncPath:W.string(),isInitialized:W.boolean(),watchEnabled:W.boolean(),lastSync:W.string().datetime().nullable().optional().transform((A)=>A??void 0),totalFiles:W.number().int().nonnegative().optional(),byEntityType:W.record(W.string(),W.number().int().nonnegative()).optional(),managementUrl:W.string().optional()})});function T08(A){return{id:A.id,pluginId:A.pluginId,title:A.title,...A.description?{description:A.description}:{},group:A.group,priority:A.priority,section:A.section,rendererName:A.rendererName,visibility:A.visibility,...A.needsOperator!==void 0&&{needsOperator:A.needsOperator},...A.digest?{digest:A.digest}:{},...A.component?{component:A.component}:{},...A.clientStyles?{clientStyles:A.clientStyles}:{},...A.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{}}}class EIA extends d6{assetRegistry;widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",N0Q,A,x08);this.assetRegistry=new OIA(this.config.routePath)}recordActivity(A,Q){let $=C08.safeParse(Q);if(!$.success)return;this.activityLog=[{action:A,entityType:$.data.entityType,entityId:$.data.entityId,timestamp:new Date().toISOString(),...$.data.conversationId?{conversationId:$.data.conversationId}:{}},...this.activityLog].slice(0,12)}recordJobProgress(A){let Q=h08.safeParse(A);if(!Q.success)return;let $=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,w={id:Q.data.id,kind:Q.data.type,status:Q.data.status,updatedAt:new Date().toISOString(),...Q.data.message?{message:Q.data.message}:{},...Q.data.jobDetails?.jobType?{jobType:Q.data.jobDetails.jobType}:{},...$?{progressLabel:$}:{}};this.jobProgress=[w,...this.jobProgress.filter((B)=>B.id!==w.id||B.kind!==w.kind)].slice(0,8)}async getIndexStatus(){if(!this.ctx)return;let A=this.ctx.entityService;try{if(typeof A.awaitIndexReady==="function")return await A.awaitIndexReady({timeoutMs:0,intervalMs:0});if(typeof A.isIndexReady==="function")return{ready:A.isIndexReady()}}catch(Q){this.logger.debug("Semantic index status unavailable",{error:eA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=E08.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:eA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new nO0(this.logger),this.datasource=new sO0(this.widgetRegistry,this.logger),A.entities.registerDataSource(this.datasource),A.endpoints.register({label:"Dashboard",url:this.config.routePath,priority:30,visibility:"public"}),A.interactions.register({id:"dashboard",label:"Dashboard",description:"Inspect runtime status, endpoints, and dashboard widgets.",href:this.config.routePath,kind:"admin",priority:30,visibility:"public"}),A.messaging.subscribe("entity:created",async(Q)=>{return this.recordActivity("created",Q.payload),{success:!0}}),A.messaging.subscribe("entity:updated",async(Q)=>{return this.recordActivity("updated",Q.payload),{success:!0}}),A.messaging.subscribe("entity:deleted",async(Q)=>{return this.recordActivity("deleted",Q.payload),{success:!0}}),A.messaging.subscribe("job-progress",async(Q)=>{return this.recordJobProgress(Q.payload),{success:!0}}),A.messaging.subscribe("dashboard:register-widget",async(Q)=>{try{let $=R08.parse(Q.payload),w=T08($);return this.widgetRegistry?.register(w),this.logger.debug("Widget registered via messaging",{widgetId:$.id,pluginId:$.pluginId,rendererName:$.rendererName,builtIn:dO0.includes($.rendererName)}),{success:!0}}catch($){return this.logger.error("Failed to register widget",{error:eA($),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let $=v08.parse(Q.payload);return this.widgetRegistry?.unregister($.pluginId,$.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:$.pluginId,widgetId:$.widgetId}),{success:!0}}catch($){return this.logger.error("Failed to unregister widget",{error:eA($),payload:Q.payload}),{success:!1,error:"Widget unregistration failed"}}}),this.logger.info("Dashboard plugin registered")}getWebRoutes(){return[{path:this.config.routePath,method:"GET",public:!0,handler:async(A)=>{if(!this.datasource||!this.ctx)return new Response("Dashboard unavailable",{status:503,headers:{"Content-Type":"text/plain; charset=utf-8"}});let Q=this.ctx,$=await xY()?.getOperatorSession(A),w=Boolean($),B=w?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((O)=>$9.hasPermission(B,O.visibility)),Z=X.length-Y.length,[H,K,U,G]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),D=Q.identity.get(),q=Q.identity.getProfile(),J=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),F={...K,endpoints:K.endpoints.filter((O)=>$9.hasPermission(B,O.visibility)),interactions:K.interactions.filter((O)=>$9.hasPermission(B,O.visibility))},L=q.name||K.model||"Brain Dashboard",_=new URL(A.url),j=`${_.pathname}${_.search}`,b=encodeURIComponent(j),f=I0Q(H.widgets,this.widgetRegistry),v=this.assetRegistry.createRenderUrls({themeCSS:this.config.themeCSS,widgetStyles:f.widgetStyles,widgetScripts:f.widgetScripts}),R={title:L,baseUrl:J,widgets:f.widgets,widgetStyles:f.widgetStyles,widgetScripts:f.widgetScripts,assetUrls:v,dashboardPath:this.config.routePath,surfaces:If(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:q,appInfo:F,activityLog:this.activityLog,jobProgress:this.jobProgress,...G!==void 0&&{indexStatus:G},...U!==void 0&&{directorySyncStatus:U},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:w,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${b}`,logoutUrl:`/logout?return_to=${b}`}};return new Response(F0Q(R),{headers:{"Cache-Control":"private, no-store","Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await xY()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let $=this.ctx;if(!$)return Response.json({groups:[]});let w=new URL(A.url).searchParams.get("q")?.trim()??"",B=[];if(w.length>=2)try{B=(await $.entityService.search({query:w,options:{limit:6}})).map((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=If($.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:L0Q({query:w,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}},...this.assetRegistry.getRoutes()]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function Fx(A={}){return new EIA(A)}h0();var y08=W.enum(["public","trusted","anchor"]),g08=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),S08=W.object({id:W.string(),pluginId:W.string(),title:W.string(),description:W.string().optional(),group:W.string().min(1),priority:W.number(),section:W.enum(["primary","secondary","sidebar"]),rendererName:W.string(),visibility:y08,needsOperator:W.number().int().nonnegative().optional(),digest:W.array(g08).max(4).optional(),component:W.custom().optional()}),m08=W.object({widget:S08,data:W.unknown()}),u08=W.object({widgets:W.record(W.string(),m08)});zA();h0();zA();h0();import{h as XA8}from"preact";zA();EZ();p2();h0();var wf0=W.enum(["generating","draft","queued","published","failed"]),c08=W.enum(["generating","draft","queued","published","failed"]),Bf0=W.object({subject:W.string(),status:wf0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional()}),_0Q=W.object({subject:W.string(),status:wf0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional(),error:W.string().optional()}),p08=W.object({subject:W.string(),status:c08,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional(),error:W.string().optional()}),Go=U6.extend({entityType:W.literal("newsletter"),metadata:p08});zA();class P0Q extends zQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Go,frontmatterSchema:Bf0})}toMarkdown(A){let Q=this.extractBody(A.content);return this.buildMarkdown(Q,A.metadata)}fromMarkdown(A){let Q=this.parseFrontmatter(A);return{entityType:"newsletter",content:A,metadata:Q}}buildStub(A){let Q={subject:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:Q}}}var b0Q=new P0Q;zA();zA();p2();h0();var l08=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),status:W.enum(["generating","draft","queued","published","failed"]).optional()}),i08=W.looseObject({entityType:W.string().optional(),query:l08.optional()});function j0Q(A){try{let{content:Q}=MQ(A.content,Bf0);return Q}catch{return A.content}}class TIA extends n7{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=i08.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=j0Q(A),$={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:cW(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)$.sentAt=A.metadata.sentAt;return $}buildListResult(A,Q,$){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,$){let{query:w}=this.parseQuery(A),B=$.entityService;if(w.id)return this.fetchSingleNewsletter(w.id,Q,B);let X=w.status,Y=X?{filter:{metadata:{status:X}}}:void 0,{items:Z,pagination:H}=await this.fetchList(w,B,Y);return Q.parse(this.buildListResult(Z,H,w))}async fetchSingleNewsletter(A,Q,$){let w=await $.getEntity({entityType:this.config.entityType,id:A});if(!w)throw Error(`Newsletter not found: ${A}`);let B=await this.resolveNavigation(w,$),X=[];if(w.metadata.entityIds?.length){let H=w.metadata.sourceEntityType??"post";X=(await Promise.all(w.metadata.entityIds.map(async(U)=>{let G=await $.getEntity({entityType:H,id:U});if(G){let D=G.metadata;return{id:U,title:D.title??U,url:`/${H}s/${D.slug??U}`}}return null}))).filter((U)=>U!==null)}let Y=j0Q(w),Z={id:w.id,subject:w.metadata.subject,status:w.metadata.status,content:Y,created:w.created,updated:w.updated,sentAt:w.metadata.sentAt,scheduledFor:w.metadata.scheduledFor,newsletter:w,prevNewsletter:B.prev?{id:B.prev.id,subject:B.prev.subject,url:B.prev.url}:null,nextNewsletter:B.next?{id:B.next.id,subject:B.next.subject,url:B.next.url}:null,sourceEntities:X.length>0?X:void 0};return Q.parse(Z)}}zA();p2();h0();var d08=W.object({prompt:W.string().optional().describe("AI generation prompt"),sourceEntityIds:W.array(W.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:W.enum(["post"]).optional().describe("Type of source entities"),content:W.string().optional().describe("Direct content (skip AI)"),subject:W.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:W.boolean().optional().describe("Create as queued (true) or draft (false)")});class yIA extends yZ{constructor(A,Q){super(A,Q,{schema:d08,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let $=A.addToQueue??!1,{prompt:w,sourceEntityIds:B,sourceEntityType:X}=A,{content:Y,subject:Z}=A;if(Y){if(!Z)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(B&&B.length>0){let D=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let J=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(J.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${J.length} posts`});let L=`Create an engaging newsletter that highlights these blog posts:
10398
10398
 
10399
10399
  ${J.map((b)=>`## ${b.metadata.title}
10400
10400
 
@@ -10463,17 +10463,17 @@ Newsletter-specific guidelines:
10463
10463
  - "Reply and let me know..."
10464
10464
  - "Until next time..."
10465
10465
 
10466
- The goal is to build a relationship with readers through valuable, authentic content.`});h0();zA();import{jsxDEV as EH,Fragment as t08}from"preact/jsx-dev-runtime";var r08=W.enum(["generating","draft","queued","published","failed"]),o08=W.object({id:W.string(),subject:W.string(),status:r08,excerpt:W.string(),created:W.string(),sentAt:W.string().optional(),url:W.string()}),s08=W.object({newsletters:W.array(o08),totalCount:W.number(),pagination:cD0.nullable()}),a08=({newsletters:A,totalCount:Q,pageTitle:$,pagination:w,baseUrl:B="/newsletters"})=>{let X=$??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return EH(t08,{children:[EH(E6,{title:X,description:Y},void 0,!1,void 0,this),EH("div",{className:"newsletter-list bg-theme",children:EH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[EH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?EH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):EH("div",{className:"space-y-4",children:A.map((Z)=>EH(v8,{href:Z.url,children:[EH(AY,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),EH(SY,{children:EH("div",{className:"flex items-center gap-3",children:[EH(sK,{status:Z.status},void 0,!1,void 0,this),EH("span",{className:"text-sm text-theme-muted",children:g9(Z.sentAt??Z.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z.excerpt&&EH("p",{className:"text-theme-muted line-clamp-2",children:Z.excerpt},void 0,!1,void 0,this)]},Z.id,!0,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&EH(Ub,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},k0Q=G2({name:"newsletter-list",description:"Newsletter list page template",schema:s08,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:a08}});h0();zA();import{jsxDEV as c5,Fragment as wA8}from"preact/jsx-dev-runtime";var e08=W.enum(["generating","draft","queued","published","failed"]),AA8=W.object({id:W.string(),title:W.string(),url:W.string()}),O0Q=W.object({id:W.string(),subject:W.string(),url:W.string()}),QA8=W.object({id:W.string(),subject:W.string(),status:e08,content:W.string(),created:W.string(),updated:W.string(),sentAt:W.string().optional(),scheduledFor:W.string().optional(),sourceEntities:W.array(AA8).optional(),prevNewsletter:O0Q.nullable().optional(),nextNewsletter:O0Q.nullable().optional()}),$A8=({subject:A,status:Q,content:$,created:w,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:H})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],U=B??w,G=B?"Sent":"Created";return c5(wA8,{children:[c5(E6,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),c5("section",{className:"newsletter-detail-section",children:c5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:c5("div",{className:"max-w-3xl mx-auto",children:[c5(yL,{items:K},void 0,!1,void 0,this),c5("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),c5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[c5(sK,{status:Q},void 0,!1,void 0,this),c5("span",{children:[G,": ",g9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&c5("span",{children:["Scheduled for: ",g9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&c5(v8,{variant:"compact",className:"mb-8",children:[c5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),c5("ul",{className:"space-y-1",children:Y.map((D)=>c5("li",{children:c5("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5(XX,{markdown:$},void 0,!1,void 0,this),(Z??H)&&c5("nav",{className:"mt-12 pt-8 border-t border-theme",children:c5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?c5(v8,{href:Z.url,variant:"compact",children:[c5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),c5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Z.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):c5("div",{},void 0,!1,void 0,this),H&&c5(v8,{href:H.url,variant:"compact",className:"md:text-right",children:[c5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),c5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:H.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)},f0Q=G2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:QA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:$A8}});var Xf0={name:"@brains/newsletter",version:"0.2.0-alpha.195",description:"Newsletter composite \u2014 bundles the newsletter entity with the buttondown service plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var YA8=W.looseObject({}),ZA8=W.object({prompt:W.string().optional(),content:W.string().optional()});class Yf0 extends c6{entityType="newsletter";schema=Go;adapter=b0Q;constructor(A={}){super("newsletter",Xf0,A,YA8)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new yIA(this.logger,A)}getTemplates(){return{generation:M0Q,"newsletter-list":k0Q,"newsletter-detail":f0Q}}getDataSources(){return[new TIA(this.logger.child("NewsletterDataSource"))]}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToGenerateExecute(A),this.registerEvalHandlers(A),A.messaging.subscribe("system:plugins:ready",async()=>{let Q=await A.messaging.send({type:"buttondown:is-configured",payload:{}});if(!("noop"in Q)&&Q.success)await A.messaging.send({type:"plugin:site-builder:slot:register",payload:{pluginId:this.id,slotName:"footer-top",render:()=>XA8(FzA,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async($,w)=>{let B=typeof w.subject==="string"?w.subject:"",X=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:B,content:$}});return{id:!("noop"in X)&&X.data?.emailId?X.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:10}});if($.length===0)return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:"No published posts available for newsletter"}}),{success:!0};return await A.jobs.enqueue({type:"newsletter:generation",data:{sourceEntityIds:$.map((w)=>w.id),sourceEntityType:"post",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}}),{success:!0}}catch($){return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:eA($)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let $=ZA8.parse(Q),w=$.content?`Create an engaging newsletter based on this content:
10466
+ The goal is to build a relationship with readers through valuable, authentic content.`});h0();zA();import{jsxDEV as EH,Fragment as t08}from"preact/jsx-dev-runtime";var r08=W.enum(["generating","draft","queued","published","failed"]),o08=W.object({id:W.string(),subject:W.string(),status:r08,excerpt:W.string(),created:W.string(),sentAt:W.string().optional(),url:W.string()}),s08=W.object({newsletters:W.array(o08),totalCount:W.number(),pagination:cD0.nullable()}),a08=({newsletters:A,totalCount:Q,pageTitle:$,pagination:w,baseUrl:B="/newsletters"})=>{let X=$??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return EH(t08,{children:[EH(E6,{title:X,description:Y},void 0,!1,void 0,this),EH("div",{className:"newsletter-list bg-theme",children:EH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[EH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?EH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):EH("div",{className:"space-y-4",children:A.map((Z)=>EH(v8,{href:Z.url,children:[EH(AY,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),EH(SY,{children:EH("div",{className:"flex items-center gap-3",children:[EH(sK,{status:Z.status},void 0,!1,void 0,this),EH("span",{className:"text-sm text-theme-muted",children:g9(Z.sentAt??Z.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z.excerpt&&EH("p",{className:"text-theme-muted line-clamp-2",children:Z.excerpt},void 0,!1,void 0,this)]},Z.id,!0,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&EH(Ub,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},k0Q=G2({name:"newsletter-list",description:"Newsletter list page template",schema:s08,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:a08}});h0();zA();import{jsxDEV as c5,Fragment as wA8}from"preact/jsx-dev-runtime";var e08=W.enum(["generating","draft","queued","published","failed"]),AA8=W.object({id:W.string(),title:W.string(),url:W.string()}),O0Q=W.object({id:W.string(),subject:W.string(),url:W.string()}),QA8=W.object({id:W.string(),subject:W.string(),status:e08,content:W.string(),created:W.string(),updated:W.string(),sentAt:W.string().optional(),scheduledFor:W.string().optional(),sourceEntities:W.array(AA8).optional(),prevNewsletter:O0Q.nullable().optional(),nextNewsletter:O0Q.nullable().optional()}),$A8=({subject:A,status:Q,content:$,created:w,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:H})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],U=B??w,G=B?"Sent":"Created";return c5(wA8,{children:[c5(E6,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),c5("section",{className:"newsletter-detail-section",children:c5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:c5("div",{className:"max-w-3xl mx-auto",children:[c5(yL,{items:K},void 0,!1,void 0,this),c5("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),c5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[c5(sK,{status:Q},void 0,!1,void 0,this),c5("span",{children:[G,": ",g9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&c5("span",{children:["Scheduled for: ",g9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&c5(v8,{variant:"compact",className:"mb-8",children:[c5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),c5("ul",{className:"space-y-1",children:Y.map((D)=>c5("li",{children:c5("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c5(XX,{markdown:$},void 0,!1,void 0,this),(Z??H)&&c5("nav",{className:"mt-12 pt-8 border-t border-theme",children:c5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?c5(v8,{href:Z.url,variant:"compact",children:[c5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),c5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Z.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):c5("div",{},void 0,!1,void 0,this),H&&c5(v8,{href:H.url,variant:"compact",className:"md:text-right",children:[c5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),c5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:H.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)},f0Q=G2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:QA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:$A8}});var Xf0={name:"@brains/newsletter",version:"0.2.0-alpha.196",description:"Newsletter composite \u2014 bundles the newsletter entity with the buttondown service plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var YA8=W.looseObject({}),ZA8=W.object({prompt:W.string().optional(),content:W.string().optional()});class Yf0 extends c6{entityType="newsletter";schema=Go;adapter=b0Q;constructor(A={}){super("newsletter",Xf0,A,YA8)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new yIA(this.logger,A)}getTemplates(){return{generation:M0Q,"newsletter-list":k0Q,"newsletter-detail":f0Q}}getDataSources(){return[new TIA(this.logger.child("NewsletterDataSource"))]}async onRegister(A){this.deferPublishRegistration(A),this.subscribeToGenerateExecute(A),this.registerEvalHandlers(A),A.messaging.subscribe("system:plugins:ready",async()=>{let Q=await A.messaging.send({type:"buttondown:is-configured",payload:{}});if(!("noop"in Q)&&Q.success)await A.messaging.send({type:"plugin:site-builder:slot:register",payload:{pluginId:this.id,slotName:"footer-top",render:()=>XA8(FzA,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async($,w)=>{let B=typeof w.subject==="string"?w.subject:"",X=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:B,content:$}});return{id:!("noop"in X)&&X.data?.emailId?X.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:10}});if($.length===0)return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:"No published posts available for newsletter"}}),{success:!0};return await A.jobs.enqueue({type:"newsletter:generation",data:{sourceEntityIds:$.map((w)=>w.id),sourceEntityType:"post",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}}),{success:!0}}catch($){return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:eA($)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let $=ZA8.parse(Q),w=$.content?`Create an engaging newsletter based on this content:
10467
10467
 
10468
10468
  ${$.content}`:$.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:w,templateName:"newsletter:generation"})})}}function Zf0(A={}){return new Yf0(A)}zA();h0();h0();var HA8="https://api.buttondown.email/v1",KA8=W.enum(["unactivated","regular","unsubscribed","already_subscribed"]),UA8=W.enum(["draft","about_to_send","scheduled","sent"]),gIA=W.looseObject({id:W.string(),email:W.string(),subscriber_type:KA8,metadata:W.record(W.string(),W.string()).optional()}),x0Q=W.looseObject({id:W.string(),subject:W.string(),body:W.string().optional(),status:UA8,publish_date:W.string().optional()}),GA8=W.looseObject({results:W.array(gIA),count:W.number()}),DA8=W.looseObject({detail:W.string().optional(),message:W.string().optional(),code:W.string().optional()});class SIA extends Error{status;code;constructor(A,Q,$){super(A);this.name="ButtondownApiError",this.status=Q,this.code=$}}class cy{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let $=`${HA8}${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let w=await fetch($,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!w.ok){let B=await w.json().catch(()=>({})),X=DA8.safeParse(B),Y=X.success?X.data.detail??X.data.message??`HTTP ${w.status}`:`HTTP ${w.status}`,Z=X.success?X.data.code:void 0;throw this.logger.error("Buttondown API error",{endpoint:A,status:w.status,code:Z,error:Y}),new SIA(`Buttondown API error: ${Y}`,w.status,Z)}return w.json()}async createSubscriber(A){let Q={email_address:A.email,type:this.config.doubleOptIn?"unactivated":"regular"};if(A.name)Q.metadata={name:A.name};if(A.tags&&A.tags.length>0)Q.tags=A.tags;this.logger.info("Creating subscriber",{email:A.email});try{return gIA.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch($){if($ instanceof SIA&&$.code==="email_already_exists")return this.logger.info("Subscriber already exists",{email:A.email}),{...await this.getSubscriberByEmail(A.email),subscriber_type:"already_subscribed"};throw $}}async getSubscriberByEmail(A){return gIA.parse(await this.request(`/subscribers/${encodeURIComponent(A)}`))}async unsubscribe(A){this.logger.info("Unsubscribing",{email:A}),await this.request(`/subscribers/${encodeURIComponent(A)}`,{method:"DELETE"})}async listSubscribers(A){let Q=new URLSearchParams;if(A?.type)Q.set("type",A.type);if(A?.limit)Q.set("page_size",String(A.limit));let $=Q.toString(),w=$?`/subscribers?${$}`:"/subscribers";return GA8.parse(await this.request(w))}async createEmail(A){let Q={subject:A.subject,body:A.body,status:A.status??"draft"};if(A.publish_date)Q.publish_date=A.publish_date;return this.logger.info("Creating email",{subject:A.subject,status:A.status??"draft"}),x0Q.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return x0Q.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}zA();h0();var R0Q=W.string().email({pattern:W.regexes.html5Email}),qA8=W.object({email:R0Q.describe("Email address to subscribe"),name:W.string().optional().describe("Subscriber name (optional)"),tags:W.array(W.string()).optional().describe("Tags to apply to subscriber (optional)")}),zA8=W.object({email:R0Q.describe("Email address to unsubscribe")}),VA8=W.object({type:W.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:W.number().optional().describe("Maximum number of results")});function v0Q(A,Q,$){let w=new cy(Q,$);return[e8(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",qA8,async(B)=>{try{let X=await w.createSubscriber({email:B.email,...B.name&&{name:B.name},...B.tags&&{tags:B.tags}}),Y=X.subscriber_type==="already_subscribed";return d7({subscriberId:X.id,email:X.email,status:X.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${B.email} is already subscribed`:`Subscribed ${B.email} successfully`)}catch(X){return jY(eA(X))}}),e8(A,"unsubscribe","Unsubscribe an email address from the newsletter.",zA8,async(B)=>{try{return await w.unsubscribe(B.email),d7({email:B.email},`Unsubscribed ${B.email} successfully`)}catch(X){return jY(eA(X))}}),e8(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",VA8,async(B)=>{try{let X=await w.listSubscribers({...B.type&&{type:B.type},...B.limit&&{limit:B.limit}});return d7({subscribers:X.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:X.count},`Found ${X.count} subscribers`)}catch(X){return jY(eA(X))}})]}async function C0Q(A,Q,$,w){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let B=await $.getEntity({entityType:"post",id:A.entityId});if(!B)return{success:!1,error:`Post ${A.entityId} not found`};w.info("Auto-sending newsletter for published post",{postId:B.id,title:B.metadata.title});try{let X=await Q.createEmail({subject:B.metadata.title,body:B.content,status:"about_to_send"});return w.info("Newsletter sent for post",{postId:B.id,emailId:X.id}),{success:!0,emailId:X.id}}catch(X){let Y=eA(X);return w.error("Failed to send newsletter for post",{postId:B.id,error:Y}),{success:!1,error:Y}}}var JA8=W.object({apiKey:W.string().optional().describe("Buttondown API key"),doubleOptIn:W.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:W.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class Wf0 extends d6{constructor(A={}){super("buttondown",Xf0,A,JA8)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new cy({apiKey:this.config.apiKey,doubleOptIn:this.config.doubleOptIn},this.logger);if(A.messaging.subscribe("buttondown:send",async($)=>{try{return{success:!0,data:{emailId:(await Q.createEmail({subject:$.payload.subject,body:$.payload.content,status:"about_to_send"})).id}}}catch(w){return this.logger.error("Buttondown send failed",{error:eA(w)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async($)=>{let w=await C0Q($.payload,Q,A.entityService,this.logger);if(!w.success)return this.logger.error("Buttondown auto-send failed",{entityId:$.payload.entityId,error:w.error}),{success:!1,error:w.error};return{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return v0Q(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 Hf0(A={}){return new Wf0(A)}var FA8=W.object({apiKey:W.string().optional().describe("Buttondown API key"),doubleOptIn:W.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:W.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function h0Q(A={}){let Q=FA8.safeParse(A);if(!Q.success)throw new KN("newsletter",Q.error.issues.map((w)=>({path:w.path.map(String).join("."),code:w.code,message:w.message})));let $=Q.data;return[Zf0({}),Hf0({...$.apiKey!==void 0&&{apiKey:$.apiKey},...$.doubleOptIn!==void 0&&{doubleOptIn:$.doubleOptIn},...$.autoSendOnPublish!==void 0&&{autoSendOnPublish:$.autoSendOnPublish}})]}zA();h0();import{existsSync as vA8,mkdirSync as CA8,writeFileSync as hA8}from"fs";import{join as vb}from"path";h0();var mIA=W.object({baseFolder:W.string().default("_obsidian")});function uIA(A){return typeof A==="object"&&A!==null}function a90(A){if(!uIA(A))return;let Q=A.def;return uIA(Q)?Q:void 0}function E0Q(A){let Q=a90(A)?.type;return typeof Q==="string"?Q:void 0}function LA8(A){return typeof A==="function"?A():A}function IA8(A){let Q=A,$=!0,w=void 0,B=!1,X=!0;while(X){X=!1;let Z=a90(Q),H=E0Q(Q);if(H==="optional"||H==="nullable"){$=!1,Q=Z?.innerType,X=!0;continue}if(H==="default")$=!1,B=!0,w=LA8(Z?.defaultValue),Q=Z?.innerType,X=!0}let Y={inner:Q,required:$};if(B)Y.defaultValue=w;return Y}function NA8(A){let $=a90(A)?.entries;if(!uIA($))return;let w=Object.values($);if(!w.every((B)=>typeof B==="string"))return;return w}function _A8(A){let Q=a90(A),$=Q?.values;if(Array.isArray($))return $[0];return Q?.value}function T0Q(A){let Q=E0Q(A);if(Q==="enum"){let $=NA8(A);return $?{type:"enum",enumValues:$}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:_A8(A)};if(Q==="string")return{type:"string"};if(Q==="number")return{type:"number"};if(Q==="boolean")return{type:"boolean"};if(Q==="array")return{type:"array"};if(Q==="date")return{type:"date"};if(Q==="pipeline"||Q==="pipe"){let $=a90(A);return T0Q($?.out)}return{type:"unknown"}}function y0Q(A){let Q=[];for(let[$,w]of Object.entries(A.shape)){let{inner:B,required:X,defaultValue:Y}=IA8(w),Z=T0Q(B),H={name:$,type:Z.type,required:X},K=Y!==void 0?Y:Z.defaultValue;if(K!==void 0)H.defaultValue=K;if(Z.enumValues)H.enumValues=Z.enumValues;Q.push(H)}return Q}function PA8(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 g0Q(A,Q,$=""){let w=["---"];for(let B of Q){let X=PA8(B,A);if(X==="")w.push(`${B.name}:`);else w.push(`${B.name}: ${X}`)}if(w.push("---"),w.push(""),$)w.push($);else w.push("<!-- Write your content here -->"),w.push("");return w.join(`
10469
10469
  `)}Fp();var bA8={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function jA8(A){let Q={name:A.name,id:A.name,type:bA8[A.type]};if(A.type==="enum"&&A.enumValues){let $={};A.enumValues.forEach((w,B)=>{$[String(B)]=w}),Q.options=$}return Q}function S0Q(A,Q){let $={filesPaths:A,fields:Q.map(jA8)};return`---
10470
10470
  ${Jp($)}---
10471
- `}p2();Fp();var MA8=new Set(["entityType"]),kA8={base:"Notes"},OA8=new Set(["note"]);function fA8(A){let Q=["file.name"];for(let $ of A)if(!MA8.has($.name))Q.push($.name);return Q}function xA8(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function m0Q(A,Q){let $=kA8[A]??EyA(A),w=xA8(Q),B=fA8(Q),X=[{type:"table",name:`All ${$}`,order:B}];if(w)X.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:B});let Z={filters:{and:[OA8.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${$}.base`,content:Jp(Z),hasStatus:w}}function u0Q(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w}")`),$={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return Jp($)}function c0Q(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w.entityType}")`),$={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 Jp($)}var p0Q={name:"@brains/obsidian-vault",version:"0.2.0-alpha.195",description:"Obsidian vault integration \u2014 generates templates from entity schemas",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var EA8={mkdir:CA8,writeFile:hA8,existsFile:vA8},TA8=W.object({entityTypes:W.array(W.string()).optional().describe("Entity types to generate templates for (default: all)")});class cIA extends d6{deps;constructor(A={},Q={}){super("obsidian-vault",p0Q,A,mIA);this.deps={...EA8,...Q}}async onReady(A){this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A)}async getTools(){let A=this.getContext();return[e8(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",TA8,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let $=A.entityService.getEntityTypes(),w=Q?$.filter((L)=>Q.includes(L)):$,B=vb(A.dataDir,this.config.baseFolder),X=vb(B,"templates"),Y=vb(B,"fileClasses"),Z=vb(B,"bases");this.deps.mkdir(X,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(Z,{recursive:!0});let H=[],K=[],U=[],G=[],D=[],q=[];for(let L of w){let _=A.entities.getEffectiveFrontmatterSchema(L);if(!_){this.logger.debug(`Skipping ${L}: no frontmatter schema`),K.push(L);continue}let j=y0Q(_),b=A.entities.getAdapter(L),f=b?.isSingleton===!0,v=S0Q(L,j);if(this.deps.writeFile(vb(Y,`${L}.md`),v),U.push(L),f){D.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let R=b?.getBodyTemplate()??"",O=g0Q(L,j,R);this.deps.writeFile(vb(X,`${L}.md`),O),H.push(L);let S=m0Q(L,j),u=vb(Z,S.filename);if(!this.deps.existsFile(u))this.deps.writeFile(u,S.content),G.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)q.push({entityType:L,fields:j});this.logger.debug(`Generated template + fileClass: ${L}`)}let J=u0Q(D);if(J){let L=vb(Z,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,J),G.push("Settings"),this.logger.debug("Generated Settings.base")}let F=c0Q(q);if(F){let L=vb(Z,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,F),G.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${H.length} templates, ${U.length} fileClasses, ${G.length} bases (${K.length} skipped)`),d7({generated:H,skipped:K,fileClasses:U,bases:G})}catch($){return this.logger.error("Failed to sync",{error:$}),jY($ instanceof Error?$.message:"Unknown error")}}}function pIA(A={},Q){return new cIA(A,Q)}Y20();zA();h0();var l0Q={name:"@brains/notifications",version:"0.2.0-alpha.195",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};Y20();var gA8=W.looseObject({defaultRecipient:yz0.optional()});class i0Q extends d6{constructor(A={}){super("notifications",l0Q,A,gA8)}async onRegister(A){A.messaging.subscribe($h,async(Q)=>{let $=XAA.parse(Q.payload),w=$.recipient??this.config.defaultRecipient;if(!w)return A.logger.warn("Notification has no recipient"),{success:!1,error:"Notification recipient missing"};let B={to:w.address,subject:$.title,text:$.body,...$.html?{html:$.html}:{},sensitivity:$.sensitivity},X=await A.messaging.send({type:Vb0,payload:B});if(!("success"in X)||!X.success||!X.data)return{success:!1,error:"Notification delivery failed"};let Y=X.data;if(Y.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:Y.id?{status:"sent",deliveryId:Y.id}:{status:"sent"}}})}}function Kf0(A={}){return new i0Q(A)}Uw();zA();zA();p2();e9();zA();h0();var Uf0=W.enum(["draft","active","archived"]),Gf0=W.enum(["anchor","trusted","public"]),Df0=W.enum(["agent-confirmed","manual"]),SA8=W.enum(["draft","active","archived"]),mA8=W.enum(["anchor","trusted","public"]),uA8=W.enum(["agent-confirmed","manual"]),GI=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),Cb=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),lIA=W.object({event:W.string().min(1),target:W.string().min(1),operatorAction:W.boolean().optional(),label:Cb,description:Cb,operatorDescription:Cb}),iIA=W.object({id:W.string().min(1),title:W.string().min(1),prompt:Cb,requiredDetails:W.array(W.string().min(1)).default([]),instructions:W.array(W.string().min(1)).default([]),doneWhen:W.array(W.string().min(1)).default([]),transitions:W.array(lIA).default([])}),qf0=W.object({purpose:W.string().min(1),operatingRules:W.array(W.string().min(1)).default([]),initialState:W.string().min(1),states:W.array(iIA).min(1),finalStates:W.array(W.string().min(1)).min(1),nextPrompts:W.array(W.string().min(1)).default([])}),Do=W.object({title:W.string(),status:Uf0.default("active"),audience:Gf0.default("anchor"),trigger:GI.optional(),lifecycle:GI.optional(),once:W.boolean().optional(),starterText:GI.optional(),description:GI.optional(),starterPrompt:GI.optional(),completionMode:Df0.default("agent-confirmed")}),d0Q=W.object({title:W.string(),status:Uf0,audience:Gf0,trigger:GI.optional(),lifecycle:GI.optional(),once:W.boolean().optional(),starterText:GI.optional(),description:GI.optional(),starterPrompt:GI.optional(),completionMode:Df0}),cA8=W.object({title:W.string(),status:SA8,audience:mA8,trigger:Cb.optional(),lifecycle:Cb.optional(),once:W.boolean().optional(),starterText:Cb.optional(),description:Cb.optional(),starterPrompt:Cb.optional(),completionMode:uA8}),qo=U6.extend({entityType:W.literal("playbook"),metadata:cA8});class zf0 extends n${constructor(){super(qf0,{title:"Playbook",mappings:[{key:"purpose",label:"Purpose",type:"string"},{key:"operatingRules",label:"Operating Rules",type:"array",itemType:"string"},{key:"initialState",label:"Initial State",type:"string"},{key:"states",label:"States",type:"array",itemType:"object",itemMappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"prompt",label:"Prompt",type:"custom",formatter:dIA,parser:nIA},{key:"requiredDetails",label:"Required Details",type:"array",itemType:"string"},{key:"instructions",label:"Instructions",type:"array",itemType:"string"},{key:"doneWhen",label:"Done When",type:"array",itemType:"string"},{key:"transitions",label:"Transitions",type:"array",itemType:"object",itemMappings:[{key:"event",label:"Event",type:"string"},{key:"target",label:"Target",type:"string"},{key:"operatorAction",label:"User Choice",type:"custom",formatter:pA8,parser:lA8},{key:"label",label:"Label",type:"custom",formatter:dIA,parser:nIA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:dIA,parser:nIA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var t90=new zf0;function dIA(A){return typeof A==="string"?A:""}function nIA(A){let Q=A.trim();return Q.length>0?Q:void 0}function pA8(A){return typeof A==="boolean"?String(A):""}function lA8(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function rIA(A){let Q=[],$=new Set,w=new Set;for(let B of A.states){if($.has(B.id))w.add(B.id);$.add(B.id)}if(!$.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let B of w)Q.push(`Duplicate playbook state id '${B}'.`);for(let B of A.finalStates)if(!$.has(B))Q.push(`Playbook final state '${B}' is not defined.`);for(let B of A.states)for(let X of B.transitions)if(!$.has(X.target))Q.push(`Playbook transition '${B.id}' -> '${X.target}' targets an undefined state.`);for(let B of iA8(A,$))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function zo(A){let Q=rIA(A);if(!Q.valid)throw Error(Q.errors.join(`
10471
+ `}p2();Fp();var MA8=new Set(["entityType"]),kA8={base:"Notes"},OA8=new Set(["note"]);function fA8(A){let Q=["file.name"];for(let $ of A)if(!MA8.has($.name))Q.push($.name);return Q}function xA8(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function m0Q(A,Q){let $=kA8[A]??EyA(A),w=xA8(Q),B=fA8(Q),X=[{type:"table",name:`All ${$}`,order:B}];if(w)X.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:B});let Z={filters:{and:[OA8.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${$}.base`,content:Jp(Z),hasStatus:w}}function u0Q(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w}")`),$={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return Jp($)}function c0Q(A){if(A.length===0)return null;let Q=A.map((w)=>`file.inFolder("${w.entityType}")`),$={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 Jp($)}var p0Q={name:"@brains/obsidian-vault",version:"0.2.0-alpha.196",description:"Obsidian vault integration \u2014 generates templates from entity schemas",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var EA8={mkdir:CA8,writeFile:hA8,existsFile:vA8},TA8=W.object({entityTypes:W.array(W.string()).optional().describe("Entity types to generate templates for (default: all)")});class cIA extends d6{deps;constructor(A={},Q={}){super("obsidian-vault",p0Q,A,mIA);this.deps={...EA8,...Q}}async onReady(A){this.logger.info("Auto-syncing Obsidian templates, fileClasses, and bases"),await this.sync(A)}async getTools(){let A=this.getContext();return[e8(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",TA8,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let $=A.entityService.getEntityTypes(),w=Q?$.filter((L)=>Q.includes(L)):$,B=vb(A.dataDir,this.config.baseFolder),X=vb(B,"templates"),Y=vb(B,"fileClasses"),Z=vb(B,"bases");this.deps.mkdir(X,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(Z,{recursive:!0});let H=[],K=[],U=[],G=[],D=[],q=[];for(let L of w){let _=A.entities.getEffectiveFrontmatterSchema(L);if(!_){this.logger.debug(`Skipping ${L}: no frontmatter schema`),K.push(L);continue}let j=y0Q(_),b=A.entities.getAdapter(L),f=b?.isSingleton===!0,v=S0Q(L,j);if(this.deps.writeFile(vb(Y,`${L}.md`),v),U.push(L),f){D.push(L),this.logger.debug(`Generated fileClass (singleton): ${L}`);continue}let R=b?.getBodyTemplate()??"",O=g0Q(L,j,R);this.deps.writeFile(vb(X,`${L}.md`),O),H.push(L);let S=m0Q(L,j),u=vb(Z,S.filename);if(!this.deps.existsFile(u))this.deps.writeFile(u,S.content),G.push(L),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)q.push({entityType:L,fields:j});this.logger.debug(`Generated template + fileClass: ${L}`)}let J=u0Q(D);if(J){let L=vb(Z,"Settings.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,J),G.push("Settings"),this.logger.debug("Generated Settings.base")}let F=c0Q(q);if(F){let L=vb(Z,"Pipeline.base");if(!this.deps.existsFile(L))this.deps.writeFile(L,F),G.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${H.length} templates, ${U.length} fileClasses, ${G.length} bases (${K.length} skipped)`),d7({generated:H,skipped:K,fileClasses:U,bases:G})}catch($){return this.logger.error("Failed to sync",{error:$}),jY($ instanceof Error?$.message:"Unknown error")}}}function pIA(A={},Q){return new cIA(A,Q)}Y20();zA();h0();var l0Q={name:"@brains/notifications",version:"0.2.0-alpha.196",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};Y20();var gA8=W.looseObject({defaultRecipient:yz0.optional()});class i0Q extends d6{constructor(A={}){super("notifications",l0Q,A,gA8)}async onRegister(A){A.messaging.subscribe($h,async(Q)=>{let $=XAA.parse(Q.payload),w=$.recipient??this.config.defaultRecipient;if(!w)return A.logger.warn("Notification has no recipient"),{success:!1,error:"Notification recipient missing"};let B={to:w.address,subject:$.title,text:$.body,...$.html?{html:$.html}:{},sensitivity:$.sensitivity},X=await A.messaging.send({type:Vb0,payload:B});if(!("success"in X)||!X.success||!X.data)return{success:!1,error:"Notification delivery failed"};let Y=X.data;if(Y.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:Y.id?{status:"sent",deliveryId:Y.id}:{status:"sent"}}})}}function Kf0(A={}){return new i0Q(A)}Uw();zA();zA();p2();e9();zA();h0();var Uf0=W.enum(["draft","active","archived"]),Gf0=W.enum(["anchor","trusted","public"]),Df0=W.enum(["agent-confirmed","manual"]),SA8=W.enum(["draft","active","archived"]),mA8=W.enum(["anchor","trusted","public"]),uA8=W.enum(["agent-confirmed","manual"]),GI=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),Cb=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),lIA=W.object({event:W.string().min(1),target:W.string().min(1),operatorAction:W.boolean().optional(),label:Cb,description:Cb,operatorDescription:Cb}),iIA=W.object({id:W.string().min(1),title:W.string().min(1),prompt:Cb,requiredDetails:W.array(W.string().min(1)).default([]),instructions:W.array(W.string().min(1)).default([]),doneWhen:W.array(W.string().min(1)).default([]),transitions:W.array(lIA).default([])}),qf0=W.object({purpose:W.string().min(1),operatingRules:W.array(W.string().min(1)).default([]),initialState:W.string().min(1),states:W.array(iIA).min(1),finalStates:W.array(W.string().min(1)).min(1),nextPrompts:W.array(W.string().min(1)).default([])}),Do=W.object({title:W.string(),status:Uf0.default("active"),audience:Gf0.default("anchor"),trigger:GI.optional(),lifecycle:GI.optional(),once:W.boolean().optional(),starterText:GI.optional(),description:GI.optional(),starterPrompt:GI.optional(),completionMode:Df0.default("agent-confirmed")}),d0Q=W.object({title:W.string(),status:Uf0,audience:Gf0,trigger:GI.optional(),lifecycle:GI.optional(),once:W.boolean().optional(),starterText:GI.optional(),description:GI.optional(),starterPrompt:GI.optional(),completionMode:Df0}),cA8=W.object({title:W.string(),status:SA8,audience:mA8,trigger:Cb.optional(),lifecycle:Cb.optional(),once:W.boolean().optional(),starterText:Cb.optional(),description:Cb.optional(),starterPrompt:Cb.optional(),completionMode:uA8}),qo=U6.extend({entityType:W.literal("playbook"),metadata:cA8});class zf0 extends n${constructor(){super(qf0,{title:"Playbook",mappings:[{key:"purpose",label:"Purpose",type:"string"},{key:"operatingRules",label:"Operating Rules",type:"array",itemType:"string"},{key:"initialState",label:"Initial State",type:"string"},{key:"states",label:"States",type:"array",itemType:"object",itemMappings:[{key:"id",label:"ID",type:"string"},{key:"title",label:"Title",type:"string"},{key:"prompt",label:"Prompt",type:"custom",formatter:dIA,parser:nIA},{key:"requiredDetails",label:"Required Details",type:"array",itemType:"string"},{key:"instructions",label:"Instructions",type:"array",itemType:"string"},{key:"doneWhen",label:"Done When",type:"array",itemType:"string"},{key:"transitions",label:"Transitions",type:"array",itemType:"object",itemMappings:[{key:"event",label:"Event",type:"string"},{key:"target",label:"Target",type:"string"},{key:"operatorAction",label:"User Choice",type:"custom",formatter:pA8,parser:lA8},{key:"label",label:"Label",type:"custom",formatter:dIA,parser:nIA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:dIA,parser:nIA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var t90=new zf0;function dIA(A){return typeof A==="string"?A:""}function nIA(A){let Q=A.trim();return Q.length>0?Q:void 0}function pA8(A){return typeof A==="boolean"?String(A):""}function lA8(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function rIA(A){let Q=[],$=new Set,w=new Set;for(let B of A.states){if($.has(B.id))w.add(B.id);$.add(B.id)}if(!$.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let B of w)Q.push(`Duplicate playbook state id '${B}'.`);for(let B of A.finalStates)if(!$.has(B))Q.push(`Playbook final state '${B}' is not defined.`);for(let B of A.states)for(let X of B.transitions)if(!$.has(X.target))Q.push(`Playbook transition '${B.id}' -> '${X.target}' targets an undefined state.`);for(let B of iA8(A,$))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function zo(A){let Q=rIA(A);if(!Q.valid)throw Error(Q.errors.join(`
10472
10472
  `))}function iA8(A,Q){if(!Q.has(A.initialState))return[];let $=new Set,w=[A.initialState];while(w.length>0){let B=w.shift();if(!B||$.has(B))continue;$.add(B);let X=A.states.find((Y)=>Y.id===B);if(!X)continue;for(let Y of X.transitions)if(Q.has(Y.target)&&!$.has(Y.target))w.push(Y.target)}return A.states.map((B)=>B.id).filter((B)=>!$.has(B))}class Jf0 extends zQ{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:qo,frontmatterSchema:Do})}createPlaybookContent(A,Q){return this.buildMarkdown(t90.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,Do),$=this.extractBody(A).trim(),w=dA8($)?nA8($):t90.parse($);return zo(w),{frontmatter:Do.parse(Q),body:w,bodyMarkdown:$}}fromMarkdown(A){let{frontmatter:Q}=this.parsePlaybookContent(A);return{content:A,entityType:"playbook",metadata:{title:Q.title,status:Q.status,audience:Q.audience,...Q.trigger?{trigger:Q.trigger}:{},...Q.lifecycle?{lifecycle:Q.lifecycle}:{},...Q.once!==void 0?{once:Q.once}:{},...Q.starterText?{starterText:Q.starterText}:{},...Q.description?{description:Q.description}:{},...Q.starterPrompt?{starterPrompt:Q.starterPrompt}:{},completionMode:Q.completionMode}}}}var py=new Jf0;function dA8(A){return/^##\s+Steps\s*$/im.test(A)}function nA8(A){let Q=rA8(oIA(A,"Steps"));if(Q.length===0)throw Error("Playbook must declare at least one step.");let $=Q.map((w,B)=>{let X=B===Q.length-1;if(!X&&w.doneWhen.length===0&&w.choices.length===0&&!w.skip)throw Error(`Playbook step '${w.title}' must declare Done when, Choices, or Skip.`);return{id:w.id,title:w.title,...w.prompt?{prompt:w.prompt}:{},requiredDetails:w.requiredDetails,instructions:w.instructions,doneWhen:w.doneWhen,transitions:[...w.doneWhen.length>0&&!X?[{event:"NEXT",target:Q[B+1]?.id??w.id}]:[],...w.choices.map((Y,Z)=>({event:`CHOICE_${Z+1}`,target:O1(Y.target),operatorAction:!0,label:Y.label})),...w.skip?[{event:"SKIP",target:O1(w.skip.target),operatorAction:!0,label:w.skip.label}]:[]]}});return{purpose:oA8(A,"Purpose"),operatingRules:n0Q(A,"Operating Rules"),initialState:Q[0]?.id??"",states:$,finalStates:[Q.at(-1)?.id??""],nextPrompts:n0Q(A,"Next Prompts")}}function rA8(A){let Q=[],$;for(let w of A.split(/\r?\n/)){let B=/^###\s+(.+?)\s*$/.exec(w);if(B){$={title:B[1]??"",content:[]},Q.push($);continue}$?.content.push(w)}return Q.map((w)=>{let B=w.content.join(`
10473
10473
  `);return{title:w.title,id:O1(w.title),...r0Q(B,"Say")?{prompt:r0Q(B,"Say")}:{},requiredDetails:Vf0(B,"Required details"),instructions:Vf0(B,"To do"),doneWhen:Vf0(B,"Done when"),choices:sA8(B,"Choices"),...o0Q(B)?{skip:o0Q(B)}:{}}})}function oIA(A,Q){let $=A.split(/\r?\n/),w=$.findIndex((X)=>X.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(w===-1)return"";let B=[];for(let X of $.slice(w+1)){if(/^##\s+/.test(X))break;B.push(X)}return B.join(`
10474
10474
  `).trim()}function oA8(A,Q){return oIA(A,Q).split(/\r?\n/).map(($)=>$.trim()).filter(($)=>$.length>0&&!$.startsWith("#")).join(`
10475
10475
  `).trim()}function n0Q(A,Q){return s0Q(oIA(A,Q))}function r0Q(A,Q){return new RegExp(`^${tA8(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function Vf0(A,Q){let $=A.split(/\r?\n/),w=$.findIndex((X)=>X.trim().toLowerCase()===`${Q.toLowerCase()}:`);if(w===-1)return[];let B=[];for(let X of $.slice(w+1)){let Y=X.trim();if(Y.length===0)continue;if(/^[A-Za-z][A-Za-z ]+:/.test(Y)||/^#{1,6}\s+/.test(Y))break;B.push(X)}return s0Q(B.join(`
10476
- `))}function sA8(A,Q){return Vf0(A,Q).map(aA8)}function aA8(A){let Q=/^(.+?)\s*(?:\u2192|->)\s*(.+)$/.exec(A);if(!Q)throw Error(`Invalid playbook choice '${A}'. Expected "Label \u2192 Step".`);return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function o0Q(A){let Q=/^Skip:\s*(.+?)\s*(?:\u2192|->)\s*(.+?)\s*$/im.exec(A);if(!Q)return;return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function s0Q(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function tA8(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}h0();var Ff0=W.object({}).catchall(W.unknown()).transform(()=>({}));var Lf0={name:"@brains/playbooks",version:"0.2.0-alpha.195",description:"Runtime orchestration for chat-native playbook runs",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.32.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var A18="playbook";class sIA extends c6{entityType=A18;schema=qo;adapter=py;constructor(A={}){super("playbook",Lf0,A,Ff0)}async getInstructions(){return"Playbook entities describe durable, editable guided workflows for the agent. Use them as operating guidance when a playbook run is active; do not treat them as content to publish unless the user explicitly asks."}}function aIA(A={}){return new sIA(A)}Uw();zA();h0();EZ();$20();function If0(A,Q){return A.length===Q.length&&A.every(($,w)=>$===Q[w])}function tIA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function Nf0(A,Q){return Q.gateVerdicts.some(($)=>$.stateId===A.id&&If0($.goal,A.doneWhen)&&$.met)}function Q18(A,Q,$){return F2.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map((w)=>{let B=Q.finalStates.includes(w.id);return[w.id,{...B?{type:"final"}:{},...B?{}:{on:Object.fromEntries(w.transitions.map((X)=>[X.event,{target:X.target,...tIA(w,X.event)?{guard:()=>Nf0(w,$)}:{}}]))}}]}))})}function eIA(A,Q){let $=Q18(Q.playbookId,A,Q);return F2.createActor($,{snapshot:$.resolveState({value:Q.currentState})})}function $18(A,Q,$){let w=eIA(Q,A);w.start();let B=w.getSnapshot().can({type:$});return w.stop(),B}function Vo(A,Q,$){return $.transitions.filter((w)=>$18(A,Q,w.event))}function e90(A,Q,$){let w=new Set(Vo(A,Q,$).map((B)=>`${B.event}\x00${B.target}`));return $.transitions.filter((B)=>!w.has(`${B.event}\x00${B.target}`))}function a0Q(A,Q){return A.evidence.filter(($)=>!$.stateId||$.stateId===Q)}function ly(A,Q){return A.states.find(($)=>$.id===Q)}function iy(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function t0Q(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let $=A.gateVerdicts.find((w)=>w.stateId===Q.id&&If0(w.goal,Q.doneWhen));if(!$)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return $.met?`- Met: ${$.reason}`:`- Not yet met: ${$.reason}`}function e0Q(A,Q,$){let w=Vo(A,Q,$),B=w.filter((H)=>H.operatorAction!==!0),X=w.filter((H)=>H.operatorAction===!0),Y=e90(A,Q,$),Z=A.gateVerdicts.find((H)=>H.stateId===$.id&&If0(H.goal,$.doneWhen));return[`Current state: ${$.id} (${$.title})`,"Instructions:",...$.instructions.map((H)=>`- ${H}`),"Done When:",...$.doneWhen.length>0?$.doneWhen.map((H)=>`- ${H}`):["- none"],"Goal status:",Z?`- ${Z.met?"Met":"Not yet met"}: ${Z.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...B.length>0?B.map((H)=>iy(H)):["- none"],"Available operator actions:",...X.length>0?X.map((H)=>iy(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>iy(H)):["- none"]].join(`
10476
+ `))}function sA8(A,Q){return Vf0(A,Q).map(aA8)}function aA8(A){let Q=/^(.+?)\s*(?:\u2192|->)\s*(.+)$/.exec(A);if(!Q)throw Error(`Invalid playbook choice '${A}'. Expected "Label \u2192 Step".`);return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function o0Q(A){let Q=/^Skip:\s*(.+?)\s*(?:\u2192|->)\s*(.+?)\s*$/im.exec(A);if(!Q)return;return{label:Q[1]?.trim()??"",target:Q[2]?.trim()??""}}function s0Q(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function tA8(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}h0();var Ff0=W.object({}).catchall(W.unknown()).transform(()=>({}));var Lf0={name:"@brains/playbooks",version:"0.2.0-alpha.196",description:"Runtime orchestration for chat-native playbook runs",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/runtime-state":"workspace:*","@brains/utils":"workspace:*",xstate:"^5.32.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var A18="playbook";class sIA extends c6{entityType=A18;schema=qo;adapter=py;constructor(A={}){super("playbook",Lf0,A,Ff0)}async getInstructions(){return"Playbook entities describe durable, editable guided workflows for the agent. Use them as operating guidance when a playbook run is active; do not treat them as content to publish unless the user explicitly asks."}}function aIA(A={}){return new sIA(A)}Uw();zA();h0();EZ();$20();function If0(A,Q){return A.length===Q.length&&A.every(($,w)=>$===Q[w])}function tIA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function Nf0(A,Q){return Q.gateVerdicts.some(($)=>$.stateId===A.id&&If0($.goal,A.doneWhen)&&$.met)}function Q18(A,Q,$){return F2.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map((w)=>{let B=Q.finalStates.includes(w.id);return[w.id,{...B?{type:"final"}:{},...B?{}:{on:Object.fromEntries(w.transitions.map((X)=>[X.event,{target:X.target,...tIA(w,X.event)?{guard:()=>Nf0(w,$)}:{}}]))}}]}))})}function eIA(A,Q){let $=Q18(Q.playbookId,A,Q);return F2.createActor($,{snapshot:$.resolveState({value:Q.currentState})})}function $18(A,Q,$){let w=eIA(Q,A);w.start();let B=w.getSnapshot().can({type:$});return w.stop(),B}function Vo(A,Q,$){return $.transitions.filter((w)=>$18(A,Q,w.event))}function e90(A,Q,$){let w=new Set(Vo(A,Q,$).map((B)=>`${B.event}\x00${B.target}`));return $.transitions.filter((B)=>!w.has(`${B.event}\x00${B.target}`))}function a0Q(A,Q){return A.evidence.filter(($)=>!$.stateId||$.stateId===Q)}function ly(A,Q){return A.states.find(($)=>$.id===Q)}function iy(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function t0Q(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let $=A.gateVerdicts.find((w)=>w.stateId===Q.id&&If0(w.goal,Q.doneWhen));if(!$)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return $.met?`- Met: ${$.reason}`:`- Not yet met: ${$.reason}`}function e0Q(A,Q,$){let w=Vo(A,Q,$),B=w.filter((H)=>H.operatorAction!==!0),X=w.filter((H)=>H.operatorAction===!0),Y=e90(A,Q,$),Z=A.gateVerdicts.find((H)=>H.stateId===$.id&&If0(H.goal,$.doneWhen));return[`Current state: ${$.id} (${$.title})`,"Instructions:",...$.instructions.map((H)=>`- ${H}`),"Done When:",...$.doneWhen.length>0?$.doneWhen.map((H)=>`- ${H}`):["- none"],"Goal status:",Z?`- ${Z.met?"Met":"Not yet met"}: ${Z.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...B.length>0?B.map((H)=>iy(H)):["- none"],"Available operator actions:",...X.length>0?X.map((H)=>iy(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>iy(H)):["- none"]].join(`
10477
10477
  `)}function AAQ(A){let{run:Q,body:$,state:w,playbookTitle:B}=A,X=Vo(Q,$,w),Y=X.filter((L)=>L.operatorAction!==!0),Z=X.filter((L)=>L.operatorAction===!0),H=e90(Q,$,w),K=Y.map((L)=>iy(L)).join(`
10478
10478
  `),U=Z.map((L)=>iy(L)).join(`
10479
10479
  `),G=H.map((L)=>iy(L)).join(`
@@ -10547,9 +10547,9 @@ ${Object.entries(A).map(([$,w])=>`- ${$}: playbookId=${w.playbookId}, trigger=${
10547
10547
  ${A.guidance}`:B}}function GAQ(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:J18(Q.data)}))}}function J18(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function F18(A){return{kind:"actions",id:`actions:playbook:${A.run.id}`,title:A.title,defaultOpen:!0,actions:A.transitions.map((Q)=>({type:"event",id:`playbook:${A.run.id}:${Q.event}`,label:Q.label??Q.operatorDescription??Q.description??Q.event,event:Q.event,fromState:A.run.currentState,...Q.operatorDescription??Q.description?{description:Q.operatorDescription??Q.description}:{}}))}}function L18(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function DAQ(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function qAQ(A,Q){let $=A.filter(Q),w=$.filter((B)=>B.status==="active"||B.status==="offered");return XNA(w)??XNA($)}function XNA(A){return[...A].sort((Q,$)=>($.completedAt??$.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function I18(A){return{async evaluate(Q){let $=Q.goal.join(`
10548
10548
  `),w=await A.entityService.search({query:$,options:{limit:8,excludeTypes:["playbook"],visibilityScope:AB("anchor")}}),B=N18(Q,w),{verdict:X}=await A.judge({instruction:"Decide whether the playbook goal is satisfied by the supplied current-run runtime evidence and KB excerpts. Current-run runtime evidence is authoritative for playbook completion; use KB excerpts as supporting context, not to override clear runtime evidence from this run. Return met=true only when the outcome clearly holds. If evidence is missing or ambiguous, return met=false with a short reason.",material:B,schema:G18});return X}}}function N18(A,Q){return["## Playbook run",`runId: ${A.run.id}`,`playbookId: ${A.run.playbookId}`,`currentState: ${A.state.id} (${A.state.title})`,"","## State instructions",...A.state.instructions.map(($)=>`- ${$}`),"","## Done When goal",...A.goal.map(($)=>`- ${$}`),"","## Runtime evidence",...A.evidence.length>0?A.evidence.map(($,w)=>_18(w+1,$)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map(($,w)=>P18(w+1,$)):["No relevant KB excerpts found."]].join(`
10549
10549
  `)}function _18(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${VAQ(Q.data)}`}function P18(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${JAQ(Q.entity.content,1200)}`,`Metadata: ${VAQ(Q.entity.metadata)}`].join(`
10550
- `)}function VAQ(A){try{return JAQ(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function JAQ(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var b18={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function ZNA(A={},Q={}){return new YNA(A,Q)}Uw();zA();h0();import{readFile as M18}from"fs/promises";import{join as k18}from"path";var FAQ={name:"@brains/rover-onboarding",version:"0.2.0-alpha.195",description:"Rover onboarding playbook bundle and activation plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/playbooks":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var O18=W.object({enabled:W.boolean().default(!1)}).strict(),LAQ=[{id:"rover-onboarding",fileName:"rover-onboarding.md",starter:{id:"onboarding",trigger:"first-anchor-web-chat",playbookId:"rover-onboarding",once:!0,starterText:"Set up Rover",description:"Tune Rover's identity and anchor profile before using the knowledge loop.",starterPrompt:"Start playbook rover-onboarding."}},{id:"rover-first-knowledge-loop",fileName:"rover-first-knowledge-loop.md"}];class IAQ extends d6{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",FAQ,A,O18)}async onReady(A){if(!this.config.enabled)return;for(let Q of LAQ)await this.seedPlaybookIfMissing(A,Q);for(let Q of LAQ){if(!Q.starter)continue;await A.messaging.send({type:gS,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let w=await M18(k18(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:w}})}}function NAQ(A={}){return new IAQ(A)}zA();h0();h0();zA();var WNA=W.enum(["new","planned","in-progress","done","declined"]),HNA=W.enum(["low","medium","high","critical"]),f18=W.enum(["new","planned","in-progress","done","declined"]),x18=W.enum(["low","medium","high","critical"]),A70=W.object({title:W.string(),status:WNA,priority:HNA.default("medium"),requested:W.number().int().default(1),declinedReason:W.string().optional()}),R18=W.object({title:W.string(),status:WNA,priority:HNA,requested:W.number().int(),slug:W.string()}),v18=W.object({title:W.string(),status:f18,priority:x18,requested:W.number().int(),slug:W.string()}),Q70=U6.extend({entityType:W.literal("wish"),metadata:v18});h0();var KNA=W.object({}).catchall(W.unknown()).transform(()=>({}));zA();p2();class $70 extends zQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Q70,frontmatterSchema:A70})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,A70);return{frontmatter:A70.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),$=O1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:$}}}}var _AQ=new $70;p2();p2();async function PAQ(A,Q){let $=`${Q.title}: ${Q.description}`,B=(await A.search({query:$,options:{types:["wish"],limit:1}}))[0];if(B&&B.score>=A.similarityThreshold)return B.entity;let X=O1(Q.title);return A.getEntity({entityType:"wish",id:X})}class jf0{logger;context;adapter=new $70;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,$){let w=A.title??A.prompt??"Untitled wish",B=A.content??A.prompt??"",X=await PAQ({search:(K)=>this.context.entityService.search(K),getEntity:(K)=>this.context.entityService.getEntity(K),similarityThreshold:0.85},{title:w,description:B});if(X){let{frontmatter:K,description:U}=this.adapter.parseWishContent(X.content),G=K.requested+1,D=this.adapter.createWishContent({...K,requested:G},U);return await this.context.entityService.updateEntity({entity:{...X,content:D,metadata:{...X.metadata,requested:G}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:G}),{success:!0,entityId:X.id,existed:!0,requested:G}}let Y=O1(w),Z=A.options?.priority??"medium",H=this.adapter.createWishContent({title:w,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,metadata:{title:w,status:"new",priority:Z,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:w}),{success:!0,entityId:Y,existed:!1,requested:1}}}var bAQ={critical:0,high:1,medium:2,low:3};function jAQ(A){A.sort((Q,$)=>{let w=$.metadata.requested-Q.metadata.requested;if(w!==0)return w;return bAQ[Q.metadata.priority]-bAQ[$.metadata.priority]})}var MAQ={name:"@brains/wishlist",version:"0.2.0-alpha.195",description:"Wishlist plugin for tracking unfulfilled user requests",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var h18=W.object({items:W.array(W.object({name:W.string(),count:W.number()}))}),E18="wish";class kAQ extends c6{entityType=E18;schema=Q70;adapter=_AQ;constructor(A={}){super("wishlist",MAQ,A,KNA)}async interceptCreate(A,Q,$){let w=await new jf0(this.logger,$).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!w.success)return{kind:"handled",result:{success:!1,error:w.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...w.entityId?{entityId:w.entityId}:{},status:w.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",group:"knowledge",section:"secondary",priority:30,rendererName:"ListWidget",digestProvider:($)=>{let{items:w}=h18.parse($),B=w[0];return{digest:B?[{label:"Top wish",value:`${B.name} \xB7 \xD7${B.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let $=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return jAQ($),{items:$.map((w)=>({id:w.id,name:w.metadata.title,count:w.metadata.requested,priority:w.metadata.priority,status:w.metadata.status}))}}}}),{success:!0}});let Q=new jf0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:($)=>$})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function T18(A={}){return new kAQ(A)}var Mf0=T18;zA();zA();h0();var w70=W.object({title:W.string(),target:W.string()}),OAQ=W.object({title:W.string(),target:W.string(),slug:W.string().optional()}),B70=U6.extend({entityType:W.literal("prompt"),metadata:OAQ});zA();p2();class UNA extends zQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:B70,frontmatterSchema:w70})}toMarkdown(A){let Q=this.extractBody(A.content),$=this.parseFrontMatter(A.content,w70);return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,w70),$=O1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:$}}}}var GNA=new UNA;var fAQ={name:"@brains/prompt",version:"0.2.0-alpha.195",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var g18="prompt";class DNA extends c6{entityType=g18;schema=B70;adapter=GNA;constructor(){super("prompt",fAQ,{},bY)}getEntityTypeConfig(){return{embeddable:!1}}}function ny(){return new DNA}zA();h0();h0();class kf0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let $=new URL(`${this.baseUrl}/search/photos`);$.searchParams.set("query",A),$.searchParams.set("page",String(Q.page)),$.searchParams.set("per_page",String(Q.perPage));let w=await this.fetchFn($.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!w.ok)throw Error(`Unsplash API error: ${w.status} ${w.statusText}`);let B=m18.parse(await w.json());return{photos:B.results.map(u18),total:B.total,totalPages:B.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var S18=W.looseObject({id:W.string(),description:W.string().nullable(),alt_description:W.string().nullable(),urls:W.looseObject({raw:W.url(),full:W.url(),regular:W.url(),small:W.url(),thumb:W.url()}),links:W.looseObject({html:W.url(),download_location:W.url()}),user:W.looseObject({name:W.string(),links:W.looseObject({html:W.url()})}),width:W.number().int().nonnegative(),height:W.number().int().nonnegative()}),m18=W.looseObject({total:W.number().int().nonnegative(),total_pages:W.number().int().nonnegative(),results:W.array(S18)});function u18(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}}h0();async function Of0(A,Q,$,w){let B=await A.getEntity({entityType:Q,id:$});if(!B)return!1;return await A.updateEntity({entity:{...B,metadata:{...B.metadata,coverImageId:w}}}),!0}var c18={query:W.string().describe("Search terms for stock photos"),perPage:W.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:W.number().min(1).default(1).describe("Page number")},p18={photoId:W.string().describe("Photo ID from search results"),downloadLocation:W.url().describe("Download tracking URL (required by provider ToS)"),photographerName:W.string().describe("Photographer name for attribution"),photographerUrl:W.url().describe("Photographer profile URL for attribution"),sourceUrl:W.url().describe("Photo page URL on provider"),imageUrl:W.url().describe("Image URL to download"),title:W.string().optional().describe("Image entity title"),alt:W.string().optional().describe("Alt text for the image"),targetEntityType:W.string().optional().describe("Entity type to set cover image on"),targetEntityId:W.string().optional().describe("Entity ID to set cover image on")},l18=W.object({query:W.string(),perPage:W.number().min(1).max(30).default(10),page:W.number().min(1).default(1)}),i18=W.object({photoId:W.string(),downloadLocation:W.url(),photographerName:W.string(),photographerUrl:W.url(),sourceUrl:W.url(),imageUrl:W.url(),title:W.string().optional(),alt:W.string().optional(),targetEntityType:W.string().optional(),targetEntityId:W.string().optional()});function xAQ(A,Q){return[d18(A,Q),n18(A,Q)]}function d18(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:c18,visibility:"anchor",sideEffects:"none",handler:async($)=>{let w=l18.safeParse($);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(w.data.query,{page:w.data.page,perPage:w.data.perPage})}}catch(B){return{success:!1,error:B instanceof Error?B.message:"Search failed"}}}}}function n18(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:p18,visibility:"anchor",sideEffects:"external",handler:async($)=>{let w=i18.safeParse($);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:K,title:U,alt:G,targetEntityType:D,targetEntityId:q}=w.data,J={photographerName:Y,photographerUrl:Z,sourceUrl:H},F=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(F[0]){let j={imageEntityId:F[0].id,alreadyExisted:!0,attribution:J};if(D&&q)j.coverSet=await Of0(Q.entityService,D,q,F[0].id);return{success:!0,data:j}}let L=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:K,...U!==void 0?{title:U}:{},...G!==void 0?{alt:G}:{},...D!==void 0?{targetEntityType:D}:{},...q!==void 0?{targetEntityId:q}:{}}}),_={imageEntityId:B,alreadyExisted:!1,attribution:J,jobId:L,status:"generating"};if(D&&q)_.coverSet=!1;return{success:!0,data:_}}}}zA();h0();cZ();var r18=W.object({photoId:W.string(),downloadLocation:W.url(),photographerName:W.string(),photographerUrl:W.url(),sourceUrl:W.url(),imageUrl:W.url(),title:W.string().optional(),alt:W.string().optional(),targetEntityType:W.string().optional(),targetEntityId:W.string().optional()});class qNA extends H8{deps;constructor(A,Q){super(A,{schema:r18,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,$){await this.reportProgress($,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress($,{progress:35,message:"Downloading stock photo"});let w=await this.deps.fetchImage(A.imageUrl),B=A.title??`Stock photo ${A.photoId}`,X=ZG.createImageEntity({dataUrl:w,title:B,alt:A.alt??B});await this.reportProgress($,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...X,metadata:{...X.metadata,sourceUrl:A.imageUrl}}}),Z={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(Z.coverSet=await Of0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!Z.coverSet)Z.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress($,{progress:100,message:"Stock photo selected"}),Z}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}cZ();var RAQ={name:"@brains/stock-photo",version:"0.2.0-alpha.195",description:"Stock photo search and selection \u2014 Unsplash provider",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var s18=W.object({provider:W.enum(["unsplash"]).default("unsplash"),apiKey:W.string().optional().describe("Stock photo provider API key")});class zNA extends d6{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",RAQ,A,s18);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=this.createProvider();return this.cachedTools=xAQ(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??Eq,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new qNA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??Eq}))}createProvider(){return new kf0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function VNA(A={},Q={}){return new zNA(A,Q)}zA();h0();zA();zA();h0();var vAQ=W.enum(["ai","foundation","work"]),CAQ=W.object({suffix:vAQ,title:W.string(),body:W.string(),linkLabel:W.string(),linkHref:W.string()}),X70=W.object({eyebrow:W.string(),headline:W.string(),cards:W.array(CAQ).min(1)}),JNA=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),a18=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),Y70=U6.extend({entityType:W.literal("ecosystem-section"),metadata:a18});class hAQ extends zQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Y70,frontmatterSchema:JNA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var FNA=new hAQ;h0();function t18(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function LNA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function Z70(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function ff0(A){let Q=t18(A),w=LNA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return X70.parse({eyebrow:LNA(Q,"Eyebrow"),headline:LNA(Q,"Headline"),cards:w.map((B)=>({suffix:Z70(B,"Suffix"),title:Z70(B,"Title"),body:Z70(B,"Body"),linkLabel:Z70(B,"Link Label"),linkHref:Z70(B,"Link Href")}))})}function EAQ(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,$)=>[`### Card ${$+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
10550
+ `)}function VAQ(A){try{return JAQ(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function JAQ(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var b18={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function ZNA(A={},Q={}){return new YNA(A,Q)}Uw();zA();h0();import{readFile as M18}from"fs/promises";import{join as k18}from"path";var FAQ={name:"@brains/rover-onboarding",version:"0.2.0-alpha.196",description:"Rover onboarding playbook bundle and activation plugin",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/playbooks":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var O18=W.object({enabled:W.boolean().default(!1)}).strict(),LAQ=[{id:"rover-onboarding",fileName:"rover-onboarding.md",starter:{id:"onboarding",trigger:"first-anchor-web-chat",playbookId:"rover-onboarding",once:!0,starterText:"Set up Rover",description:"Tune Rover's identity and anchor profile before using the knowledge loop.",starterPrompt:"Start playbook rover-onboarding."}},{id:"rover-first-knowledge-loop",fileName:"rover-first-knowledge-loop.md"}];class IAQ extends d6{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",FAQ,A,O18)}async onReady(A){if(!this.config.enabled)return;for(let Q of LAQ)await this.seedPlaybookIfMissing(A,Q);for(let Q of LAQ){if(!Q.starter)continue;await A.messaging.send({type:gS,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let w=await M18(k18(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:w}})}}function NAQ(A={}){return new IAQ(A)}zA();h0();h0();zA();var WNA=W.enum(["new","planned","in-progress","done","declined"]),HNA=W.enum(["low","medium","high","critical"]),f18=W.enum(["new","planned","in-progress","done","declined"]),x18=W.enum(["low","medium","high","critical"]),A70=W.object({title:W.string(),status:WNA,priority:HNA.default("medium"),requested:W.number().int().default(1),declinedReason:W.string().optional()}),R18=W.object({title:W.string(),status:WNA,priority:HNA,requested:W.number().int(),slug:W.string()}),v18=W.object({title:W.string(),status:f18,priority:x18,requested:W.number().int(),slug:W.string()}),Q70=U6.extend({entityType:W.literal("wish"),metadata:v18});h0();var KNA=W.object({}).catchall(W.unknown()).transform(()=>({}));zA();p2();class $70 extends zQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Q70,frontmatterSchema:A70})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,A70);return{frontmatter:A70.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),$=O1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:$}}}}var _AQ=new $70;p2();p2();async function PAQ(A,Q){let $=`${Q.title}: ${Q.description}`,B=(await A.search({query:$,options:{types:["wish"],limit:1}}))[0];if(B&&B.score>=A.similarityThreshold)return B.entity;let X=O1(Q.title);return A.getEntity({entityType:"wish",id:X})}class jf0{logger;context;adapter=new $70;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,$){let w=A.title??A.prompt??"Untitled wish",B=A.content??A.prompt??"",X=await PAQ({search:(K)=>this.context.entityService.search(K),getEntity:(K)=>this.context.entityService.getEntity(K),similarityThreshold:0.85},{title:w,description:B});if(X){let{frontmatter:K,description:U}=this.adapter.parseWishContent(X.content),G=K.requested+1,D=this.adapter.createWishContent({...K,requested:G},U);return await this.context.entityService.updateEntity({entity:{...X,content:D,metadata:{...X.metadata,requested:G}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:G}),{success:!0,entityId:X.id,existed:!0,requested:G}}let Y=O1(w),Z=A.options?.priority??"medium",H=this.adapter.createWishContent({title:w,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,metadata:{title:w,status:"new",priority:Z,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:w}),{success:!0,entityId:Y,existed:!1,requested:1}}}var bAQ={critical:0,high:1,medium:2,low:3};function jAQ(A){A.sort((Q,$)=>{let w=$.metadata.requested-Q.metadata.requested;if(w!==0)return w;return bAQ[Q.metadata.priority]-bAQ[$.metadata.priority]})}var MAQ={name:"@brains/wishlist",version:"0.2.0-alpha.196",description:"Wishlist plugin for tracking unfulfilled user requests",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var h18=W.object({items:W.array(W.object({name:W.string(),count:W.number()}))}),E18="wish";class kAQ extends c6{entityType=E18;schema=Q70;adapter=_AQ;constructor(A={}){super("wishlist",MAQ,A,KNA)}async interceptCreate(A,Q,$){let w=await new jf0(this.logger,$).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!w.success)return{kind:"handled",result:{success:!1,error:w.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...w.entityId?{entityId:w.entityId}:{},status:w.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",group:"knowledge",section:"secondary",priority:30,rendererName:"ListWidget",digestProvider:($)=>{let{items:w}=h18.parse($),B=w[0];return{digest:B?[{label:"Top wish",value:`${B.name} \xB7 \xD7${B.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let $=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return jAQ($),{items:$.map((w)=>({id:w.id,name:w.metadata.title,count:w.metadata.requested,priority:w.metadata.priority,status:w.metadata.status}))}}}}),{success:!0}});let Q=new jf0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:($)=>$})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function T18(A={}){return new kAQ(A)}var Mf0=T18;zA();zA();h0();var w70=W.object({title:W.string(),target:W.string()}),OAQ=W.object({title:W.string(),target:W.string(),slug:W.string().optional()}),B70=U6.extend({entityType:W.literal("prompt"),metadata:OAQ});zA();p2();class UNA extends zQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:B70,frontmatterSchema:w70})}toMarkdown(A){let Q=this.extractBody(A.content),$=this.parseFrontMatter(A.content,w70);return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,w70),$=O1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:$}}}}var GNA=new UNA;var fAQ={name:"@brains/prompt",version:"0.2.0-alpha.196",description:"Prompt entity type \u2014 AI prompts as editable markdown entities",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","bun-types":"^1.3.14",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var g18="prompt";class DNA extends c6{entityType=g18;schema=B70;adapter=GNA;constructor(){super("prompt",fAQ,{},bY)}getEntityTypeConfig(){return{embeddable:!1}}}function ny(){return new DNA}zA();h0();h0();class kf0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let $=new URL(`${this.baseUrl}/search/photos`);$.searchParams.set("query",A),$.searchParams.set("page",String(Q.page)),$.searchParams.set("per_page",String(Q.perPage));let w=await this.fetchFn($.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!w.ok)throw Error(`Unsplash API error: ${w.status} ${w.statusText}`);let B=m18.parse(await w.json());return{photos:B.results.map(u18),total:B.total,totalPages:B.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var S18=W.looseObject({id:W.string(),description:W.string().nullable(),alt_description:W.string().nullable(),urls:W.looseObject({raw:W.url(),full:W.url(),regular:W.url(),small:W.url(),thumb:W.url()}),links:W.looseObject({html:W.url(),download_location:W.url()}),user:W.looseObject({name:W.string(),links:W.looseObject({html:W.url()})}),width:W.number().int().nonnegative(),height:W.number().int().nonnegative()}),m18=W.looseObject({total:W.number().int().nonnegative(),total_pages:W.number().int().nonnegative(),results:W.array(S18)});function u18(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}}h0();async function Of0(A,Q,$,w){let B=await A.getEntity({entityType:Q,id:$});if(!B)return!1;return await A.updateEntity({entity:{...B,metadata:{...B.metadata,coverImageId:w}}}),!0}var c18={query:W.string().describe("Search terms for stock photos"),perPage:W.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:W.number().min(1).default(1).describe("Page number")},p18={photoId:W.string().describe("Photo ID from search results"),downloadLocation:W.url().describe("Download tracking URL (required by provider ToS)"),photographerName:W.string().describe("Photographer name for attribution"),photographerUrl:W.url().describe("Photographer profile URL for attribution"),sourceUrl:W.url().describe("Photo page URL on provider"),imageUrl:W.url().describe("Image URL to download"),title:W.string().optional().describe("Image entity title"),alt:W.string().optional().describe("Alt text for the image"),targetEntityType:W.string().optional().describe("Entity type to set cover image on"),targetEntityId:W.string().optional().describe("Entity ID to set cover image on")},l18=W.object({query:W.string(),perPage:W.number().min(1).max(30).default(10),page:W.number().min(1).default(1)}),i18=W.object({photoId:W.string(),downloadLocation:W.url(),photographerName:W.string(),photographerUrl:W.url(),sourceUrl:W.url(),imageUrl:W.url(),title:W.string().optional(),alt:W.string().optional(),targetEntityType:W.string().optional(),targetEntityId:W.string().optional()});function xAQ(A,Q){return[d18(A,Q),n18(A,Q)]}function d18(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:c18,visibility:"anchor",sideEffects:"none",handler:async($)=>{let w=l18.safeParse($);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(w.data.query,{page:w.data.page,perPage:w.data.perPage})}}catch(B){return{success:!1,error:B instanceof Error?B.message:"Search failed"}}}}}function n18(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:p18,visibility:"anchor",sideEffects:"external",handler:async($)=>{let w=i18.safeParse($);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:K,title:U,alt:G,targetEntityType:D,targetEntityId:q}=w.data,J={photographerName:Y,photographerUrl:Z,sourceUrl:H},F=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(F[0]){let j={imageEntityId:F[0].id,alreadyExisted:!0,attribution:J};if(D&&q)j.coverSet=await Of0(Q.entityService,D,q,F[0].id);return{success:!0,data:j}}let L=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:K,...U!==void 0?{title:U}:{},...G!==void 0?{alt:G}:{},...D!==void 0?{targetEntityType:D}:{},...q!==void 0?{targetEntityId:q}:{}}}),_={imageEntityId:B,alreadyExisted:!1,attribution:J,jobId:L,status:"generating"};if(D&&q)_.coverSet=!1;return{success:!0,data:_}}}}zA();h0();cZ();var r18=W.object({photoId:W.string(),downloadLocation:W.url(),photographerName:W.string(),photographerUrl:W.url(),sourceUrl:W.url(),imageUrl:W.url(),title:W.string().optional(),alt:W.string().optional(),targetEntityType:W.string().optional(),targetEntityId:W.string().optional()});class qNA extends H8{deps;constructor(A,Q){super(A,{schema:r18,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,$){await this.reportProgress($,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress($,{progress:35,message:"Downloading stock photo"});let w=await this.deps.fetchImage(A.imageUrl),B=A.title??`Stock photo ${A.photoId}`,X=ZG.createImageEntity({dataUrl:w,title:B,alt:A.alt??B});await this.reportProgress($,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...X,metadata:{...X.metadata,sourceUrl:A.imageUrl}}}),Z={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(Z.coverSet=await Of0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!Z.coverSet)Z.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress($,{progress:100,message:"Stock photo selected"}),Z}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}cZ();var RAQ={name:"@brains/stock-photo",version:"0.2.0-alpha.196",description:"Stock photo search and selection \u2014 Unsplash provider",dependencies:{"@brains/image":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var s18=W.object({provider:W.enum(["unsplash"]).default("unsplash"),apiKey:W.string().optional().describe("Stock photo provider API key")});class zNA extends d6{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",RAQ,A,s18);this.deps=Q}async getTools(){if(!this.config.apiKey)return[];if(this.cachedTools)return this.cachedTools;let A=this.getContext(),Q=this.createProvider();return this.cachedTools=xAQ(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??Eq,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new qNA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??Eq}))}createProvider(){return new kf0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function VNA(A={},Q={}){return new zNA(A,Q)}zA();h0();zA();zA();h0();var vAQ=W.enum(["ai","foundation","work"]),CAQ=W.object({suffix:vAQ,title:W.string(),body:W.string(),linkLabel:W.string(),linkHref:W.string()}),X70=W.object({eyebrow:W.string(),headline:W.string(),cards:W.array(CAQ).min(1)}),JNA=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),a18=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),Y70=U6.extend({entityType:W.literal("ecosystem-section"),metadata:a18});class hAQ extends zQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Y70,frontmatterSchema:JNA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var FNA=new hAQ;h0();function t18(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function LNA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function Z70(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function ff0(A){let Q=t18(A),w=LNA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return X70.parse({eyebrow:LNA(Q,"Eyebrow"),headline:LNA(Q,"Headline"),cards:w.map((B)=>({suffix:Z70(B,"Suffix"),title:Z70(B,"Title"),body:Z70(B,"Body"),linkLabel:Z70(B,"Link Label"),linkHref:Z70(B,"Link Href")}))})}function EAQ(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,$)=>[`### Card ${$+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
10551
10551
  `)}var e18=W.looseObject({query:W.object({id:W.string().optional()}).optional()});class xf0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,$){let B=e18.parse(A??{}).query?.id??"rizom-ecosystem",X=await $.entityService.getEntity({entityType:"ecosystem-section",id:B});if(!X)throw Error(`Ecosystem section not found: ${B}`);return Q.parse(ff0(X.content))}}import{jsxDEV as $28}from"preact/jsx-dev-runtime";var A28="px-6 md:px-10 xl:px-20",Q28=`${A28} relative z-[1]`,TAQ=({id:A,className:Q,children:$})=>$28("section",{id:A,className:wQ(Q28,Q),children:$},void 0,!1,void 0,this);import{jsxDEV as Rf0}from"preact/jsx-dev-runtime";var w28=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),yAQ=({name:A="rizom",brandSuffix:Q,className:$,dotClassName:w,suffixClassName:B})=>{let X=w28.get(Q);return Rf0("span",{className:wQ("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",$),children:[Rf0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),Rf0("span",{className:wQ(X??"text-accent",w),children:"."},void 0,!1,void 0,this),Rf0("span",{className:wQ("italic font-normal text-theme-muted",B),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Fragment as INA}from"preact";import{jsxDEV as W70}from"preact/jsx-dev-runtime";var B28=/(\*[^*]+\*)/;function gAQ(A,Q){let $=A.split(`
10552
- `);return W70(INA,{children:$.map((w,B)=>W70(INA,{children:[B>0&&W70("br",{},void 0,!1,void 0,this),w.split(B28).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return W70("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return W70(INA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as $U,Fragment as z28}from"preact/jsx-dev-runtime";var X28="italic text-accent font-normal",Y28="You are here",Z28={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},W28={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},H28={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},K28="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",U28="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",G28="font-label text-[10.5px] uppercase tracking-[0.22em] text-theme-muted self-start mt-[18px] pb-1 border-b border-white/10 transition-colors hover:text-theme",D28="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",q28=({card:A})=>{let Q=A.linkLabel===Y28,$=A.linkHref.trim().length===0,w=$U(z28,{children:[$U(yAQ,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),$U("span",{className:`${K28} ${Z28[A.suffix]}`,children:A.title},void 0,!1,void 0,this),$U("p",{className:U28,children:A.body},void 0,!1,void 0,this),Q?$U("span",{className:D28,children:A.linkLabel},void 0,!1,void 0,this):$U("span",{className:G28,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B=`flex flex-col gap-[14px] border-t pt-7 ${Q?W28[A.suffix]:"border-white/10"}`;return Q||$?$U("div",{className:B,children:w},void 0,!1,void 0,this):$U("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${H28[A.suffix]}`,children:w},void 0,!1,void 0,this)},SAQ=({eyebrow:A,headline:Q,cards:$})=>$U(TAQ,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[$U("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[$U("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),$U("h2",{className:"mt-5 font-display text-[clamp(34px,4.4vw,60px)] font-[380] leading-[1.04] tracking-[-0.02em] text-heading [font-variation-settings:'opsz'_96]",children:gAQ(Q,X28)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$U("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:$.map((w)=>$U(q28,{card:w},w.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);zA();var NNA=G2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:X70,formatter:{parse:ff0,format:EAQ},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:SAQ}});var mAQ={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.195",description:"Entity-backed Rizom ecosystem section",dependencies:{"@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var J28=W.object({}).catchall(W.unknown()).transform(()=>({})),F28="ecosystem-section";class _NA extends c6{entityType=F28;schema=Y70;adapter=FNA;constructor(A={}){super("rizom-ecosystem",mAQ,A,J28)}getTemplates(){return{ecosystem:NNA}}getDataSources(){return[new xf0]}}function ry(A={}){return new _NA(A)}zA();zA();p2();h0();e9();h0();zA();var jw="agent",uAQ="agent-discovery";var cAQ="agent-network",pAQ="AgentNetworkWidget",lAQ="agent-proximity",iAQ="AgentProximityWidget",H70="agent-discovery:entities",vf0="agent-discovery:proximity-map",PNA="proximity-map",bNA="agent-list",jNA="agent-detail",m9="skill",dAQ="skill",Cf0="skill-derivation",nAQ="skill:project",rAQ="skill-derivation",oAQ="skill:skill-derivation",sAQ="skills";var hf0=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),Lx=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),aAQ=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),L28=W.enum(["professional","team","collective"]),aV=W.object({name:W.string(),kind:L28,organization:W.string().optional(),brainName:W.string().describe("Name of the brain instance"),url:W.string().url().describe("Brain endpoint URL"),did:W.string().optional().describe("Decentralized identifier (public)"),repoDid:W.string().optional().describe("ATProto repo DID"),brainDid:W.string().optional().describe("ATProto brain DID"),anchorDid:W.string().optional().describe("ATProto anchor DID"),cardUri:W.string().optional().describe("ATProto brain card URI"),cardCid:W.string().optional().describe("ATProto brain card CID"),a2aEndpoint:W.string().url().optional().describe("A2A endpoint URL"),status:Lx,discoveredAt:W.string().datetime().describe("When this agent was first discovered"),introducedBy:W.array(W.string()).optional().describe("Agent ids of the peers whose directories reported this agent"),hops:W.number().int().min(2).optional().describe("Discovery order: 2 = sighted through a first-order peer")}),tAQ=W.object({name:W.string(),url:W.string().url(),status:Lx,discoveredAt:W.string().datetime().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional()}),I28=W.object({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.string().url(),did:W.string().optional(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional(),status:aAQ,discoveredAt:W.string().datetime(),introducedBy:W.array(W.string()).optional(),hops:W.number().int().min(2).optional()}),N28=W.object({name:W.string(),url:W.string().url(),status:aAQ,discoveredAt:W.string().datetime().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional()}),K70=MB.extend({entityType:W.literal(jw),metadata:tAQ}),_28=U6.extend({entityType:W.literal(jw),metadata:N28}),U70=_28.extend({frontmatter:I28,about:W.string(),skills:W.array(hf0),notes:W.string()}),P28=U70.extend({url:W.string().optional(),typeLabel:W.string().optional()}),b28=U70.extend({url:W.string(),typeLabel:W.string()});h0();var j28=W.array(hf0);function eAQ(A){let Q=j28.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
10552
+ `);return W70(INA,{children:$.map((w,B)=>W70(INA,{children:[B>0&&W70("br",{},void 0,!1,void 0,this),w.split(B28).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return W70("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return W70(INA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as $U,Fragment as z28}from"preact/jsx-dev-runtime";var X28="italic text-accent font-normal",Y28="You are here",Z28={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},W28={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},H28={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},K28="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",U28="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",G28="font-label text-[10.5px] uppercase tracking-[0.22em] text-theme-muted self-start mt-[18px] pb-1 border-b border-white/10 transition-colors hover:text-theme",D28="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",q28=({card:A})=>{let Q=A.linkLabel===Y28,$=A.linkHref.trim().length===0,w=$U(z28,{children:[$U(yAQ,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),$U("span",{className:`${K28} ${Z28[A.suffix]}`,children:A.title},void 0,!1,void 0,this),$U("p",{className:U28,children:A.body},void 0,!1,void 0,this),Q?$U("span",{className:D28,children:A.linkLabel},void 0,!1,void 0,this):$U("span",{className:G28,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B=`flex flex-col gap-[14px] border-t pt-7 ${Q?W28[A.suffix]:"border-white/10"}`;return Q||$?$U("div",{className:B,children:w},void 0,!1,void 0,this):$U("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${H28[A.suffix]}`,children:w},void 0,!1,void 0,this)},SAQ=({eyebrow:A,headline:Q,cards:$})=>$U(TAQ,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[$U("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[$U("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),$U("h2",{className:"mt-5 font-display text-[clamp(34px,4.4vw,60px)] font-[380] leading-[1.04] tracking-[-0.02em] text-heading [font-variation-settings:'opsz'_96]",children:gAQ(Q,X28)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$U("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:$.map((w)=>$U(q28,{card:w},w.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);zA();var NNA=G2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:X70,formatter:{parse:ff0,format:EAQ},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:SAQ}});var mAQ={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.196",description:"Entity-backed Rizom ecosystem section",dependencies:{"@brains/plugins":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var J28=W.object({}).catchall(W.unknown()).transform(()=>({})),F28="ecosystem-section";class _NA extends c6{entityType=F28;schema=Y70;adapter=FNA;constructor(A={}){super("rizom-ecosystem",mAQ,A,J28)}getTemplates(){return{ecosystem:NNA}}getDataSources(){return[new xf0]}}function ry(A={}){return new _NA(A)}zA();zA();p2();h0();e9();h0();zA();var jw="agent",uAQ="agent-discovery";var cAQ="agent-network",pAQ="AgentNetworkWidget",lAQ="agent-proximity",iAQ="AgentProximityWidget",H70="agent-discovery:entities",vf0="agent-discovery:proximity-map",PNA="proximity-map",bNA="agent-list",jNA="agent-detail",m9="skill",dAQ="skill",Cf0="skill-derivation",nAQ="skill:project",rAQ="skill-derivation",oAQ="skill:skill-derivation",sAQ="skills";var hf0=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),Lx=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),aAQ=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),L28=W.enum(["professional","team","collective"]),aV=W.object({name:W.string(),kind:L28,organization:W.string().optional(),brainName:W.string().describe("Name of the brain instance"),url:W.string().url().describe("Brain endpoint URL"),did:W.string().optional().describe("Decentralized identifier (public)"),repoDid:W.string().optional().describe("ATProto repo DID"),brainDid:W.string().optional().describe("ATProto brain DID"),anchorDid:W.string().optional().describe("ATProto anchor DID"),cardUri:W.string().optional().describe("ATProto brain card URI"),cardCid:W.string().optional().describe("ATProto brain card CID"),a2aEndpoint:W.string().url().optional().describe("A2A endpoint URL"),status:Lx,discoveredAt:W.string().datetime().describe("When this agent was first discovered"),introducedBy:W.array(W.string()).optional().describe("Agent ids of the peers whose directories reported this agent"),hops:W.number().int().min(2).optional().describe("Discovery order: 2 = sighted through a first-order peer")}),tAQ=W.object({name:W.string(),url:W.string().url(),status:Lx,discoveredAt:W.string().datetime().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional()}),I28=W.object({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.string().url(),did:W.string().optional(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional(),status:aAQ,discoveredAt:W.string().datetime(),introducedBy:W.array(W.string()).optional(),hops:W.number().int().min(2).optional()}),N28=W.object({name:W.string(),url:W.string().url(),status:aAQ,discoveredAt:W.string().datetime().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.string().url().optional()}),K70=MB.extend({entityType:W.literal(jw),metadata:tAQ}),_28=U6.extend({entityType:W.literal(jw),metadata:N28}),U70=_28.extend({frontmatter:I28,about:W.string(),skills:W.array(hf0),notes:W.string()}),P28=U70.extend({url:W.string().optional(),typeLabel:W.string().optional()}),b28=U70.extend({url:W.string(),typeLabel:W.string()});h0();var j28=W.array(hf0);function eAQ(A){let Q=j28.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
10553
10553
  `)}function A1Q(A){if(!A.trim())return[];let Q=[];for(let $ of A.split(`
10554
10554
  `)){let w=$.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!w)continue;let B=w[1]??"",X=w[2]??"",Y=w[3],Z=Y?Y.split(",").map((H)=>H.trim()).filter(Boolean):[];Q.push({name:B,description:X,tags:Z})}return Q}var M28=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),k28=W.object({about:W.string(),skills:W.array(M28),notes:W.string()}),Q1Q=new n$(k28,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:eAQ,parser:A1Q},{key:"notes",label:"Notes",type:"string"}]});class L4 extends zQ{constructor(){super({entityType:jw,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:K70,frontmatterSchema:aV,publishedStatuses:["approved"]})}fromMarkdown(A){let Q=this.parseFrontMatter(A,aV),$=rS(Q.url);return{content:A,entityType:jw,metadata:{name:Q.name,url:Q.url,status:Q.status,discoveredAt:Q.discoveredAt,slug:$,...Q.repoDid&&{repoDid:Q.repoDid},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},...Q.cardUri&&{cardUri:Q.cardUri},...Q.cardCid&&{cardCid:Q.cardCid},...Q.a2aEndpoint&&{a2aEndpoint:Q.a2aEndpoint}}}}createAgentContent(A){let Q={name:A.name,kind:A.kind,...A.organization&&{organization:A.organization},brainName:A.brainName,url:A.url,...A.did&&{did:A.did},...A.repoDid&&{repoDid:A.repoDid},...A.brainDid&&{brainDid:A.brainDid},...A.anchorDid&&{anchorDid:A.anchorDid},...A.cardUri&&{cardUri:A.cardUri},...A.cardCid&&{cardCid:A.cardCid},...A.a2aEndpoint&&{a2aEndpoint:A.a2aEndpoint},status:Lx.parse(A.status),discoveredAt:A.discoveredAt,...A.introducedBy?.length&&{introducedBy:A.introducedBy},...A.hops!==void 0&&{hops:A.hops}},$=Q1Q.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown($,Q)}parseAgentContent(A){let Q=this.extractBody(A);if(!Q.trim())return{about:"",skills:[],notes:""};try{let $=Q1Q.parse(Q);return{about:$.about,skills:$.skills,notes:$.notes}}catch{return{about:"",skills:[],notes:""}}}parseEntity(A){return{frontmatter:this.parseFrontMatter(A.content,aV),body:this.parseAgentContent(A.content)}}}zA();h0();var O28=new L4,$1Q=W.enum(["discovered","approved","archived"]),f28=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),status:$1Q.optional()}),x28=W.looseObject({entityType:W.string().optional(),query:f28.optional()});function R28(A){let Q=MQ(A.content,aV),$=O28.parseAgentContent(A.content);return U70.parse({...A,frontmatter:Q.metadata,about:$.about,skills:$.skills,notes:$.notes})}class Ef0 extends n7{id=H70;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:jw,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return R28(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=x28.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,$){let w=$1Q.safeParse($.status);return{agents:A,pagination:Q,baseUrl:$.baseUrl,selectedStatus:w.success?w.data:"all"}}async fetch(A,Q,$){let{query:w}=this.parseQuery(A);if(w.id)return super.fetch(A,Q,$);let{items:B,pagination:X}=await this.fetchList(w,$.entityService,w.status?{filter:{metadata:{status:w.status}}}:void 0);return Q.parse(this.buildListResult(B,X,w))}}var v28=180*(3-Math.sqrt(5));function MNA(A){return Math.max(0,Math.min(1,A))}function kNA(A,Q){let[$,w]=A;if(Math.hypot($,w)<=0.000000000001)return Q*v28%360;return(Math.atan2(w,$)*180/Math.PI%360+360)%360}function w1Q(A,Q){let $=new Map(A.map((Y)=>[Y.id,Y])),w=new Map(A.map((Y)=>[Y.id,new Set]));for(let Y of Q){if(Y.source.entityType!=="agent"||Y.target.entityType!=="agent"||Y.source.entityId===Y.target.entityId||!$.has(Y.source.entityId)||!$.has(Y.target.entityId))continue;w.get(Y.source.entityId)?.add(Y.target.entityId),w.get(Y.target.entityId)?.add(Y.source.entityId)}let B=new Set,X=[];for(let Y of Array.from($.keys()).sort()){if(B.has(Y))continue;let Z=[],H=[Y];B.add(Y);while(H.length>0){let K=H.pop();if(!K)continue;Z.push(K);for(let U of Array.from(w.get(K)??[]).sort()){if(B.has(U))continue;B.add(U),H.push(U)}}if(Z.length>=2)X.push(Z.sort())}return X.map((Y)=>({label:C28(Y,$),memberIds:Y,links:Y.flatMap((Z)=>Array.from(w.get(Z)??[]).filter((H)=>Z.localeCompare(H)<0).sort().map((H)=>({sourceId:Z,targetId:H})))})).sort((Y,Z)=>{let H=Y.memberIds.some((G)=>($.get(G)?.tags.length??0)>0),K=Z.memberIds.some((G)=>($.get(G)?.tags.length??0)>0);if(H!==K)return H?-1:1;let U=Y.label.localeCompare(Z.label);return U!==0?U:(Y.memberIds[0]??"").localeCompare(Z.memberIds[0]??"")})}function C28(A,Q){let $=new Map;for(let B of A){let X=Q.get(B);for(let Y of new Set(X?.tags??[]))$.set(Y,($.get(Y)??0)+1)}let w=Array.from($.entries()).sort((B,X)=>{let Y=X[1]-B[1];return Y!==0?Y:B[0].localeCompare(X[0])})[0]?.[0];return w?`${w} \xB7 ${A.length}`:`unknown \xB7 ${A.length}`}h0();var h28=aV.shape.kind,E28=W.object({kind:W.enum(["identity","centroid"])}),T28=W.object({id:W.string(),name:W.string(),kind:h28,status:Lx,tags:W.array(W.string()),distance:W.number().min(0).max(1),bearing:W.number().min(0).lt(360)}),y28=W.object({sourceId:W.string(),targetId:W.string()}),g28=W.object({label:W.string(),memberIds:W.array(W.string()).min(2),links:W.array(y28).min(1)}),S28=W.object({min:W.number().min(0),max:W.number().min(0)}),B1Q=W.object({kicker:W.string().optional(),headingLead:W.string().optional(),headingAccent:W.string().optional(),lede:W.string().optional(),ctaLabel:W.string().optional(),ctaHref:W.string().optional()}),m28=W.object({id:W.string(),name:W.string(),viaIds:W.array(W.string()).min(1),tags:W.array(W.string()),distance:W.number().min(0).max(1),bearing:W.number().min(0).lt(360)}),hb=W.object({center:E28,nodes:W.array(T28),clusters:W.array(g28),sightings:W.array(m28),distanceRange:S28,pendingCount:W.number().int().min(0),kicker:W.string().optional(),headingLead:W.string().optional(),headingAccent:W.string().optional(),lede:W.string().optional(),ctaLabel:W.string().optional(),ctaHref:W.string().optional()});var u28=new L4;function X1Q(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function DI(A){let Q=new Set,$=[];for(let w of A){let B=X1Q(w);if(!B||Q.has(B))continue;Q.add(B),$.push(B)}return $}function c28(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function Y1Q(A,Q={}){let $=Q.minCount??1,w=Q.topN??12,B=Q.visibilityScope??"public",X=new Map,[Y,Z]=await Promise.all([A.entityService.listEntities({entityType:m9,options:{filter:{visibilityScope:B}}}),A.entityService.listEntities({entityType:jw,options:{filter:{visibilityScope:B}}})]),H=(K)=>{for(let U of DI(K))X.set(U,(X.get(U)??0)+1)};for(let K of Y)H(K.metadata.tags);for(let K of Z){let U=u28.parseAgentContent(K.content);H(U.skills.flatMap((G)=>G.tags))}return Array.from(X.entries()).map(([K,U])=>({tag:K,count:U})).filter((K)=>K.count>=$).sort(c28).slice(0,w)}function Z1Q(A){if(A.length===0)return"";return["Current agent-directory tag vocabulary (reuse existing tags where they fit; propose new only when nothing does):",...A.map(({tag:Q,count:$})=>`- ${Q} (${$})`)].join(`
10555
10555
  `)}var p28={entityId:"brain-character",entityType:"brain-character"},l28=0.25,i28=0.5,d28=new L4;function W1Q(A){return A.status==="discovered"&&(A.introducedBy?.length??0)>0}async function Tf0(A){let[Q,$]=await Promise.all([A.entityService.listEntities({entityType:jw}),A.semantic.project({types:[jw],origin:p28,maxNeighborDistance:l28})]),w=new Map($.points.map((D)=>[D.entityId,D])),B=Q.slice().sort((D,q)=>D.id.localeCompare(q.id)).map((D)=>({agent:D,...d28.parseEntity(D)})),X=B.filter((D)=>!W1Q(D.frontmatter)),Y=B.filter((D)=>W1Q(D.frontmatter)),Z=[];for(let{agent:D,frontmatter:q,body:J}of X){let F=w.get(D.id);if(!F)continue;Z.push({id:D.id,name:q.name,kind:q.kind,status:q.status,tags:H1Q(J.skills),distance:MNA(F.distanceToOrigin),bearing:kNA(F.coordinates,Z.length)})}let H=Z.filter((D)=>D.status!=="archived"),K=new Set(H.map((D)=>D.id)),U=Math.max(i28,...H.map((D)=>D.distance)),G=[];for(let{agent:D,frontmatter:q,body:J}of Y){let F=w.get(D.id);if(!F)continue;let L=MNA(F.distanceToOrigin);if(L>U)continue;let _=(q.introducedBy??[]).filter((j)=>K.has(j));if(_.length===0)continue;G.push({id:D.id,name:q.name,viaIds:_,tags:H1Q(J.skills),distance:L,bearing:kNA(F.coordinates,G.length)})}return hb.parse({center:{kind:$.origin.kind==="entity"?"identity":"centroid"},nodes:Z,clusters:w1Q(H,$.neighbors),sightings:G,distanceRange:$.distanceRange,pendingCount:Math.max(0,X.length-Z.length)})}function H1Q(A){return DI(A.flatMap((Q)=>Q.tags))}class yf0{id=vf0;name="Agent Proximity Map DataSource";description="Builds a public semantic proximity map for saved agents";async fetch(A,Q,$){let w=await Tf0({entityService:$.entityService,semantic:{project:(B)=>$.entityService.projectSemanticSpace(B)}});return Q.parse(w)}}zA();h0();Uw();zA();async function Fo(A,Q,$){let B=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let X=await Q(B,$?{signal:$}:void 0);if(!X.ok)return null;let Y=await X.json();return aA0(Y)}catch{if($?.aborted)throw $.reason;return null}}function Eb(A){let Q=A.trim();if(Q.startsWith("http://")||Q.startsWith("https://"))try{return new URL(Q).hostname}catch{return Q}let $=Q.match(/https?:\/\/[^\s]+?(?=[.,;:!?)]*(?:\s|$))/);if($)try{return new URL($[0]).hostname}catch{return $[0]}if(/^[^\s]+\.[^\s]+$/.test(Q))return Q;return""}p2();var n28=new L4;function Lo(A,Q={}){let $=A.anchor?.name??A.brainName,w=A.anchor?.kind??"professional",B=[];if(A.anchor?.description)B.push(A.anchor.description);if(A.description)B.push(A.description);let X=Q.status??"discovered",Y=new Date().toISOString();return{content:n28.createAgentContent({name:$,kind:w,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:X,discoveredAt:Y,...Q.provenance&&{introducedBy:Q.provenance.introducedBy,hops:Q.provenance.hops},about:B.join(`
@@ -11570,7 +11570,7 @@ ${A.guidance}`:B}}function GAQ(A){return{...A,evidence:A.evidence.map((Q)=>({...
11570
11570
  /* the shimmer delay is inlined per node, so the override needs force */
11571
11571
  .agent-proximity-site .proximity-agent { animation: none !important; }
11572
11572
  }
11573
- `,Po={kicker:"Agent network",headingLead:"The rhizome grows",headingAccent:"beneath this brain",lede:"Every agent this brain has met, mapped by how close its work runs to ours \u2014 distance measured in meaning, not geography. Threads thicken where practices touch; where several lights gather, a constellation forms.",ctaLabel:"Meet the agents",ctaHref:"/agents"};function yNA(A){let Q=A.nodes.filter((K)=>K.status!=="archived").length,$=A.nodes.length-Q,w=A.kicker??Po.kicker,B=A.headingLead??Po.headingLead,X=A.headingAccent??Po.headingAccent,Y=A.lede??Po.lede,Z=A.ctaLabel??Po.ctaLabel,H=A.ctaHref??Po.ctaHref;return Zw("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[Zw("style",{children:EQ8},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__grid",children:[Zw("div",{class:"agent-proximity-site__copy",children:[Zw("p",{class:"agent-proximity-site__kicker",children:w},void 0,!1,void 0,this),Zw("h2",{class:"agent-proximity-site__heading",children:[B," ",Zw("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:$},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"archived traces"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Zw("a",{class:"agent-proximity-site__cta",href:H,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&Zw("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&Zw("p",{class:"agent-proximity-site__note",children:"Identity not indexed yet \u2014 using network centroid"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{class:"agent-proximity-site__map",children:Zw(uf0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[Zw("span",{children:[Zw("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\xB7"},void 0,!1,void 0,this)," archived trace"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var TQ8=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),yQ8=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),gQ8=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),gNA=W.enum(["discovered","approved","archived"]),SQ8=W.enum(["professional","team","collective"]),mQ8=W.object({name:W.string(),kind:SQ8,organization:W.string().optional(),brainName:W.string(),url:W.url(),did:W.string().optional(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.url().optional(),status:gNA,discoveredAt:W.string()}),uQ8=W.object({name:W.string(),url:W.url(),status:gNA,discoveredAt:W.string().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.url().optional()}),pf0=W.object({id:W.string(),entityType:W.literal(jw),content:W.string(),created:W.string(),updated:W.string(),visibility:TQ8,metadata:uQ8,contentHash:W.string(),frontmatter:mQ8,about:W.string(),skills:W.array(gQ8),notes:W.string(),url:W.string().optional(),typeLabel:W.string().optional()}),cQ8=W.object({agents:W.array(pf0),pageTitle:W.string().optional(),pagination:yQ8.nullable(),baseUrl:W.string().optional(),selectedStatus:W.union([W.literal("all"),gNA])}),R1Q="/scripts/agent-proximity-map.js",pQ8=new n$(B1Q,{title:"Network",mappings:[{key:"kicker",label:"Kicker",type:"string"},{key:"headingLead",label:"Heading Lead",type:"string"},{key:"headingAccent",label:"Heading Accent",type:"string"},{key:"lede",label:"Lede",type:"string"},{key:"ctaLabel",label:"Cta Label",type:"string"},{key:"ctaHref",label:"Cta Href",type:"string"}]});function v1Q(){return{[PNA]:G2({name:PNA,description:"Semantic agent proximity map site section",schema:hb,dataSourceId:vf0,overlayFormatter:pQ8,requiredPermission:"public",runtimeScripts:[{src:R1Q,defer:!0}],staticAssets:{[R1Q]:Io},layout:{component:yNA}}),[bNA]:G2({name:bNA,description:"Agent directory list page template",schema:cQ8,dataSourceId:H70,requiredPermission:"public",layout:{component:O1Q}}),[jNA]:G2({name:jNA,description:"Individual agent profile template",schema:W.object({agent:pf0,prevAgent:pf0.nullable(),nextAgent:pf0.nullable()}),dataSourceId:H70,requiredPermission:"public",layout:{component:x1Q}})}}var bo={name:"@brains/agent-discovery",version:"0.2.0-alpha.195",description:"Agent discovery \u2014 brain+anchor contacts and skills",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/auth-service":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/dashboard":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var iQ8=new L4;class SNA extends c6{entityType=jw;schema=K70;adapter=iQ8;constructor(){super(uAQ,bo,{},bY)}createGenerationHandler(A){return new ONA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return v1Q()}getDataSources(){return[new Ef0(this.logger.child("AgentDataSource")),new yf0]}async onRegister(A){_1Q(A),I1Q(A,this.id)}async getInstructions(){return P1Q()}}function mNA(){return new SNA}zA();EZ();h0();c4();h0();var C1Q=W.object({source:W.object({kind:W.literal("url"),url:W.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:W.boolean().optional(),confirmationToken:W.string().optional()}),dQ8=new L4;function nQ8(A){let Q=Eb(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function rQ8(A,Q){return(Eb(Q)||A).toLowerCase()}async function oQ8(A){let{context:Q,entityId:$,card:w}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:jw,id:$}),Y=Lo(w,{status:"approved"}),H={...dQ8.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:w.url};if(X){let U={...X,content:Y.content,metadata:H,updated:B};return await Q.entityService.updateEntity({entity:U}),{entity:U,created:!1}}let K={id:$,entityType:jw,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function h1Q(A,Q=globalThis.fetch){let w=new eU;return{name:"agent_connect",description:"Verify and connect a remote A2A agent by fetching its Agent Card from /.well-known/agent-card.json, then save the verified contact in the local agent directory as approved for future outbound calls. Never use this tool for a request to approve or archive an existing saved contact; update that contact's status with system_update instead. This adds a directory contact; it does not message the remote agent or grant it inbound trusted access. Requires confirmation before verification and persistence. Call this tool without confirmed on the initial request; the tool returns confirmation args for the user to approve.",inputSchema:C1Q.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=C1Q.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((U)=>`${U.path.join(".")}: ${U.message}`).join(", ")}`};let Z=Y.data,H=nQ8(Z.source.url);if(!H)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(jw,"create",X)}catch(U){return{success:!1,error:U instanceof Error?U.message:String(U)}}if(Z.confirmed){let U=Z.confirmationToken,G=w.validate(U,Z);if(G.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await Fo(H.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=rQ8(H.domain,D.url),{entity:J,created:F}=await oQ8({context:A,entityId:q,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:J.metadata.status,entityId:J.id,connected:!0,created:F,a2aEndpoint:D.url,skills:D.skills.map((L)=>({name:L.name,description:L.description,tags:L.tags}))}}}let K=w.create((U)=>({source:Z.source,confirmed:!0,confirmationToken:U}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${H.domain}?`,preview:`This will fetch and validate ${H.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:K}}}}h0();var E1Q=W.object({}),sQ8=W.object({agents:W.array(W.object({name:W.string(),url:W.string()}))}),uNA=new L4;async function aQ8(A,Q,$){let w=`https://${A}/.well-known/agent-directory.json`;try{let B=await Q(w,$?{signal:$}:void 0);if(!B.ok)return null;let X=sQ8.safeParse(await B.json());return X.success?X.data:null}catch{if($?.aborted)throw $.reason;return null}}async function cNA(A,Q=globalThis.fetch,$){let w=await A.entityService.listEntities({entityType:jw}),B=w.filter((L)=>L.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let L of B){$?.throwIfAborted();let _=await aQ8(L.id,Q,$);if(!_){Z+=1;continue}for(let j of _.agents){let b=Eb(j.url).toLowerCase();if(!b||b===X||b===L.id)continue;let f=Y.get(b)??new Set;f.add(L.id),Y.set(b,f)}}let H=new Map(w.map((L)=>[L.id,L])),K=new Date().toISOString(),U=[],G=new Set,D=0,q=0,J=0,F=0;for(let[L,_]of Y){$?.throwIfAborted();let j=H.get(L);if(j){let{frontmatter:R,body:O}=uNA.parseEntity(j),S=R.introducedBy??[];if(R.status!=="discovered"||S.length===0){J+=1;continue}let u=[...S,...[..._].filter((i)=>!S.includes(i))];if(u.length===S.length)continue;await A.entityService.updateEntity({entity:{...j,content:uNA.createAgentContent({...R,introducedBy:u,about:O.about,skills:O.skills,notes:O.notes}),updated:K}}),q+=1;continue}let b=await Fo(L,Q,$);if(!b){F+=1;continue}let f=Lo(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),v=uNA.fromMarkdown(f.content);await A.entityService.createEntity({entity:{id:L,entityType:jw,content:f.content,metadata:{...v.metadata,...f.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(L);for(let R of _)G.add(R)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:q,alreadyKnown:J,unverified:F,createdDomains:U,introducingPeers:[...G],observedAt:K}}function T1Q(A,Q=globalThis.fetch){return{name:"agent_scan_directories",description:"Walk each approved agent's public directory at /.well-known/agent-directory.json and record second-order sightings: agents your peers list that you are not connected to. A sighting is saved as a discovered agent with provenance (which peers introduced it, hop count) and data from its own verified Agent Card. Re-scanning is idempotent: connected agents are skipped and repeat sightings only merge new introducers. Never approves anything; promotion stays with agent_connect.",inputSchema:E1Q.shape,visibility:"trusted",sideEffects:"external",handler:async($,w)=>{let B=E1Q.safeParse($);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(jw,"create",w)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await cNA(A,Q,w.signal);return{success:!0,data:{peersScanned:X.peersScanned,unreachablePeers:X.unreachablePeers,created:X.created,updated:X.updated,alreadyKnown:X.alreadyKnown,unverified:X.unverified}}}}}c4();h0();var tQ8=W.enum(["public","trusted"]),y1Q=W.object({agent:W.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:tQ8.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),keyFingerprint:W.string().optional()}),eQ8=W.object({keys:W.array(W.unknown())}),A68=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),kid:W.string().optional(),alg:W.literal("EdDSA").optional()}).passthrough();function g1Q(A){return(Eb(A)||A.trim()).toLowerCase()}async function Q68(A,Q){let $=g1Q(Q),w=await A.entityService.getEntity({entityType:jw,id:$});if(!w)return null;let B=g1Q(w.metadata.a2aEndpoint??w.metadata.url);if(!B)return null;return{domain:B}}async function $68(A,Q){try{let $=await Q(`https://${A}/.well-known/jwks.json`);if(!$.ok)return null;let w=eQ8.safeParse(await $.json());if(!w.success)return null;let B=w.data.keys.map((X)=>A68.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return bUA(B.data)}catch{return null}}function S1Q(A,Q=globalThis.fetch){let w=new eU;return{name:"agent_set_trust_level",description:"Grant or revoke inbound A2A trust for a saved contact; this is the only tool for inbound trust changes. To revoke, call directly with level public\u2014no key fingerprint or preliminary lookup is needed. To grant, use level trusted; the tool resolves and pins the peer key. This does not add or remove directory contacts or change outbound calling. Requires confirmation.",inputSchema:y1Q.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=y1Q.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=xY();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await Q68(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=X.data;if(H.confirmed){let D=w.validate(H.confirmationToken,H);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(H.level==="trusted"){if(!H.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let K=H.level==="trusted"?await $68(Z.domain,Q):void 0;if(H.level==="trusted"&&!K)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let U=w.create((D)=>({agent:Z.domain,level:H.level,confirmed:!0,confirmationToken:D,...K?{keyFingerprint:K}:{}})),G=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:G?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:G?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${K}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${Z.domain}. The directory contact remains saved for outbound calls.`,args:U}}}}var lf0=W.object({notifyOnNewAgents:W.boolean().default(!1).describe("Notify when directory scans discover new agents")}).strict();class pNA extends d6{fetchFn;constructor(A,Q={}){super("agent",bo,Q,lf0);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",deliverAlerts:this.config.notifyOnNewAgents,run:async({signal:Q})=>{let $=await cNA(A,this.fetchFn,Q);if($.created===0||!this.config.notifyOnNewAgents)return{};let w=[...$.createdDomains].sort(),B=[...$.introducingPeers].sort(),X=`${$.created} agent${$.created===1?"":"s"}`;return{alerts:[{dedupeKey:`sightings:${u6(`${$.observedAt}\x00${w.join("\x00")}`)}`,title:"New agent sightings",body:`${X} sighted through ${B.join(", ")}`}]}}})}async getTools(){return[h1Q(this.getContext(),this.fetchFn),T1Q(this.getContext(),this.fetchFn),S1Q(this.getContext(),this.fetchFn)]}}function lNA(A={}){return new pNA(void 0,A)}zA();zA();h0();var sy=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),m1Q=sy,V70=MB.extend({entityType:W.literal(m9),metadata:m1Q});zA();class jo extends zQ{constructor(){super({entityType:m9,purpose:"A capability advertised by a remote agent.",schema:V70,frontmatterSchema:sy})}fromMarkdown(A){let Q=this.parseFrontMatter(A,sy);return{content:A,entityType:m9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}zA();h0();var w68=W.object({skills:W.array(sy).max(8)}),u1Q=G2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:w68,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
11573
+ `,Po={kicker:"Agent network",headingLead:"The rhizome grows",headingAccent:"beneath this brain",lede:"Every agent this brain has met, mapped by how close its work runs to ours \u2014 distance measured in meaning, not geography. Threads thicken where practices touch; where several lights gather, a constellation forms.",ctaLabel:"Meet the agents",ctaHref:"/agents"};function yNA(A){let Q=A.nodes.filter((K)=>K.status!=="archived").length,$=A.nodes.length-Q,w=A.kicker??Po.kicker,B=A.headingLead??Po.headingLead,X=A.headingAccent??Po.headingAccent,Y=A.lede??Po.lede,Z=A.ctaLabel??Po.ctaLabel,H=A.ctaHref??Po.ctaHref;return Zw("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[Zw("style",{children:EQ8},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__grid",children:[Zw("div",{class:"agent-proximity-site__copy",children:[Zw("p",{class:"agent-proximity-site__kicker",children:w},void 0,!1,void 0,this),Zw("h2",{class:"agent-proximity-site__heading",children:[B," ",Zw("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{children:[Zw("div",{class:"agent-proximity-site__stat-number",children:$},void 0,!1,void 0,this),Zw("div",{class:"agent-proximity-site__stat-label",children:"archived traces"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Zw("a",{class:"agent-proximity-site__cta",href:H,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&Zw("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&Zw("p",{class:"agent-proximity-site__note",children:"Identity not indexed yet \u2014 using network centroid"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{class:"agent-proximity-site__map",children:Zw(uf0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zw("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[Zw("span",{children:[Zw("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),Zw("span",{children:[Zw("b",{children:"\xB7"},void 0,!1,void 0,this)," archived trace"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var TQ8=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),yQ8=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),gQ8=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),gNA=W.enum(["discovered","approved","archived"]),SQ8=W.enum(["professional","team","collective"]),mQ8=W.object({name:W.string(),kind:SQ8,organization:W.string().optional(),brainName:W.string(),url:W.url(),did:W.string().optional(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.url().optional(),status:gNA,discoveredAt:W.string()}),uQ8=W.object({name:W.string(),url:W.url(),status:gNA,discoveredAt:W.string().optional(),slug:W.string(),repoDid:W.string().optional(),brainDid:W.string().optional(),anchorDid:W.string().optional(),cardUri:W.string().optional(),cardCid:W.string().optional(),a2aEndpoint:W.url().optional()}),pf0=W.object({id:W.string(),entityType:W.literal(jw),content:W.string(),created:W.string(),updated:W.string(),visibility:TQ8,metadata:uQ8,contentHash:W.string(),frontmatter:mQ8,about:W.string(),skills:W.array(gQ8),notes:W.string(),url:W.string().optional(),typeLabel:W.string().optional()}),cQ8=W.object({agents:W.array(pf0),pageTitle:W.string().optional(),pagination:yQ8.nullable(),baseUrl:W.string().optional(),selectedStatus:W.union([W.literal("all"),gNA])}),R1Q="/scripts/agent-proximity-map.js",pQ8=new n$(B1Q,{title:"Network",mappings:[{key:"kicker",label:"Kicker",type:"string"},{key:"headingLead",label:"Heading Lead",type:"string"},{key:"headingAccent",label:"Heading Accent",type:"string"},{key:"lede",label:"Lede",type:"string"},{key:"ctaLabel",label:"Cta Label",type:"string"},{key:"ctaHref",label:"Cta Href",type:"string"}]});function v1Q(){return{[PNA]:G2({name:PNA,description:"Semantic agent proximity map site section",schema:hb,dataSourceId:vf0,overlayFormatter:pQ8,requiredPermission:"public",runtimeScripts:[{src:R1Q,defer:!0}],staticAssets:{[R1Q]:Io},layout:{component:yNA}}),[bNA]:G2({name:bNA,description:"Agent directory list page template",schema:cQ8,dataSourceId:H70,requiredPermission:"public",layout:{component:O1Q}}),[jNA]:G2({name:jNA,description:"Individual agent profile template",schema:W.object({agent:pf0,prevAgent:pf0.nullable(),nextAgent:pf0.nullable()}),dataSourceId:H70,requiredPermission:"public",layout:{component:x1Q}})}}var bo={name:"@brains/agent-discovery",version:"0.2.0-alpha.196",description:"Agent discovery \u2014 brain+anchor contacts and skills",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/auth-service":"workspace:*","@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/dashboard":"workspace:*","@brains/http-signatures":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var iQ8=new L4;class SNA extends c6{entityType=jw;schema=K70;adapter=iQ8;constructor(){super(uAQ,bo,{},bY)}createGenerationHandler(A){return new ONA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return v1Q()}getDataSources(){return[new Ef0(this.logger.child("AgentDataSource")),new yf0]}async onRegister(A){_1Q(A),I1Q(A,this.id)}async getInstructions(){return P1Q()}}function mNA(){return new SNA}zA();EZ();h0();c4();h0();var C1Q=W.object({source:W.object({kind:W.literal("url"),url:W.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:W.boolean().optional(),confirmationToken:W.string().optional()}),dQ8=new L4;function nQ8(A){let Q=Eb(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function rQ8(A,Q){return(Eb(Q)||A).toLowerCase()}async function oQ8(A){let{context:Q,entityId:$,card:w}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:jw,id:$}),Y=Lo(w,{status:"approved"}),H={...dQ8.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:w.url};if(X){let U={...X,content:Y.content,metadata:H,updated:B};return await Q.entityService.updateEntity({entity:U}),{entity:U,created:!1}}let K={id:$,entityType:jw,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function h1Q(A,Q=globalThis.fetch){let w=new eU;return{name:"agent_connect",description:"Verify and connect a remote A2A agent by fetching its Agent Card from /.well-known/agent-card.json, then save the verified contact in the local agent directory as approved for future outbound calls. Never use this tool for a request to approve or archive an existing saved contact; update that contact's status with system_update instead. This adds a directory contact; it does not message the remote agent or grant it inbound trusted access. Requires confirmation before verification and persistence. Call this tool without confirmed on the initial request; the tool returns confirmation args for the user to approve.",inputSchema:C1Q.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=C1Q.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((U)=>`${U.path.join(".")}: ${U.message}`).join(", ")}`};let Z=Y.data,H=nQ8(Z.source.url);if(!H)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(jw,"create",X)}catch(U){return{success:!1,error:U instanceof Error?U.message:String(U)}}if(Z.confirmed){let U=Z.confirmationToken,G=w.validate(U,Z);if(G.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await Fo(H.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=rQ8(H.domain,D.url),{entity:J,created:F}=await oQ8({context:A,entityId:q,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:J.metadata.status,entityId:J.id,connected:!0,created:F,a2aEndpoint:D.url,skills:D.skills.map((L)=>({name:L.name,description:L.description,tags:L.tags}))}}}let K=w.create((U)=>({source:Z.source,confirmed:!0,confirmationToken:U}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${H.domain}?`,preview:`This will fetch and validate ${H.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:K}}}}h0();var E1Q=W.object({}),sQ8=W.object({agents:W.array(W.object({name:W.string(),url:W.string()}))}),uNA=new L4;async function aQ8(A,Q,$){let w=`https://${A}/.well-known/agent-directory.json`;try{let B=await Q(w,$?{signal:$}:void 0);if(!B.ok)return null;let X=sQ8.safeParse(await B.json());return X.success?X.data:null}catch{if($?.aborted)throw $.reason;return null}}async function cNA(A,Q=globalThis.fetch,$){let w=await A.entityService.listEntities({entityType:jw}),B=w.filter((L)=>L.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let L of B){$?.throwIfAborted();let _=await aQ8(L.id,Q,$);if(!_){Z+=1;continue}for(let j of _.agents){let b=Eb(j.url).toLowerCase();if(!b||b===X||b===L.id)continue;let f=Y.get(b)??new Set;f.add(L.id),Y.set(b,f)}}let H=new Map(w.map((L)=>[L.id,L])),K=new Date().toISOString(),U=[],G=new Set,D=0,q=0,J=0,F=0;for(let[L,_]of Y){$?.throwIfAborted();let j=H.get(L);if(j){let{frontmatter:R,body:O}=uNA.parseEntity(j),S=R.introducedBy??[];if(R.status!=="discovered"||S.length===0){J+=1;continue}let u=[...S,...[..._].filter((i)=>!S.includes(i))];if(u.length===S.length)continue;await A.entityService.updateEntity({entity:{...j,content:uNA.createAgentContent({...R,introducedBy:u,about:O.about,skills:O.skills,notes:O.notes}),updated:K}}),q+=1;continue}let b=await Fo(L,Q,$);if(!b){F+=1;continue}let f=Lo(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),v=uNA.fromMarkdown(f.content);await A.entityService.createEntity({entity:{id:L,entityType:jw,content:f.content,metadata:{...v.metadata,...f.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(L);for(let R of _)G.add(R)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:q,alreadyKnown:J,unverified:F,createdDomains:U,introducingPeers:[...G],observedAt:K}}function T1Q(A,Q=globalThis.fetch){return{name:"agent_scan_directories",description:"Walk each approved agent's public directory at /.well-known/agent-directory.json and record second-order sightings: agents your peers list that you are not connected to. A sighting is saved as a discovered agent with provenance (which peers introduced it, hop count) and data from its own verified Agent Card. Re-scanning is idempotent: connected agents are skipped and repeat sightings only merge new introducers. Never approves anything; promotion stays with agent_connect.",inputSchema:E1Q.shape,visibility:"trusted",sideEffects:"external",handler:async($,w)=>{let B=E1Q.safeParse($);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(jw,"create",w)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await cNA(A,Q,w.signal);return{success:!0,data:{peersScanned:X.peersScanned,unreachablePeers:X.unreachablePeers,created:X.created,updated:X.updated,alreadyKnown:X.alreadyKnown,unverified:X.unverified}}}}}c4();h0();var tQ8=W.enum(["public","trusted"]),y1Q=W.object({agent:W.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:tQ8.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:W.boolean().optional(),confirmationToken:W.string().optional(),keyFingerprint:W.string().optional()}),eQ8=W.object({keys:W.array(W.unknown())}),A68=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),kid:W.string().optional(),alg:W.literal("EdDSA").optional()}).passthrough();function g1Q(A){return(Eb(A)||A.trim()).toLowerCase()}async function Q68(A,Q){let $=g1Q(Q),w=await A.entityService.getEntity({entityType:jw,id:$});if(!w)return null;let B=g1Q(w.metadata.a2aEndpoint??w.metadata.url);if(!B)return null;return{domain:B}}async function $68(A,Q){try{let $=await Q(`https://${A}/.well-known/jwks.json`);if(!$.ok)return null;let w=eQ8.safeParse(await $.json());if(!w.success)return null;let B=w.data.keys.map((X)=>A68.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return bUA(B.data)}catch{return null}}function S1Q(A,Q=globalThis.fetch){let w=new eU;return{name:"agent_set_trust_level",description:"Grant or revoke inbound A2A trust for a saved contact; this is the only tool for inbound trust changes. To revoke, call directly with level public\u2014no key fingerprint or preliminary lookup is needed. To grant, use level trusted; the tool resolves and pins the peer key. This does not add or remove directory contacts or change outbound calling. Requires confirmation.",inputSchema:y1Q.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=y1Q.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=xY();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await Q68(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=X.data;if(H.confirmed){let D=w.validate(H.confirmationToken,H);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(H.level==="trusted"){if(!H.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let K=H.level==="trusted"?await $68(Z.domain,Q):void 0;if(H.level==="trusted"&&!K)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let U=w.create((D)=>({agent:Z.domain,level:H.level,confirmed:!0,confirmationToken:D,...K?{keyFingerprint:K}:{}})),G=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:G?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:G?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${K}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${Z.domain}. The directory contact remains saved for outbound calls.`,args:U}}}}var lf0=W.object({notifyOnNewAgents:W.boolean().default(!1).describe("Notify when directory scans discover new agents")}).strict();class pNA extends d6{fetchFn;constructor(A,Q={}){super("agent",bo,Q,lf0);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",deliverAlerts:this.config.notifyOnNewAgents,run:async({signal:Q})=>{let $=await cNA(A,this.fetchFn,Q);if($.created===0||!this.config.notifyOnNewAgents)return{};let w=[...$.createdDomains].sort(),B=[...$.introducingPeers].sort(),X=`${$.created} agent${$.created===1?"":"s"}`;return{alerts:[{dedupeKey:`sightings:${u6(`${$.observedAt}\x00${w.join("\x00")}`)}`,title:"New agent sightings",body:`${X} sighted through ${B.join(", ")}`}]}}})}async getTools(){return[h1Q(this.getContext(),this.fetchFn),T1Q(this.getContext(),this.fetchFn),S1Q(this.getContext(),this.fetchFn)]}}function lNA(A={}){return new pNA(void 0,A)}zA();zA();h0();var sy=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),m1Q=sy,V70=MB.extend({entityType:W.literal(m9),metadata:m1Q});zA();class jo extends zQ{constructor(){super({entityType:m9,purpose:"A capability advertised by a remote agent.",schema:V70,frontmatterSchema:sy})}fromMarkdown(A){let Q=this.parseFrontMatter(A,sy);return{content:A,entityType:m9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}zA();h0();var w68=W.object({skills:W.array(sy).max(8)}),u1Q=G2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:w68,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
11574
11574
 
11575
11575
  Given knowledge domains, CONSOLIDATE related topics into broader skills.
11576
11576
  There should be FEWER skills than topics \u2014 combine related domains.
@@ -11832,9 +11832,9 @@ ${JSON.stringify($,null,2)}`}function tf0(A){return A.map((Q)=>Q.detail===null?{
11832
11832
  border-bottom: none;
11833
11833
  }
11834
11834
  }
11835
- `;import{jsxDEV as JW}from"preact/jsx-dev-runtime";var $2Q=Q2Q,Ax0=W.object({title:W.string(),detail:W.string().optional()}),f68=W.discriminatedUnion("status",[W.object({status:W.literal("generating")}),W.object({status:W.literal("ready"),strengths:W.array(Ax0).default([]),weaknesses:W.array(Ax0).default([]),opportunities:W.array(Ax0).default([]),threats:W.array(Ax0).default([]),derivedAt:W.string()})]);function x68({items:A}){if(A.length===0)return JW("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return JW("ul",{class:"swot-list",children:A.map((Q)=>JW("li",{class:"swot-item",children:[JW("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?JW("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function Qx0({title:A,tone:Q,items:$}){return JW("section",{class:`swot-cell is-${Q}`,children:[JW("div",{class:"swot-head",children:A},void 0,!1,void 0,this),JW(x68,{items:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Q_A({data:A}){let Q=f68.safeParse(A);if(!Q.success||Q.data.status==="generating")return JW("div",{"data-swot-widget":!0,children:JW("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let $=Q.data;return JW("div",{"data-swot-widget":!0,children:JW("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[JW(Qx0,{title:"Strengths",tone:"s",items:$.strengths},void 0,!1,void 0,this),JW(Qx0,{title:"Weaknesses",tone:"w",items:$.weaknesses},void 0,!1,void 0,this),JW(Qx0,{title:"Opportunities",tone:"o",items:$.opportunities},void 0,!1,void 0,this),JW(Qx0,{title:"Threats",tone:"t",items:$.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var $_A={name:"@brains/assessment",version:"0.2.0-alpha.195",description:"Assessment outputs and capability-profile analysis",dependencies:{"@brains/content-formatters":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var v68=W.object({status:W.enum(["ready","generating"])}),w_A=new yb;class B_A extends c6{entityType="swot";schema=Mo;adapter=w_A;initialSyncComplete=!1;constructor(){super("swot",$_A,{},bY)}async onRegister(A){let Q=new ef0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=EW.from(async()=>{});if(!X)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",X);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return w_A.parseSwotContent(Y.content).frontmatter});let $=async(X)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:X},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${X}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:X}),null}},w=async(X)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await $(X)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await w("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",group:"network",section:"secondary",priority:14,rendererName:"SwotWidget",digestProvider:(X)=>{let{status:Y}=v68.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:Q_A,clientStyles:$2Q,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=w_A.parseSwotContent(X.content);return{status:"ready",...Y}}}}),{success:!0}});let B=async(X)=>{let{entityType:Y}=X.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await $("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",B),A.messaging.subscribe("entity:updated",B),A.messaging.subscribe("entity:deleted",B)}}function X_A(){return new B_A}zA();e9();h0();var LLB=new yb,w2Q=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),B2Q=W.enum(["discovered","approved"]),C68=W.object({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.string().url(),did:W.string().optional(),status:B2Q,discoveredAt:W.string().datetime()}),h68=MB.extend({entityType:W.literal("agent"),metadata:W.object({name:W.string(),url:W.string().url(),status:B2Q,slug:W.string()})}),Y_A=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),E68=MB.extend({entityType:W.literal("skill"),metadata:Y_A}),T68=W.object({about:W.string(),skills:W.array(w2Q),notes:W.string()});function y68(A){if(!Array.isArray(A)||A.length===0)return"";return A.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
11835
+ `;import{jsxDEV as JW}from"preact/jsx-dev-runtime";var $2Q=Q2Q,Ax0=W.object({title:W.string(),detail:W.string().optional()}),f68=W.discriminatedUnion("status",[W.object({status:W.literal("generating")}),W.object({status:W.literal("ready"),strengths:W.array(Ax0).default([]),weaknesses:W.array(Ax0).default([]),opportunities:W.array(Ax0).default([]),threats:W.array(Ax0).default([]),derivedAt:W.string()})]);function x68({items:A}){if(A.length===0)return JW("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return JW("ul",{class:"swot-list",children:A.map((Q)=>JW("li",{class:"swot-item",children:[JW("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?JW("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function Qx0({title:A,tone:Q,items:$}){return JW("section",{class:`swot-cell is-${Q}`,children:[JW("div",{class:"swot-head",children:A},void 0,!1,void 0,this),JW(x68,{items:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Q_A({data:A}){let Q=f68.safeParse(A);if(!Q.success||Q.data.status==="generating")return JW("div",{"data-swot-widget":!0,children:JW("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let $=Q.data;return JW("div",{"data-swot-widget":!0,children:JW("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[JW(Qx0,{title:"Strengths",tone:"s",items:$.strengths},void 0,!1,void 0,this),JW(Qx0,{title:"Weaknesses",tone:"w",items:$.weaknesses},void 0,!1,void 0,this),JW(Qx0,{title:"Opportunities",tone:"o",items:$.opportunities},void 0,!1,void 0,this),JW(Qx0,{title:"Threats",tone:"t",items:$.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var $_A={name:"@brains/assessment",version:"0.2.0-alpha.196",description:"Assessment outputs and capability-profile analysis",dependencies:{"@brains/content-formatters":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var v68=W.object({status:W.enum(["ready","generating"])}),w_A=new yb;class B_A extends c6{entityType="swot";schema=Mo;adapter=w_A;initialSyncComplete=!1;constructor(){super("swot",$_A,{},bY)}async onRegister(A){let Q=new ef0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=EW.from(async()=>{});if(!X)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",X);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return w_A.parseSwotContent(Y.content).frontmatter});let $=async(X)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:X},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${X}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:X}),null}},w=async(X)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await $(X)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await w("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",group:"network",section:"secondary",priority:14,rendererName:"SwotWidget",digestProvider:(X)=>{let{status:Y}=v68.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:Q_A,clientStyles:$2Q,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=w_A.parseSwotContent(X.content);return{status:"ready",...Y}}}}),{success:!0}});let B=async(X)=>{let{entityType:Y}=X.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await $("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",B),A.messaging.subscribe("entity:updated",B),A.messaging.subscribe("entity:deleted",B)}}function X_A(){return new B_A}zA();e9();h0();var LLB=new yb,w2Q=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),B2Q=W.enum(["discovered","approved"]),C68=W.object({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.string().url(),did:W.string().optional(),status:B2Q,discoveredAt:W.string().datetime()}),h68=MB.extend({entityType:W.literal("agent"),metadata:W.object({name:W.string(),url:W.string().url(),status:B2Q,slug:W.string()})}),Y_A=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),E68=MB.extend({entityType:W.literal("skill"),metadata:Y_A}),T68=W.object({about:W.string(),skills:W.array(w2Q),notes:W.string()});function y68(A){if(!Array.isArray(A)||A.length===0)return"";return A.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
11836
11836
  `)}function g68(A){if(!A.trim())return[];return A.split(`
11837
- `).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map(($)=>$.trim()).filter(Boolean):[]}))}var S68=new n$(T68,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:y68,parser:g68},{key:"notes",label:"Notes",type:"string"}]});class X2Q extends zQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:h68,frontmatterSchema:C68})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=S68.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(Q,{name:A.name,kind:A.kind,...A.organization?{organization:A.organization}:{},brainName:A.brainName,url:A.url,...A.did?{did:A.did}:{},status:A.status,discoveredAt:A.discoveredAt})}}class Y2Q extends zQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:E68,frontmatterSchema:Y_A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Y_A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var ILB=new X2Q,NLB=new Y2Q,m68=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),_LB=W.object({skills:W.array(m68),agents:W.array(W.object({id:W.string().optional(),name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.url(),did:W.string().optional(),status:W.enum(["discovered","approved"]),discoveredAt:W.string().datetime().optional(),about:W.string(),skills:W.array(w2Q),notes:W.string().default("")}))});var u68=W.object({}).strict();function $x0(A={}){return u68.parse(A),[X_A()]}zA();h0();h0();var Z_A=W.object({enabled:W.boolean().default(!0),pdsEndpoint:W.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:W.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:W.string().optional().describe("DID of the PDS repo that owns records"),appPassword:W.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:W.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:W.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});h0();var c68=W.looseObject({message:W.string()}),p68=W.looseObject({did:W.string(),handle:W.string(),accessJwt:W.string(),refreshJwt:W.string()}),W_A=W.looseObject({uri:W.string(),cid:W.string()}),l68=W_A.extend({value:W.record(W.string(),W.unknown())}),i68=W.looseObject({$type:W.literal("blob").optional(),ref:W.looseObject({$link:W.string()}),mimeType:W.string(),size:W.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),d68=W.looseObject({blob:i68});function n68(A){return A.replace(/\/+$/,"")}var r68=(A,Q)=>fetch(A,Q);async function F70(A,Q){let $=await A.text(),w;try{w=$.length>0?JSON.parse($):void 0}catch{if(!A.ok)throw Error(`AT Protocol request failed with ${A.status}`);throw Error("Failed to parse JSON")}if(!A.ok){let B=c68.safeParse(w);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(w)}class L70{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=n68(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??r68}async createSession(){let A=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.server.createSession`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:this.identifier,password:this.appPassword})}),Q=await F70(A,p68);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return F70($,W_A)}async putRecord(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return F70($,W_A)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return F70($,l68)}async uploadBlob(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return F70($,d68)}async getSession(){return this.session??=await this.createSession(),this.session}}function ty(A){return A?.startsWith("did:web:")??!1}function wx0(A){if(!ty(A))return;let Q=A.slice(8);if(!Q)return;let[$]=Q.split(":");if(!$)return;try{return decodeURIComponent($)}catch{return $}}function W2Q(A){if(!ty(A))return;let Q=A.slice(8);if(!Q)return;let[,...$]=Q.split(":");if($.length===0)return"/.well-known/did.json";return`/${$.map((B)=>{try{return decodeURIComponent(B)}catch{return B}}).join("/")}/did.json`}function H2Q(A){return A.replace(/\/+$/,"")}function I70(A){return`did:web:${encodeURIComponent(A)}`}function Bx0(A){return`${I70(A)}:anchor`}function H_A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function K2Q(A,Q){let $=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...H_A(Q),...$&&{alsoKnownAs:$},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:H2Q(A.pdsEndpoint)}]}}function U2Q(A){if(!ty(A.brainDid))return null;return K2Q(A,A.brainDid)}function Z2Q(A,Q){if(!A||!Q)return;let $=wx0(A),w=W2Q(A);if(!$||!w)return;return{path:w,hostname:$,document:Q}}function Xx0(A){let Q=[],$=Z2Q(A.brainDid,U2Q(A));if($)Q.push($);if(ty(A.anchorDid)&&A.anchorDid!==A.brainDid){let w=Z2Q(A.anchorDid,H_A(A.anchorDid));if(w)Q.push(w)}return Q}function K_A(A,Q){let $=[];if(!A.brainDid){let w=I70(Q);$.push({path:"/.well-known/did.json",hostname:Q,document:K2Q(A,w)})}if(!A.anchorDid){let w=Bx0(Q);$.push({path:"/anchor/did.json",hostname:Q,document:H_A(w)})}return $}function o68(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function s68(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function G2Q(A,Q){let $=A[Q];return typeof $==="string"&&$.length>0?$:void 0}function D2Q(A,Q){let $=A[Q];if(!Array.isArray($))return;let w=$.filter((B)=>typeof B==="string"&&B.length>0);return w.length>0?w:void 0}function a68(A){let Q=A.metadata,$=G2Q(Q,"name"),w=G2Q(Q,"description");if(!$||!w)return;let B=D2Q(Q,"tags"),X=D2Q(Q,"examples");return{id:s68($),name:$,description:w,...B&&{tags:B},...X&&{examples:X}}}async function t68(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map(($)=>a68($)).filter(($)=>$!==void 0).slice(0,100)}async function U_A(A,Q,$=new Date){let w=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=o68(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,H=Q.brainDid??I70(Z),K=Q.anchorDid??Bx0(Z);if(ty(H)){if(wx0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await t68(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:w.name,role:w.role,purpose:w.purpose,values:w.values},anchor:{did:K,name:B.name,kind:B.kind},skills:U,model:X.model,version:X.version,createdAt:$.toISOString(),updatedAt:$.toISOString()}}var q2Q={name:"@brains/atproto",version:"0.2.0-alpha.195",description:"AT Protocol integration for identity, publishing, discovery, and feeds",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var z2Q=i8["ai.rizom.brain.card"],A$8=W.looseObject({did:W.string()}),Q$8=W.looseObject({service:W.array(W.looseObject({id:W.string().optional(),type:W.string().optional(),serviceEndpoint:W.string().optional()})).optional()}),$$8="ai.rizom.brain.card",w$8="self",V2Q=50;class G_A extends d6{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",q2Q,A,Z_A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??D9.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=Xx0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((w)=>w.path),...Q])].map((w)=>({path:w,method:"GET",public:!0,handler:(B)=>{let X=new URL(B.url).hostname,Y=[...Xx0(this.config),...K_A(this.config,X)].filter((H)=>H.path===w),Z=Y.find((H)=>H.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let $=await U_A(A,this.config);aP(z2Q,$);let w=this.config.repoDid;if(Q.dryRun)return{record:$,dryRun:!0,...w&&{repo:w}};let B=this.resolveAppPassword();if(!this.config.identifier||!B)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(B),Y=await X.createSession(),Z=w??Y.did;if(!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let H=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:$});return{record:$,repo:Z,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let $=this.projectionRegistry.get(Q.entityType);if(!$)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,$)}async publishPost(A,Q){let $=this.projectionRegistry.get("post");if(!$)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},$)}async discoverBrainCards(A,Q){let $=[...new Set(Q.repos.map((X)=>X.trim()))].filter((X)=>X.length>0);if($.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if($.length>V2Q)throw Error(`AT Protocol discovery accepts at most ${V2Q} repos per batch`);let w=new Set,B=[];for(let X of $)try{let Y=await this.resolveRepoPdsEndpoint(X),Z=this.createPublicPdsClient(Y.pdsEndpoint);if(!Z.getRecord)throw Error("AT Protocol PDS client does not support record reads");let H=await Z.getRecord({repo:Y.repoDid,collection:$$8,rkey:w$8});aP(z2Q,H.value);let K=X$8(H.uri)??Y.repoDid,U=`${K}:${H.uri}:${H.cid}`;if(w.has(U)){B.push({repo:X,status:"skipped",repoDid:K,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}w.add(U),await A.messaging.send({type:Q50,payload:{repoDid:K,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:K,uri:H.uri,cid:H.cid})}catch(Y){B.push({repo:X,status:"skipped",error:eA(Y)})}return{discovered:B.filter((X)=>X.status==="discovered").length,skipped:B.filter((X)=>X.status==="skipped").length,results:B}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:eA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,$){let w=await this.findPublishEntity(A,Q),B=Q.entityId??Q.slug;if(!B)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!w)throw Error(`${Q.entityType} not found: ${B}`);if(w.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${B}`);let X=this.config.repoDid;if(Q.dryRun){let D=await $.buildRecord({entity:w,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return aP($.lexicon,D),{record:D,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),H=await Z.createSession(),K=X??H.did,U=await $.buildRecord({entity:w,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(aP($.lexicon,U),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let G=await Z.putRecord({repo:K,collection:$.collection,rkey:B$8(w.id),...$.validate!==void 0&&{validate:$.validate},record:U});return await $.onPublished?.({entity:w,context:A,record:U,uri:G.uri,cid:G.cid}),{record:U,repo:K,uri:G.uri,cid:G.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new L70({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let $=await this.resolveDidToPdsEndpoint(Q);if(!$)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:$}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let $=await this.fetch(Q.toString());if(!$.ok)return;let w=A$8.safeParse(await $.json());return w.success?w.data.did:void 0}async resolveDidToPdsEndpoint(A){let Q=A.startsWith("did:plc:")?await this.fetchJson(`https://plc.directory/${encodeURIComponent(A)}`):A.startsWith("did:web:")?await this.fetchJson(Y$8(A)):void 0,$=Q$8.safeParse(Q);if(!$.success)return;return $.data.service?.find((B)=>B.id==="#atproto_pds"||B.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new L70({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function B$8(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function X$8(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function Y$8(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[$,...w]=Q;if(!$)throw Error(`Invalid did:web value: ${A}`);if(w.length===0)return`https://${$}/.well-known/did.json`;return`https://${$}/${w.join("/")}/did.json`}function Yx0(A,Q){return new G_A(A,Q)}zA();h0();var Zx0={name:"@brains/rover",version:"0.2.0-alpha.195",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/products":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/rover-onboarding":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-content":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/topics":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*","@rizom/theme-default":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*","@rizom/site-rizom-ai":"workspace:*","@rizom/theme-rizom-ai":"workspace:*",typescript:"^7.0.2"},files:["src","brain.eval.yaml","env.schema.template"],main:"./src/index.ts",private:!0,scripts:{"build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:core:coverage":"brain-eval --suite core --tool-coverage","eval:default":"brain-eval --suite default","eval:default:coverage":"brain-eval --suite default --tool-coverage","eval:full":"brain-eval --suite full","eval:full:coverage":"brain-eval --suite full --tool-coverage",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:ui && cd test-apps/core && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:default":"bun run build:ui && cd test-apps/default && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:full":"bun run build:ui && cd test-apps/full && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:rizom-ai":"bun run build:ui && cd test-apps/rizom-ai && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:slack":"bun run --filter @brains/chat slack:preflight && bun run build:ui && cd test-apps/slack && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var W$8=W.looseObject({});class J2Q extends d6{constructor(A={}){super("rover-profile",Zx0,A,W$8)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",yC)}}function F2Q(A={}){return new J2Q(A)}zA();h0();D5();zA();zA();var N70=C_.extend(yC.shape);class Wx0{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,$){let w=$.entityService,[B,X,Y,Z]=await Promise.all([bc(w,N70),Bk0(w,{entityType:"post",count:3,parse:oB0}),Bk0(w,{entityType:"deck",count:3,parse:$90}),nB0(w)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:GJA(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}zA();class Hx0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,$){let B={profile:await bc($.entityService,N70)};return Q.parse(B)}}import{jsxDEV as F5,Fragment as U$8}from"preact/jsx-dev-runtime";var H$8="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",K$8="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",D_A=({number:A,title:Q,blurb:$,children:w})=>F5("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:F5("div",{className:"max-w-6xl mx-auto",children:F5("div",{className:H$8,children:[F5(DzA,{title:Q,number:A,blurb:$},void 0,!1,void 0,this),F5("div",{className:K$8,"aria-hidden":"true"},void 0,!1,void 0,this),F5("div",{className:"mt-6 md:mt-0",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),q_A=({profile:A,posts:Q,decks:$,postsListUrl:w,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,H=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),K=$.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),U=A.name||"Home",G=[A.intro,A.description,Z].find((q)=>q)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return F5(U$8,{children:[F5(E6,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),F5("div",{className:"homepage-list bg-theme",children:[F5("header",{className:"hero-bg-pattern relative w-full px-6 md:px-12 pt-28 pb-24 md:pt-28 md:pb-24 overflow-hidden border-b border-rule",children:F5("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&F5("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[F5("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),F5("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&F5("h1",{className:"font-heading text-[clamp(2.75rem,6.5vw,5.5rem)] font-normal text-heading leading-[1.02] tracking-[-0.025em] max-w-[18ch] [font-variation-settings:'opsz'_144,'SOFT'_30]",children:Jj0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&F5("p",{className:"font-heading font-light text-[clamp(1.1rem,1.8vw,1.4rem)] leading-[1.5] text-theme-muted max-w-[42ch] mt-8 [font-variation-settings:'opsz'_24]",children:Jj0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F5(D_A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:F5(Vj0,{items:H,viewAllUrl:w,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&F5(D_A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:F5(Vj0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&F5(D_A,{number:"03",title:"About",blurb:Y.about?.blurb,children:F5("div",{className:"flex flex-col gap-8",children:[A.description&&F5("p",{className:"font-heading font-light text-[1.25rem] leading-[1.55] text-theme max-w-[55ch] [font-variation-settings:'opsz'_24,'SOFT'_50]",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&F5(qzA,{subjects:A.expertise},void 0,!1,void 0,this),F5("a",{href:"/about",className:"mt-6 inline-flex items-center gap-2 font-mono text-[0.7rem] font-medium uppercase tracking-[0.18em] text-accent pb-1 relative before:content-[''] before:absolute before:left-0 before:right-full before:bottom-0 before:h-px before:bg-accent before:transition-[right] before:duration-300 hover:before:right-0",children:["Learn more",F5("span",{"aria-hidden":"true",children:"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F5(tqA,{cta:X,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 Rw,Fragment as G$8}from"preact/jsx-dev-runtime";var z_A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,$=[A.description,A.intro].find((B)=>B)??"About page",w=A.expertise!==void 0&&A.expertise.length>0||Boolean(A.currentFocus)||Boolean(A.availability)||Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0;return Rw(G$8,{children:[Rw(E6,{title:Q,description:$,ogType:"profile"},void 0,!1,void 0,this),Rw("div",{className:"about-page bg-theme",children:[Rw("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:Rw("div",{className:"relative z-10 max-w-4xl mx-auto",children:[Rw("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&&Rw("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),Rw("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&Rw("section",{className:"content-section-reveal mb-20 md:mb-28",children:Rw(XX,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&Rw("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),Rw("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>Rw("li",{className:i50({variant:"accent",size:"lg"}),children:B},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),Rw("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&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),Rw("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0)&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),Rw("div",{className:"space-y-4",children:[A.email&&Rw("p",{className:"text-lg",children:Rw("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&&Rw("p",{className:"text-lg",children:Rw("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&&Rw("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>Rw(BX,{href:B.url,external:!0,variant:"secondary",size:"md",children:B.label?.length?B.label:B.platform},X,!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 FW,Fragment as L2Q}from"preact/jsx-dev-runtime";var V_A=()=>{return FW(L2Q,{children:[FW(E6,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),FW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FW("div",{className:"text-center max-w-md",children:[FW("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),FW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),FW("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),FW(BX,{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)},J_A=()=>{return FW(L2Q,{children:[FW(E6,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),FW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FW("div",{className:"text-center max-w-md",children:[FW("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),FW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),FW("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),FW(BX,{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)};h0();var I2Q=W.object({label:W.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:W.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),D$8={post:{label:"Post"},deck:{label:"Deck"}},N2Q=W.object({entityDisplay:W.object({post:I2Q,deck:I2Q}).default(D$8).describe("Display metadata for post and deck entity types used by the homepage")});var _2Q={name:"@brains/site-professional",version:"0.2.0-alpha.195",description:"Professional site composition package",dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/site-info":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",typecheck:"tsc --noEmit"},type:"module"};var z$8=W.object({blurb:W.string().optional().describe("Short italic subtitle under the section title")}),V$8=W.object({heading:W.string(),buttonText:W.string(),buttonLink:W.string()}),P2Q=W.looseObject({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),description:W.string().optional(),avatar:W.string().optional(),website:W.string().optional(),email:W.string().optional(),socialLinks:W.array(W.object({platform:W.enum(["github","instagram","linkedin","email","website"]),url:W.string(),label:W.string().optional()})).optional(),tagline:W.string().optional(),intro:W.string().optional(),story:W.string().optional(),role:W.string().optional(),audience:W.string().optional(),expertise:W.array(W.string()).optional(),currentFocus:W.string().optional(),availability:W.string().optional(),desiredTone:W.string().optional()}),J$8=W.looseObject({id:W.string(),entityType:W.literal("post"),content:W.string(),created:W.string(),updated:W.string(),contentHash:W.string(),metadata:W.looseObject({title:W.string(),publishedAt:W.string().optional()}),frontmatter:W.looseObject({excerpt:W.string(),seriesName:W.string().optional(),seriesIndex:W.number().optional()}),body:W.string(),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),seriesUrl:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional(),coverImageSrcset:W.string().optional(),coverImageSizes:W.string().optional()}),F$8=W.looseObject({id:W.string(),entityType:W.literal("deck"),content:W.string(),created:W.string(),updated:W.string(),contentHash:W.string(),metadata:W.looseObject({title:W.string(),publishedAt:W.string().optional()}),frontmatter:W.looseObject({title:W.string(),description:W.string().optional(),publishedAt:W.string().optional()}),body:W.string(),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});class F_A extends d6{dependencies=["blog","decks"];constructor(A){super("professional-site",_2Q,A,N2Q)}async onRegister(A){let Q=this.config.entityDisplay.post,$=this.config.entityDisplay.deck,w=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,B=`/${$.pluralName??$.label.toLowerCase()+"s"}`,X=new Wx0(w,B);A.entities.registerDataSource(X);let Y=new Hx0;A.entities.registerDataSource(Y);let Z=W.object({profile:P2Q,posts:W.array(J$8),decks:W.array(F$8),postsListUrl:W.string(),decksListUrl:W.string(),cta:V$8,sections:W.record(W.string(),z$8)}),H=W.object({profile:P2Q}),K=W.object({});A.templates.register({"homepage-list":G2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:q_A}}),about:G2({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:z_A}}),"subscribe-thanks":G2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:V_A}}),"subscribe-error":G2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:J_A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function b2Q(A){return new F_A(A??{})}var j2Q=[{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 Kx0}from"preact/jsx-dev-runtime";function M2Q({sections:A,siteInfo:Q,slots:$,wordmark:w}){return Kx0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[Kx0($zA,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...w!==void 0?{wordmark:w}:{}},void 0,!1,void 0,this),Kx0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),Kx0(QzA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:$?.getSlot("footer-top").map((B)=>B.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var L$8={layouts:{default:M2Q},routes:j2Q,plugin:b2Q,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"}}}},_70=L$8;var k2Q=`/*
11837
+ `).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map(($)=>$.trim()).filter(Boolean):[]}))}var S68=new n$(T68,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:y68,parser:g68},{key:"notes",label:"Notes",type:"string"}]});class X2Q extends zQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:h68,frontmatterSchema:C68})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=S68.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(Q,{name:A.name,kind:A.kind,...A.organization?{organization:A.organization}:{},brainName:A.brainName,url:A.url,...A.did?{did:A.did}:{},status:A.status,discoveredAt:A.discoveredAt})}}class Y2Q extends zQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:E68,frontmatterSchema:Y_A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Y_A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var ILB=new X2Q,NLB=new Y2Q,m68=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),_LB=W.object({skills:W.array(m68),agents:W.array(W.object({id:W.string().optional(),name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),brainName:W.string(),url:W.url(),did:W.string().optional(),status:W.enum(["discovered","approved"]),discoveredAt:W.string().datetime().optional(),about:W.string(),skills:W.array(w2Q),notes:W.string().default("")}))});var u68=W.object({}).strict();function $x0(A={}){return u68.parse(A),[X_A()]}zA();h0();h0();var Z_A=W.object({enabled:W.boolean().default(!0),pdsEndpoint:W.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:W.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:W.string().optional().describe("DID of the PDS repo that owns records"),appPassword:W.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:W.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:W.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});h0();var c68=W.looseObject({message:W.string()}),p68=W.looseObject({did:W.string(),handle:W.string(),accessJwt:W.string(),refreshJwt:W.string()}),W_A=W.looseObject({uri:W.string(),cid:W.string()}),l68=W_A.extend({value:W.record(W.string(),W.unknown())}),i68=W.looseObject({$type:W.literal("blob").optional(),ref:W.looseObject({$link:W.string()}),mimeType:W.string(),size:W.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),d68=W.looseObject({blob:i68});function n68(A){return A.replace(/\/+$/,"")}var r68=(A,Q)=>fetch(A,Q);async function F70(A,Q){let $=await A.text(),w;try{w=$.length>0?JSON.parse($):void 0}catch{if(!A.ok)throw Error(`AT Protocol request failed with ${A.status}`);throw Error("Failed to parse JSON")}if(!A.ok){let B=c68.safeParse(w);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(w)}class L70{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=n68(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??r68}async createSession(){let A=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.server.createSession`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({identifier:this.identifier,password:this.appPassword})}),Q=await F70(A,p68);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return F70($,W_A)}async putRecord(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return F70($,W_A)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return F70($,l68)}async uploadBlob(A){let Q=await this.getSession(),$=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return F70($,d68)}async getSession(){return this.session??=await this.createSession(),this.session}}function ty(A){return A?.startsWith("did:web:")??!1}function wx0(A){if(!ty(A))return;let Q=A.slice(8);if(!Q)return;let[$]=Q.split(":");if(!$)return;try{return decodeURIComponent($)}catch{return $}}function W2Q(A){if(!ty(A))return;let Q=A.slice(8);if(!Q)return;let[,...$]=Q.split(":");if($.length===0)return"/.well-known/did.json";return`/${$.map((B)=>{try{return decodeURIComponent(B)}catch{return B}}).join("/")}/did.json`}function H2Q(A){return A.replace(/\/+$/,"")}function I70(A){return`did:web:${encodeURIComponent(A)}`}function Bx0(A){return`${I70(A)}:anchor`}function H_A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function K2Q(A,Q){let $=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...H_A(Q),...$&&{alsoKnownAs:$},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:H2Q(A.pdsEndpoint)}]}}function U2Q(A){if(!ty(A.brainDid))return null;return K2Q(A,A.brainDid)}function Z2Q(A,Q){if(!A||!Q)return;let $=wx0(A),w=W2Q(A);if(!$||!w)return;return{path:w,hostname:$,document:Q}}function Xx0(A){let Q=[],$=Z2Q(A.brainDid,U2Q(A));if($)Q.push($);if(ty(A.anchorDid)&&A.anchorDid!==A.brainDid){let w=Z2Q(A.anchorDid,H_A(A.anchorDid));if(w)Q.push(w)}return Q}function K_A(A,Q){let $=[];if(!A.brainDid){let w=I70(Q);$.push({path:"/.well-known/did.json",hostname:Q,document:K2Q(A,w)})}if(!A.anchorDid){let w=Bx0(Q);$.push({path:"/anchor/did.json",hostname:Q,document:H_A(w)})}return $}function o68(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function s68(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function G2Q(A,Q){let $=A[Q];return typeof $==="string"&&$.length>0?$:void 0}function D2Q(A,Q){let $=A[Q];if(!Array.isArray($))return;let w=$.filter((B)=>typeof B==="string"&&B.length>0);return w.length>0?w:void 0}function a68(A){let Q=A.metadata,$=G2Q(Q,"name"),w=G2Q(Q,"description");if(!$||!w)return;let B=D2Q(Q,"tags"),X=D2Q(Q,"examples");return{id:s68($),name:$,description:w,...B&&{tags:B},...X&&{examples:X}}}async function t68(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map(($)=>a68($)).filter(($)=>$!==void 0).slice(0,100)}async function U_A(A,Q,$=new Date){let w=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=o68(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,H=Q.brainDid??I70(Z),K=Q.anchorDid??Bx0(Z);if(ty(H)){if(wx0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await t68(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:w.name,role:w.role,purpose:w.purpose,values:w.values},anchor:{did:K,name:B.name,kind:B.kind},skills:U,model:X.model,version:X.version,createdAt:$.toISOString(),updatedAt:$.toISOString()}}var q2Q={name:"@brains/atproto",version:"0.2.0-alpha.196",description:"AT Protocol integration for identity, publishing, discovery, and feeds",dependencies:{"@brains/atproto-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var z2Q=i8["ai.rizom.brain.card"],A$8=W.looseObject({did:W.string()}),Q$8=W.looseObject({service:W.array(W.looseObject({id:W.string().optional(),type:W.string().optional(),serviceEndpoint:W.string().optional()})).optional()}),$$8="ai.rizom.brain.card",w$8="self",V2Q=50;class G_A extends d6{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",q2Q,A,Z_A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??D9.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=Xx0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((w)=>w.path),...Q])].map((w)=>({path:w,method:"GET",public:!0,handler:(B)=>{let X=new URL(B.url).hostname,Y=[...Xx0(this.config),...K_A(this.config,X)].filter((H)=>H.path===w),Z=Y.find((H)=>H.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let $=await U_A(A,this.config);aP(z2Q,$);let w=this.config.repoDid;if(Q.dryRun)return{record:$,dryRun:!0,...w&&{repo:w}};let B=this.resolveAppPassword();if(!this.config.identifier||!B)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(B),Y=await X.createSession(),Z=w??Y.did;if(!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let H=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:$});return{record:$,repo:Z,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let $=this.projectionRegistry.get(Q.entityType);if(!$)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,$)}async publishPost(A,Q){let $=this.projectionRegistry.get("post");if(!$)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},$)}async discoverBrainCards(A,Q){let $=[...new Set(Q.repos.map((X)=>X.trim()))].filter((X)=>X.length>0);if($.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if($.length>V2Q)throw Error(`AT Protocol discovery accepts at most ${V2Q} repos per batch`);let w=new Set,B=[];for(let X of $)try{let Y=await this.resolveRepoPdsEndpoint(X),Z=this.createPublicPdsClient(Y.pdsEndpoint);if(!Z.getRecord)throw Error("AT Protocol PDS client does not support record reads");let H=await Z.getRecord({repo:Y.repoDid,collection:$$8,rkey:w$8});aP(z2Q,H.value);let K=X$8(H.uri)??Y.repoDid,U=`${K}:${H.uri}:${H.cid}`;if(w.has(U)){B.push({repo:X,status:"skipped",repoDid:K,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}w.add(U),await A.messaging.send({type:Q50,payload:{repoDid:K,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:K,uri:H.uri,cid:H.cid})}catch(Y){B.push({repo:X,status:"skipped",error:eA(Y)})}return{discovered:B.filter((X)=>X.status==="discovered").length,skipped:B.filter((X)=>X.status==="skipped").length,results:B}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:eA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,$){let w=await this.findPublishEntity(A,Q),B=Q.entityId??Q.slug;if(!B)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!w)throw Error(`${Q.entityType} not found: ${B}`);if(w.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${B}`);let X=this.config.repoDid;if(Q.dryRun){let D=await $.buildRecord({entity:w,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return aP($.lexicon,D),{record:D,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),H=await Z.createSession(),K=X??H.did,U=await $.buildRecord({entity:w,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(aP($.lexicon,U),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let G=await Z.putRecord({repo:K,collection:$.collection,rkey:B$8(w.id),...$.validate!==void 0&&{validate:$.validate},record:U});return await $.onPublished?.({entity:w,context:A,record:U,uri:G.uri,cid:G.cid}),{record:U,repo:K,uri:G.uri,cid:G.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new L70({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let $=await this.resolveDidToPdsEndpoint(Q);if(!$)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:$}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let $=await this.fetch(Q.toString());if(!$.ok)return;let w=A$8.safeParse(await $.json());return w.success?w.data.did:void 0}async resolveDidToPdsEndpoint(A){let Q=A.startsWith("did:plc:")?await this.fetchJson(`https://plc.directory/${encodeURIComponent(A)}`):A.startsWith("did:web:")?await this.fetchJson(Y$8(A)):void 0,$=Q$8.safeParse(Q);if(!$.success)return;return $.data.service?.find((B)=>B.id==="#atproto_pds"||B.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new L70({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function B$8(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function X$8(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function Y$8(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[$,...w]=Q;if(!$)throw Error(`Invalid did:web value: ${A}`);if(w.length===0)return`https://${$}/.well-known/did.json`;return`https://${$}/${w.join("/")}/did.json`}function Yx0(A,Q){return new G_A(A,Q)}zA();h0();var Zx0={name:"@brains/rover",version:"0.2.0-alpha.196",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/playbooks":"workspace:*","@brains/portfolio":"workspace:*","@brains/products":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/rover-onboarding":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-content":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/topics":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*","@rizom/theme-default":"workspace:*"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/typescript-config":"workspace:*","@rizom/site-rizom-ai":"workspace:*","@rizom/theme-rizom-ai":"workspace:*",typescript:"^7.0.2"},files:["src","brain.eval.yaml","env.schema.template"],main:"./src/index.ts",private:!0,scripts:{"build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:core:coverage":"brain-eval --suite core --tool-coverage","eval:default":"brain-eval --suite default","eval:default:coverage":"brain-eval --suite default --tool-coverage","eval:full":"brain-eval --suite full","eval:full:coverage":"brain-eval --suite full --tool-coverage",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:ui && cd test-apps/core && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:default":"bun run build:ui && cd test-apps/default && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:full":"bun run build:ui && cd test-apps/full && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:rizom-ai":"bun run build:ui && cd test-apps/rizom-ai && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:slack":"bun run --filter @brains/chat slack:preflight && bun run build:ui && cd test-apps/slack && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var W$8=W.looseObject({});class J2Q extends d6{constructor(A={}){super("rover-profile",Zx0,A,W$8)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",yC)}}function F2Q(A={}){return new J2Q(A)}zA();h0();D5();zA();zA();var N70=C_.extend(yC.shape);class Wx0{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,$){let w=$.entityService,[B,X,Y,Z]=await Promise.all([bc(w,N70),Bk0(w,{entityType:"post",count:3,parse:oB0}),Bk0(w,{entityType:"deck",count:3,parse:$90}),nB0(w)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:GJA(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}zA();class Hx0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,$){let B={profile:await bc($.entityService,N70)};return Q.parse(B)}}import{jsxDEV as F5,Fragment as U$8}from"preact/jsx-dev-runtime";var H$8="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",K$8="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",D_A=({number:A,title:Q,blurb:$,children:w})=>F5("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:F5("div",{className:"max-w-6xl mx-auto",children:F5("div",{className:H$8,children:[F5(DzA,{title:Q,number:A,blurb:$},void 0,!1,void 0,this),F5("div",{className:K$8,"aria-hidden":"true"},void 0,!1,void 0,this),F5("div",{className:"mt-6 md:mt-0",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),q_A=({profile:A,posts:Q,decks:$,postsListUrl:w,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,H=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),K=$.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),U=A.name||"Home",G=[A.intro,A.description,Z].find((q)=>q)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return F5(U$8,{children:[F5(E6,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),F5("div",{className:"homepage-list bg-theme",children:[F5("header",{className:"hero-bg-pattern relative w-full px-6 md:px-12 pt-28 pb-24 md:pt-28 md:pb-24 overflow-hidden border-b border-rule",children:F5("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&F5("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[F5("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),F5("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&F5("h1",{className:"font-heading text-[clamp(2.75rem,6.5vw,5.5rem)] font-normal text-heading leading-[1.02] tracking-[-0.025em] max-w-[18ch] [font-variation-settings:'opsz'_144,'SOFT'_30]",children:Jj0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&F5("p",{className:"font-heading font-light text-[clamp(1.1rem,1.8vw,1.4rem)] leading-[1.5] text-theme-muted max-w-[42ch] mt-8 [font-variation-settings:'opsz'_24]",children:Jj0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F5(D_A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:F5(Vj0,{items:H,viewAllUrl:w,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&F5(D_A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:F5(Vj0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&F5(D_A,{number:"03",title:"About",blurb:Y.about?.blurb,children:F5("div",{className:"flex flex-col gap-8",children:[A.description&&F5("p",{className:"font-heading font-light text-[1.25rem] leading-[1.55] text-theme max-w-[55ch] [font-variation-settings:'opsz'_24,'SOFT'_50]",children:A.description},void 0,!1,void 0,this),A.expertise&&A.expertise.length>0&&F5(qzA,{subjects:A.expertise},void 0,!1,void 0,this),F5("a",{href:"/about",className:"mt-6 inline-flex items-center gap-2 font-mono text-[0.7rem] font-medium uppercase tracking-[0.18em] text-accent pb-1 relative before:content-[''] before:absolute before:left-0 before:right-full before:bottom-0 before:h-px before:bg-accent before:transition-[right] before:duration-300 hover:before:right-0",children:["Learn more",F5("span",{"aria-hidden":"true",children:"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),F5(tqA,{cta:X,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 Rw,Fragment as G$8}from"preact/jsx-dev-runtime";var z_A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,$=[A.description,A.intro].find((B)=>B)??"About page",w=A.expertise!==void 0&&A.expertise.length>0||Boolean(A.currentFocus)||Boolean(A.availability)||Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0;return Rw(G$8,{children:[Rw(E6,{title:Q,description:$,ogType:"profile"},void 0,!1,void 0,this),Rw("div",{className:"about-page bg-theme",children:[Rw("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:Rw("div",{className:"relative z-10 max-w-4xl mx-auto",children:[Rw("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&&Rw("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),Rw("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&Rw("section",{className:"content-section-reveal mb-20 md:mb-28",children:Rw(XX,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&Rw("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),Rw("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>Rw("li",{className:i50({variant:"accent",size:"lg"}),children:B},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),Rw("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&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),Rw("p",{className:"text-lg text-theme leading-relaxed",children:A.availability},void 0,!1,void 0,this)]},void 0,!0,void 0,this),(Boolean(A.email)||Boolean(A.website)||A.socialLinks!==void 0&&A.socialLinks.length>0)&&Rw("section",{children:[Rw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),Rw("div",{className:"space-y-4",children:[A.email&&Rw("p",{className:"text-lg",children:Rw("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&&Rw("p",{className:"text-lg",children:Rw("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&&Rw("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>Rw(BX,{href:B.url,external:!0,variant:"secondary",size:"md",children:B.label?.length?B.label:B.platform},X,!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 FW,Fragment as L2Q}from"preact/jsx-dev-runtime";var V_A=()=>{return FW(L2Q,{children:[FW(E6,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),FW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FW("div",{className:"text-center max-w-md",children:[FW("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),FW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),FW("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),FW(BX,{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)},J_A=()=>{return FW(L2Q,{children:[FW(E6,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),FW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FW("div",{className:"text-center max-w-md",children:[FW("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),FW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),FW("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),FW(BX,{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)};h0();var I2Q=W.object({label:W.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:W.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),D$8={post:{label:"Post"},deck:{label:"Deck"}},N2Q=W.object({entityDisplay:W.object({post:I2Q,deck:I2Q}).default(D$8).describe("Display metadata for post and deck entity types used by the homepage")});var _2Q={name:"@brains/site-professional",version:"0.2.0-alpha.196",description:"Professional site composition package",dependencies:{"@brains/blog":"workspace:*","@brains/decks":"workspace:*","@brains/plugins":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-engine":"workspace:*","@brains/site-info":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",typecheck:"tsc --noEmit"},type:"module"};var z$8=W.object({blurb:W.string().optional().describe("Short italic subtitle under the section title")}),V$8=W.object({heading:W.string(),buttonText:W.string(),buttonLink:W.string()}),P2Q=W.looseObject({name:W.string(),kind:W.enum(["professional","team","collective"]),organization:W.string().optional(),description:W.string().optional(),avatar:W.string().optional(),website:W.string().optional(),email:W.string().optional(),socialLinks:W.array(W.object({platform:W.enum(["github","instagram","linkedin","email","website"]),url:W.string(),label:W.string().optional()})).optional(),tagline:W.string().optional(),intro:W.string().optional(),story:W.string().optional(),role:W.string().optional(),audience:W.string().optional(),expertise:W.array(W.string()).optional(),currentFocus:W.string().optional(),availability:W.string().optional(),desiredTone:W.string().optional()}),J$8=W.looseObject({id:W.string(),entityType:W.literal("post"),content:W.string(),created:W.string(),updated:W.string(),contentHash:W.string(),metadata:W.looseObject({title:W.string(),publishedAt:W.string().optional()}),frontmatter:W.looseObject({excerpt:W.string(),seriesName:W.string().optional(),seriesIndex:W.number().optional()}),body:W.string(),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),seriesUrl:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional(),coverImageSrcset:W.string().optional(),coverImageSizes:W.string().optional()}),F$8=W.looseObject({id:W.string(),entityType:W.literal("deck"),content:W.string(),created:W.string(),updated:W.string(),contentHash:W.string(),metadata:W.looseObject({title:W.string(),publishedAt:W.string().optional()}),frontmatter:W.looseObject({title:W.string(),description:W.string().optional(),publishedAt:W.string().optional()}),body:W.string(),url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()});class F_A extends d6{dependencies=["blog","decks"];constructor(A){super("professional-site",_2Q,A,N2Q)}async onRegister(A){let Q=this.config.entityDisplay.post,$=this.config.entityDisplay.deck,w=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,B=`/${$.pluralName??$.label.toLowerCase()+"s"}`,X=new Wx0(w,B);A.entities.registerDataSource(X);let Y=new Hx0;A.entities.registerDataSource(Y);let Z=W.object({profile:P2Q,posts:W.array(J$8),decks:W.array(F$8),postsListUrl:W.string(),decksListUrl:W.string(),cta:V$8,sections:W.record(W.string(),z$8)}),H=W.object({profile:P2Q}),K=W.object({});A.templates.register({"homepage-list":G2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:q_A}}),about:G2({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:z_A}}),"subscribe-thanks":G2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:V_A}}),"subscribe-error":G2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:J_A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function b2Q(A){return new F_A(A??{})}var j2Q=[{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 Kx0}from"preact/jsx-dev-runtime";function M2Q({sections:A,siteInfo:Q,slots:$,wordmark:w}){return Kx0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[Kx0($zA,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...w!==void 0?{wordmark:w}:{}},void 0,!1,void 0,this),Kx0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),Kx0(QzA,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:$?.getSlot("footer-top").map((B)=>B.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var L$8={layouts:{default:M2Q},routes:j2Q,plugin:b2Q,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"}}}},_70=L$8;var k2Q=`/*
11838
11838
  * Default theme \u2014 simplified editorial base inspired by the Rizom family.
11839
11839
  *
11840
11840
  * This theme is intentionally less branded than @brains/theme-rizom. It
@@ -14819,7 +14819,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});h0();var r
14819
14819
  `);return this.truncateContent(w||Q||so(A))}truncateContent(A){if(A.length<=f7Q)return A;let Q=A.slice(0,f7Q-1),$=Q.search(/\s\S*$/);return`${($>0?Q.slice(0,$):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===u9}isDecisionEntity(A){return A.entityType===FD}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return eV(Q)}}var _Z8=5,PZ8=3;function RjA(A){A.messaging.subscribe(TR,async(Q)=>{let $=aa.parse(Q.payload);return{success:!0,data:await xR0(A,$)}})}async function xR0(A,Q){let $=AB(Q.userPermissionLevel);if(!Q.channelId)return x7Q(A,Q,{visibilityScope:$,reason:"no-channel-context",items:[]}),{items:[]};let w=new ao(A),B=await w.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:_Z8,visibilityScope:$}),X=B.results.length===0?await w.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:PZ8,visibilityScope:$}):void 0,Y=B.results.length>0,Z=Y?B.results:X?.results??[];return x7Q(A,Q,{visibilityScope:$,spaceId:B.spaceId??X?.spaceId,reason:Z.length>0?"memory-injected":"no-same-space-memory",items:Z.map((H)=>bZ8(H,Y))}),{items:Z.map(jZ8)}}function x7Q(A,Q,$){A.logger.info("Conversation memory agent context audit",{conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,channelName:Q.channelName,userPermissionLevel:Q.userPermissionLevel,visibilityScope:$.visibilityScope,spaceId:$.spaceId,reason:$.reason,itemCount:$.items.length,items:$.items})}function bZ8(A,Q){return{id:A.id,entityType:A.entityType,conversationId:A.conversationId,spaceId:A.spaceId,visibility:A.visibility,score:A.score,updated:A.updated,eligibilityReason:Q?"same-space-query-match":"recent-same-space-memory"}}function jZ8(A){let Q=A.channelName??A.channelId;return{id:A.id,source:"conversation-memory",title:`${A.entityType} from ${Q}`,content:A.content,provenance:{entityType:A.entityType,entityId:A.id,conversationId:A.conversationId,spaceId:A.spaceId,interfaceType:A.interfaceType,channelId:A.channelId,channelName:A.channelName,updated:A.updated,score:A.score,messageCount:A.messageCount,entryCount:A.entryCount,status:A.status}}}h0();EZ();var C7Q=W.union([W.enum(["public","shared","restricted"]),W.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),h7Q=W.enum(["user","assistant"]),MZ8=W.object({actorId:W.string(),canonicalId:W.string().optional(),interfaceType:W.string(),role:h7Q,displayName:W.string().optional(),username:W.string().optional(),isBot:W.boolean().optional()}),kZ8=W.object({messageId:W.string().optional(),channelId:W.string().optional(),channelName:W.string().optional(),threadId:W.string().optional(),metadata:W.record(W.string(),W.unknown()).optional()}),CjA=W.object({role:h7Q,content:W.string(),timestamp:W.string().datetime().optional(),actor:MZ8.optional(),source:kZ8.optional()}),OZ8=W.object({conversationId:W.string().default("eval-conversation"),messages:W.array(CjA)}),fZ8=W.object({conversationId:W.string()}),xZ8=W.object({conversationId:W.string().default("eval-conversation"),interfaceType:W.string().default("eval"),channelId:W.string().default("eval-channel"),channelName:W.string().optional(),projectionDecision:W.enum(["update","append"]).default("update"),existingSummary:W.string().optional(),existingMessageCount:W.number().int().min(0).default(0),messages:W.array(CjA)}),RR0=W.object({actorId:W.string(),canonicalId:W.string().optional(),displayName:W.string().optional()}),RZ8=RR0.extend({roles:W.array(W.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:W.array(W.string()).optional()}),vZ8=W.object({actorId:W.string().optional(),canonicalId:W.string().optional(),displayName:W.string()}),E7Q=W.object({id:W.string(),entityType:W.enum(["summary","decision","action-item"]),content:W.string(),excerpt:W.string().optional(),score:W.number().optional(),conversationId:W.string(),interfaceType:W.string(),channelId:W.string(),channelName:W.string().optional(),updated:W.string().datetime().optional(),visibility:C7Q,status:W.string().optional(),participants:W.array(RZ8).optional(),decidedBy:W.array(RR0).optional(),mentionedBy:W.array(RR0).optional(),assignedTo:W.array(vZ8).optional(),requestedBy:W.array(RR0).optional()}),CZ8=W.object({query:W.string().optional(),conversationId:W.string().optional(),interfaceType:W.string().optional(),channelId:W.string().optional(),limit:W.number().int().min(1).optional(),includeOtherSpaces:W.boolean().optional(),actorId:W.string().optional(),canonicalId:W.string().optional(),visibilityScope:C7Q.optional(),memory:W.array(E7Q).optional()}),hZ8=W.object({conversationId:W.string().default("eval-conversation"),message:W.string(),interfaceType:W.string().default("eval"),channelId:W.string().optional(),channelName:W.string().optional(),userPermissionLevel:W.enum(["anchor","trusted","public"]).default("trusted"),memory:W.array(E7Q).optional()}),EZ8=W.object({conversationId:W.string().default("eval-conversation"),existingSummary:W.string().optional(),existingMessageCount:W.number().int().min(0).default(0),messages:W.array(CjA)});function T7Q(A){let{context:Q,logger:$,config:w}=A;Q.eval.registerHandler("summarizeMessages",async(B)=>{let X=OZ8.parse(B),Y=vjA(X.messages,X.conversationId),H=await new no(Q,$,w).extract(Y);return H.entries.map((K)=>{let U=H.decisions.filter((D)=>D.timeRange.start>=K.timeRange.start).filter((D)=>D.timeRange.end<=K.timeRange.end).map((D)=>D.text),G=H.actionItems.filter((D)=>D.timeRange.start>=K.timeRange.start).filter((D)=>D.timeRange.end<=K.timeRange.end).map((D)=>D.text);return{...K,decisions:U,actionItems:G,keyPointsText:K.keyPoints.join(`
14820
14820
  `),decisionsText:U.join(`
14821
14821
  `),actionItemsText:G.join(`
14822
- `)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=EZ8.parse(B),Y=vjA(X.messages,X.conversationId),Z=X.existingSummary?R7Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null;return new Rx(Q,$,w).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=CZ8.parse(B),Y=X.memory?v7Q(Q,X.memory):Q;return new ao(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=hZ8.parse(B),Y=X.memory?v7Q(Q,X.memory):Q;return xR0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=xZ8.parse(B),Y=vjA(X.messages,X.conversationId),Z=TZ8({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?R7Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null,K=[],U=[],G=yZ8({context:Q,conversation:Z,messages:Y,existing:H,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new Rx(G,$,w).projectConversation(X.conversationId),summaries:K.filter((J)=>J.entityType==="summary"),decisions:K.filter((J)=>J.entityType==="decision"),actionItems:K.filter((J)=>J.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=fZ8.parse(B);return new Rx(Q,$,w).projectConversation(X.conversationId)})}function R7Q(A){return{id:A.conversationId,entityType:"summary",content:A.content,contentHash:"eval-existing-summary",visibility:A.visibility,created:"2026-01-01T00:00:00.000Z",updated:"2026-01-01T00:00:00.000Z",metadata:{conversationId:A.conversationId,channelId:"eval-channel",interfaceType:"eval",messageCount:A.messageCount,entryCount:1,sourceHash:"eval-source-hash",projectionVersion:A.projectionVersion}}}function vjA(A,Q){return A.map(($,w)=>{let B=$.timestamp??new Date(Date.UTC(2026,0,1,0,w)).toISOString();return{id:`eval-message-${w+1}`,conversationId:Q,role:$.role,content:$.content,timestamp:B,metadata:{...$.actor?{actor:$.actor}:{},...$.source?{source:$.source}:{}}}})}function TZ8(A){let Q=A.messages[0],$=A.messages[A.messages.length-1],w=Q?.timestamp??"2026-01-01T00:00:00.000Z",B=$?.timestamp??w;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:w,lastActiveAt:B,createdAt:w,updatedAt:B,metadata:{}}}function yZ8(A){let Q=eV(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:$})=>$==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async($)=>{return A.deleted.push($),!0},upsertEntity:async({entity:$})=>{return A.upserted.push($),{entityId:$.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function v7Q(A,Q){let $=Q.map(gZ8),w=$.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??so(B)}));return{...A,entityService:{...A.entityService,search:async()=>w,listEntities:async({entityType:B})=>$.filter((X)=>X.entityType===B)}}}function gZ8(A){if(A.entityType==="summary")return SZ8(A);if(A.entityType==="decision")return mZ8(A);return uZ8(A)}function hjA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:u6(A.content),visibility:A.visibility,created:Q,updated:Q}}function SZ8(A){return{...hjA(A),entityType:"summary",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,messageCount:3,entryCount:1,sourceHash:`source-${A.id}`,projectionVersion:1,...A.participants?{participants:A.participants}:{}}}}function mZ8(A){return{...hjA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:eV(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:A.status==="superseded"?"superseded":"active",...A.decidedBy?{decidedBy:A.decidedBy}:{},...A.mentionedBy?{mentionedBy:A.mentionedBy}:{}}}}function uZ8(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...hjA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:eV(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:Q,...A.assignedTo?{assignedTo:A.assignedTo}:{},...A.requestedBy?{requestedBy:A.requestedBy}:{}}}}var y7Q={name:"@brains/conversation-memory",version:"0.2.0-alpha.195",description:"Plugin for deriving durable conversation memory",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/conversation-service":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var pZ8=new vz,lZ8=new po,iZ8=new lo,dZ8=W.object({conversationId:W.string()});class EjA extends c6{entityType=u9;schema=K40;adapter=pZ8;constructor(A={}){super(LR0,y7Q,A,kjA)}getConfig(){return this.config}getTemplates(){return{"summary-list":W7Q,"summary-detail":H7Q,"ai-response":K7Q}}getDataSources(){return[new xjA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:u9,job:{type:t9Q,handler:new jR0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await OC(A,u9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:PjA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:LR0}}},sourceChange:{sourceKind:DA0,sourceTypes:[DA0],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[iu],jobData:(Q)=>{let{conversationId:$}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:$,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:$}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:PjA,deduplication:"skip",deduplicationKey:`conversation-memory:${$}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${$}`,pluginId:LR0}}}}}]}parseConversationMessagePayload(A){return dZ8.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:$}=this.parseConversationMessagePayload(Q),w=await A.conversations.get($);if(!w)return!1;return Wg({conversation:w,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(FD,U40,lZ8),A.entities.register(Rz,G40,iZ8),D7Q({context:A,pluginId:this.id}),z7Q({context:A,pluginId:this.id}),b7Q({context:A,pluginId:this.id}),k7Q({context:A,pluginId:this.id,config:this.config}),RjA(A),T7Q({context:A,logger:this.logger,config:this.config})}}function TjA(A={}){return new EjA(A)}zA();h0();h0();e9();var g7Q=W.object({label:W.string(),href:W.string()}),S7Q=W.object({label:W.string(),title:W.string(),detail:W.string()}),nZ8=W.object({eyebrow:W.string(),name:W.string(),sub:W.string()}),rZ8=W.object({tone:W.enum(["capture","synthesis","share"]),title:W.string(),text:W.string()}),yjA=W.object({captures:W.number(),links:W.number(),topics:W.number(),summaries:W.number(),peers:W.number()}),to=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:g7Q,secondaryCta:g7Q,inputs:W.array(S7Q).min(1),outputs:W.array(S7Q).min(1),core:nZ8,legend:W.array(rZ8).min(1)}),gjA=to.extend({counts:yjA}),m7Q={eyebrow:"A team brain, diagrammed",headline:"Relay sits between the work and the world, and keeps both honest.",intro:"Capture sources flow into a shared brain; the brain organizes, summarizes, and \u2014 selectively \u2014 exposes a public surface. Everything else stays private and operational.",primaryCta:{label:"See it on a real team",href:"#diagram"},secondaryCta:{label:"Read the model",href:"/about"},inputs:[{label:"Source \xB7 chat",title:"Discord",detail:"Shared decisions and field notes captured in flow."},{label:"Source \xB7 agent",title:"MCP / CLI",detail:"Structured captures from tools and assistants."},{label:"Source \xB7 web",title:"Links & docs",detail:"External material indexed with sourceable metadata."}],outputs:[{label:"Surface \xB7 public",title:"Default site",detail:"A small, durable face onto what the team currently knows."},{label:"Surface \xB7 agents",title:"A2A exchange",detail:"Peer brains coordinate over an approved, signed protocol."},{label:"Surface \xB7 query",title:"Team Q&A",detail:"Ask the brain in chat; answers cite the captures behind them."}],core:{eyebrow:"The relay",name:"brain",sub:"capture \u2192 topics \u2192 summaries"},legend:[{tone:"capture",title:"Capture",text:"Anything the team already does that produces a trace \u2014 chat messages, links, deploys, decisions."},{tone:"synthesis",title:"Synthesis",text:"The work the brain does on its own time \u2014 clustering captures into topics, summaries, and durable memory."},{tone:"share",title:"Share",text:"A small, opinionated public surface and an approved agent-to-agent protocol. Most memory stays private."}]},u7Q=new n$(to,{title:"Home diagram",mappings:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"headline",label:"Headline",type:"string"},{key:"intro",label:"Intro",type:"string"},{key:"primaryCta",label:"Primary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"secondaryCta",label:"Secondary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"inputs",label:"Inputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"outputs",label:"Outputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"core",label:"Core",type:"object",children:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"name",label:"Name",type:"string"},{key:"sub",label:"Sub",type:"string"}]},{key:"legend",label:"Legend",type:"array",itemType:"object",itemMappings:[{key:"tone",label:"Tone",type:"string"},{key:"title",label:"Title",type:"string"},{key:"text",label:"Text",type:"string"}]}]});function vR0(A){return u7Q.parse(A)}function c7Q(A){return u7Q.format(A)}h0();var oZ8=W.looseObject({query:W.object({routeId:W.string().default("home"),sectionId:W.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),sZ8={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class SjA{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,$){let w=oZ8.parse(A??{}),B=await this.fetchContent($,w.query.routeId,w.query.sectionId),X=await this.fetchCounts($);return Q.parse({...B,counts:X})}async fetchContent(A,Q,$){let w=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${$}`});if(!w?.content)return m7Q;return to.parse(vR0(w.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(sZ8).map(async([$,w])=>[$,await this.countOrZero(A,w)]));return yjA.parse(Object.fromEntries(Q))}async countOrZero(A,Q){if(!A.entityService.hasEntityType(Q))return 0;try{return await A.entityService.countEntities({entityType:Q})}catch{return 0}}}import{jsxDEV as C1}from"preact/jsx-dev-runtime";var p7Q=W.object({label:W.string(),href:W.string()}),aZ8=W.object({label:W.string(),value:W.string(),note:W.string()}),tZ8=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:p7Q,secondaryCta:p7Q,signals:W.array(aZ8)}),eZ8=W.object({phase:W.string(),title:W.string(),text:W.string()}),AW8=W.object({eyebrow:W.string(),title:W.string(),intro:W.string(),steps:W.array(eZ8)}),QW8=W.object({label:W.string(),title:W.string(),text:W.string()}),$W8=W.object({title:W.string(),intro:W.string(),cards:W.array(QW8)}),wW8=W.object({title:W.string(),intro:W.string(),points:W.array(W.string())}),BW8={title:"Relay is a collaborative team-memory brain.",intro:"It exists for teams that need to remember together: capturing what happened, summarizing why it matters, and coordinating with trusted peer brains when work crosses boundaries.",points:["Not a personal blog engine or portfolio shell.","Not a marketing automation stack.","A small public face for a larger private knowledge workflow."]},XW8="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function l7Q({href:A,label:Q}){return C1("a",{href:A,className:XW8,children:Q},void 0,!1,void 0,this)}function YW8({siteInfo:A,children:Q}){let $=[...A.navigation.primary,...A.navigation.secondary],w=A.cta??{buttonText:"Start here",buttonLink:"/about"};return C1(GPA,{children:[C1("nav",{className:"fixed left-0 right-0 top-0 z-[100] flex items-center justify-between border-b border-theme-light bg-nav-fade px-6 py-4 backdrop-blur-[12px] md:px-10 xl:px-20",children:[C1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[C1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),C1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),C1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex items-center gap-5 md:gap-8",children:[C1("div",{className:"hidden items-center gap-6 md:flex",children:$.map((B)=>C1(l7Q,{...B},`${B.href}-${B.label}`,!1,void 0,this))},void 0,!1,void 0,this),C1("a",{href:w.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:w.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("main",{children:Q},void 0,!1,void 0,this),C1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:C1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[C1("div",{children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),C1("p",{className:"mt-2 max-w-[560px] font-body text-body-xs text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex flex-wrap items-center gap-5",children:[$.map((B)=>C1(l7Q,{...B},`footer-${B.href}-${B.label}`,!1,void 0,this)),C1("button",{id:"themeToggle","aria-label":"Toggle light mode",className:"rounded-md border border-theme-light bg-transparent px-2.5 py-1.5 font-body text-label-md text-theme-light transition-colors hover:border-theme hover:text-theme",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var ZW8=({sections:A,siteInfo:Q})=>C1(YW8,{siteInfo:Q,children:A},void 0,!1,void 0,this);function WW8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,signals:X}){return C1(go,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:C1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[C1("div",{children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),C1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:$},void 0,!1,void 0,this),C1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[C1(h70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(h70,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"rounded-[32px] border border-card-relay-border bg-card-relay-bg p-5 shadow-[0_24px_90px_var(--color-glow-relay)] backdrop-blur-sm",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),C1("div",{className:"mt-5 grid gap-3",children:X.map((Y)=>C1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[C1("div",{className:"flex items-center justify-between gap-4",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),C1("span",{className:"h-2 w-2 rounded-full bg-accent shadow-[0_0_22px_var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:Y.note},void 0,!1,void 0,this)]},Y.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function HW8({eyebrow:A,title:Q,intro:$,steps:w}){return C1(go,{id:"operating-loop",className:"py-section",children:[C1("div",{className:"max-w-[840px]",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),C1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>C1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[C1("p",{className:"font-label text-label-sm text-accent",children:B.phase},void 0,!1,void 0,this),C1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:B.title},void 0,!1,void 0,this),C1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function KW8({title:A,intro:Q,cards:$}){return C1(go,{className:"py-section",children:C1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:C1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[C1("div",{children:[C1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),C1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"grid gap-4",children:$.map((w)=>C1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:w.label},void 0,!1,void 0,this),C1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:w.title},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:w.text},void 0,!1,void 0,this)]},w.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function UW8({title:A,intro:Q,points:$}){return C1(go,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[C1("div",{className:"max-w-[920px]",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),C1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),C1("p",{className:"mt-7 font-body text-body-lg text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:$.map((w)=>C1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:w},w,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var GW8=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},DW8=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),z40=(A,Q,$=`${Q}s`)=>`${DW8(A)} ${A===1?Q:$}`;function qW8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:H,counts:K}){let U=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:z40(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:z40(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:z40(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:z40(K.summaries,"summary","summaries")}];return C1(go,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[C1("div",{className:"mx-auto max-w-[1040px] text-center",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),C1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:$},void 0,!1,void 0,this),C1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[C1(h70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(h70,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mx-auto mt-20 max-w-[1020px] rounded-[32px] border border-theme-light bg-[radial-gradient(circle_at_1px_1px,rgb(255_255_255_/_0.05)_1px,transparent_0),linear-gradient(180deg,rgb(255_255_255_/_0.02),transparent)] bg-[length:24px_24px,100%_100%] px-6 py-14",children:[C1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[C1("div",{className:"flex flex-col gap-3.5",children:X.map((G)=>C1("div",{className:"rounded-2xl border border-card-panel-border border-l-2 border-l-accent bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),C1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),C1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this),C1("div",{className:"relative mx-auto grid aspect-square w-full max-w-[320px] place-items-center rounded-full bg-[radial-gradient(circle_at_center,rgb(232_119_34_/_0.25),transparent_65%)]",children:[C1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),C1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),U.map((G)=>C1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${G.className}`,children:G.label},G.key,!1,void 0,this)),C1("div",{className:"relative z-[1] px-6 text-center",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Z.eyebrow},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Z.name},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Z.sub},void 0,!1,void 0,this),C1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[z40(K.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex flex-col gap-3.5",children:Y.map((G)=>C1("div",{className:"rounded-2xl border border-card-panel-border border-r-2 border-r-secondary bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),C1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),C1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((G)=>C1("div",{className:"text-left",children:[C1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[C1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${GW8(G.tone)}`},void 0,!1,void 0,this),G.title]},void 0,!0,void 0,this),C1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:G.text},void 0,!1,void 0,this)]},G.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var zW8=G2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:gjA,formatter:{parse:(A)=>gjA.parse({...vR0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>c7Q(to.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:qW8}}),VW8=(A)=>WW8(tZ8.parse(A)),JW8=(A)=>HW8(AW8.parse(A)),FW8=(A)=>KW8($W8.parse(A)),LW8=(A)=>UW8(wW8.parse(A)),i7Q={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},d7Q={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:VW8,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...i7Q,label:"Primary CTA"},secondaryCta:{...i7Q,label:"Secondary CTA"},signals:{type:"array",label:"Signals",minItems:1,items:{type:"object",label:"Signal",fields:{label:{type:"string",label:"Label"},value:{type:"string",label:"Value"},note:{type:"string",label:"Note"}}}}}},"home-loop":{title:"Home operating loop",description:"Relay capture, synthesis, and sharing loop",layout:JW8,fields:{eyebrow:{type:"string",label:"Eyebrow"},title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},steps:{type:"array",label:"Steps",minItems:1,items:{type:"object",label:"Step",fields:{phase:{type:"string",label:"Phase"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},"home-surface":{title:"Home surface",description:"Relay default template explanation cards",layout:FW8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},cards:{type:"array",label:"Cards",minItems:1,items:{type:"object",label:"Card",fields:{label:{type:"string",label:"Label"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},about:{title:"About Relay",description:"Default Relay about page",layout:LW8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},IW8=[{id:"home",path:"/",title:"Relay",description:"Collaborative team memory and synthesis brain",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"diagram",template:"relay-site:home-diagram"}]},{id:"about",path:"/about",title:"About Relay",description:"What Relay is designed to do",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:20},sections:[{id:"about",template:"relay-site:about",content:BW8}]}],n7Q=o9Q({packageName:"@brains/relay/site",themeProfile:"studio",layout:ZW8,routes:IW8,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":zW8},dataSources:[new SjA]}});var r7Q={name:"@brains/relay",version:"0.2.0-alpha.195",description:"Relay brain model \u2014 collaborative knowledge management",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/auth-service":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-info":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@rizom/site-rizom":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},files:["src","brain.eval.yaml","env.schema.template"],private:!0,scripts:{"build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms",eval:"brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:ui && cd test-apps/core && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:default":"bun run build:ui && cd test-apps/default && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:docs":"bun run build:ui && cd test-apps/docs && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:full":"bun run build:ui && cd test-apps/full && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var o7Q=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],s7Q=[...o7Q,"image","site-info","site-content","site-builder"],PW8=[...s7Q,"docs","decks"],bW8=["Relay is a collaborative team-memory and synthesis brain. Optimize for capturing shared context, finding what the team already knows, summarizing cross-source evidence, and coordinating with peer brains.","Relay is not Rover-for-teams: do not default to personal branding, blog publishing, newsletters, social media, portfolio, or marketing workflows unless the installed plugins and user request explicitly support them."],jW8=gk({name:"relay",version:r7Q.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:n7Q,theme:uo,presets:{core:o7Q,default:s7Q,full:PW8},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:bW8,capabilities:[["prompt",ny,void 0],["note",fy,{}],["link",Ry,{}],["image",FQ0,void 0],["topics",hO0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",TjA,{memoryVisibility:"shared"}],["docs",Y90,void 0],["decks",w90,void 0],["agents",df0,void 0],["assessment",$x0,void 0],["auth-service",W$0,void 0],["notifications",Kf0,void 0],["email-resend",Jb0,void 0],["cms",gy,{}],["dashboard",Fx,void 0],["directory-sync",RT,{seedContent:!0,seedContentPath:_W8(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Vy,{definitions:d7Q}],["rizom-ecosystem",ry,void 0],["site-info",Jy,void 0],["site-builder",zy,{}]],interfaces:[["mcp",PO,()=>({})],["discord",Wf,()=>({captureUrls:!0})],["a2a",Hn,()=>({})],["webserver",Lf,()=>({})],["web-chat",Wn,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"anchor"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{note:{create:"trusted",update:"trusted",delete:"anchor"},link:{create:"trusted",update:"trusted",delete:"anchor"},doc:{create:"trusted",update:"trusted",delete:"anchor"},deck:{create:"trusted",update:"trusted",delete:"anchor"},decision:{create:"trusted",update:"trusted",delete:"anchor"},"action-item":{create:"trusted",update:"trusted",delete:"anchor"},image:{create:"trusted",update:"trusted",delete:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"}}}),a7Q=jW8;import{readFileSync as YG8}from"fs";import{join as ZG8}from"path";import{execSync as WG8}from"child_process";import{parseArgs as OW8}from"util";var fW8={model:{type:"string"},domain:{type:"string"},"content-repo":{type:"string"},backend:{type:"string"},"push-to":{type:"string"},"ai-api-key":{type:"string"},"no-interactive":{type:"boolean"},preview:{type:"boolean"},deploy:{type:"boolean"},regen:{type:"boolean"},all:{type:"boolean"},only:{type:"string"},"dry-run":{type:"boolean"},"startup-check":{type:"boolean"},"storage-dir":{type:"string"},yes:{type:"boolean"},remote:{type:"string"},token:{type:"string"},outputDir:{type:"string"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}};function AJ(A,Q){let $=A[Q];return typeof $==="string"?$:void 0}function Cx(A,Q){let $=A[Q];return typeof $==="boolean"?$:void 0}function t7Q(A){let{values:Q,positionals:$}=OW8({args:A,options:fW8,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:$[0]??"help",args:$.slice(1),flags:{model:AJ(Q,"model"),domain:AJ(Q,"domain"),"content-repo":AJ(Q,"content-repo"),backend:AJ(Q,"backend"),"push-to":AJ(Q,"push-to"),"ai-api-key":AJ(Q,"ai-api-key"),"no-interactive":Cx(Q,"no-interactive"),preview:Cx(Q,"preview"),deploy:Cx(Q,"deploy"),regen:Cx(Q,"regen"),all:Cx(Q,"all"),only:AJ(Q,"only"),"dry-run":Cx(Q,"dry-run"),"startup-check":Cx(Q,"startup-check"),"storage-dir":AJ(Q,"storage-dir"),yes:Cx(Q,"yes"),remote:AJ(Q,"remote"),token:AJ(Q,"token"),outputDir:AJ(Q,"outputDir")}}}V40();import{mkdirSync as sU8}from"fs";import{join as aU8}from"path";import{execSync as tU8}from"child_process";var hR0={name:"@rizom/brain",version:"0.2.0-alpha.195",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};import{mkdirSync as D4Q,writeFileSync as F40,chmodSync as L40,existsSync as ojA,readFileSync as sjA}from"fs";import{basename as ajA,dirname as tjA,join as pB,resolve as HH8}from"path";import{fileURLToPath as KH8}from"url";var e7Q=`ARG BUN_VERSION=1.3.10
14822
+ `)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=EZ8.parse(B),Y=vjA(X.messages,X.conversationId),Z=X.existingSummary?R7Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null;return new Rx(Q,$,w).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=CZ8.parse(B),Y=X.memory?v7Q(Q,X.memory):Q;return new ao(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=hZ8.parse(B),Y=X.memory?v7Q(Q,X.memory):Q;return xR0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=xZ8.parse(B),Y=vjA(X.messages,X.conversationId),Z=TZ8({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?R7Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null,K=[],U=[],G=yZ8({context:Q,conversation:Z,messages:Y,existing:H,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new Rx(G,$,w).projectConversation(X.conversationId),summaries:K.filter((J)=>J.entityType==="summary"),decisions:K.filter((J)=>J.entityType==="decision"),actionItems:K.filter((J)=>J.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=fZ8.parse(B);return new Rx(Q,$,w).projectConversation(X.conversationId)})}function R7Q(A){return{id:A.conversationId,entityType:"summary",content:A.content,contentHash:"eval-existing-summary",visibility:A.visibility,created:"2026-01-01T00:00:00.000Z",updated:"2026-01-01T00:00:00.000Z",metadata:{conversationId:A.conversationId,channelId:"eval-channel",interfaceType:"eval",messageCount:A.messageCount,entryCount:1,sourceHash:"eval-source-hash",projectionVersion:A.projectionVersion}}}function vjA(A,Q){return A.map(($,w)=>{let B=$.timestamp??new Date(Date.UTC(2026,0,1,0,w)).toISOString();return{id:`eval-message-${w+1}`,conversationId:Q,role:$.role,content:$.content,timestamp:B,metadata:{...$.actor?{actor:$.actor}:{},...$.source?{source:$.source}:{}}}})}function TZ8(A){let Q=A.messages[0],$=A.messages[A.messages.length-1],w=Q?.timestamp??"2026-01-01T00:00:00.000Z",B=$?.timestamp??w;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:w,lastActiveAt:B,createdAt:w,updatedAt:B,metadata:{}}}function yZ8(A){let Q=eV(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:$})=>$==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async($)=>{return A.deleted.push($),!0},upsertEntity:async({entity:$})=>{return A.upserted.push($),{entityId:$.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function v7Q(A,Q){let $=Q.map(gZ8),w=$.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??so(B)}));return{...A,entityService:{...A.entityService,search:async()=>w,listEntities:async({entityType:B})=>$.filter((X)=>X.entityType===B)}}}function gZ8(A){if(A.entityType==="summary")return SZ8(A);if(A.entityType==="decision")return mZ8(A);return uZ8(A)}function hjA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:u6(A.content),visibility:A.visibility,created:Q,updated:Q}}function SZ8(A){return{...hjA(A),entityType:"summary",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,messageCount:3,entryCount:1,sourceHash:`source-${A.id}`,projectionVersion:1,...A.participants?{participants:A.participants}:{}}}}function mZ8(A){return{...hjA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:eV(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:A.status==="superseded"?"superseded":"active",...A.decidedBy?{decidedBy:A.decidedBy}:{},...A.mentionedBy?{mentionedBy:A.mentionedBy}:{}}}}function uZ8(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...hjA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:eV(A),timeRange:{start:"2026-01-01T00:00:00.000Z",end:"2026-01-01T00:01:00.000Z"},sourceSummaryId:A.conversationId,sourceMessageCount:2,projectionVersion:1,status:Q,...A.assignedTo?{assignedTo:A.assignedTo}:{},...A.requestedBy?{requestedBy:A.requestedBy}:{}}}}var y7Q={name:"@brains/conversation-memory",version:"0.2.0-alpha.196",description:"Plugin for deriving durable conversation memory",dependencies:{"@brains/content-formatters":"workspace:*","@brains/contracts":"workspace:*","@brains/conversation-service":"workspace:*","@brains/dashboard":"workspace:*","@brains/plugins":"workspace:*","@brains/templates":"workspace:*","@brains/ui-library":"workspace:*","@brains/utils":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/node":"^20.19.43",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},main:"./src/index.ts",private:!0,scripts:{eval:"cd evals && bun run brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var pZ8=new vz,lZ8=new po,iZ8=new lo,dZ8=W.object({conversationId:W.string()});class EjA extends c6{entityType=u9;schema=K40;adapter=pZ8;constructor(A={}){super(LR0,y7Q,A,kjA)}getConfig(){return this.config}getTemplates(){return{"summary-list":W7Q,"summary-detail":H7Q,"ai-response":K7Q}}getDataSources(){return[new xjA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:u9,job:{type:t9Q,handler:new jR0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await OC(A,u9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:PjA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:LR0}}},sourceChange:{sourceKind:DA0,sourceTypes:[DA0],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[iu],jobData:(Q)=>{let{conversationId:$}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:$,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:$}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:PjA,deduplication:"skip",deduplicationKey:`conversation-memory:${$}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${$}`,pluginId:LR0}}}}}]}parseConversationMessagePayload(A){return dZ8.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:$}=this.parseConversationMessagePayload(Q),w=await A.conversations.get($);if(!w)return!1;return Wg({conversation:w,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(FD,U40,lZ8),A.entities.register(Rz,G40,iZ8),D7Q({context:A,pluginId:this.id}),z7Q({context:A,pluginId:this.id}),b7Q({context:A,pluginId:this.id}),k7Q({context:A,pluginId:this.id,config:this.config}),RjA(A),T7Q({context:A,logger:this.logger,config:this.config})}}function TjA(A={}){return new EjA(A)}zA();h0();h0();e9();var g7Q=W.object({label:W.string(),href:W.string()}),S7Q=W.object({label:W.string(),title:W.string(),detail:W.string()}),nZ8=W.object({eyebrow:W.string(),name:W.string(),sub:W.string()}),rZ8=W.object({tone:W.enum(["capture","synthesis","share"]),title:W.string(),text:W.string()}),yjA=W.object({captures:W.number(),links:W.number(),topics:W.number(),summaries:W.number(),peers:W.number()}),to=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:g7Q,secondaryCta:g7Q,inputs:W.array(S7Q).min(1),outputs:W.array(S7Q).min(1),core:nZ8,legend:W.array(rZ8).min(1)}),gjA=to.extend({counts:yjA}),m7Q={eyebrow:"A team brain, diagrammed",headline:"Relay sits between the work and the world, and keeps both honest.",intro:"Capture sources flow into a shared brain; the brain organizes, summarizes, and \u2014 selectively \u2014 exposes a public surface. Everything else stays private and operational.",primaryCta:{label:"See it on a real team",href:"#diagram"},secondaryCta:{label:"Read the model",href:"/about"},inputs:[{label:"Source \xB7 chat",title:"Discord",detail:"Shared decisions and field notes captured in flow."},{label:"Source \xB7 agent",title:"MCP / CLI",detail:"Structured captures from tools and assistants."},{label:"Source \xB7 web",title:"Links & docs",detail:"External material indexed with sourceable metadata."}],outputs:[{label:"Surface \xB7 public",title:"Default site",detail:"A small, durable face onto what the team currently knows."},{label:"Surface \xB7 agents",title:"A2A exchange",detail:"Peer brains coordinate over an approved, signed protocol."},{label:"Surface \xB7 query",title:"Team Q&A",detail:"Ask the brain in chat; answers cite the captures behind them."}],core:{eyebrow:"The relay",name:"brain",sub:"capture \u2192 topics \u2192 summaries"},legend:[{tone:"capture",title:"Capture",text:"Anything the team already does that produces a trace \u2014 chat messages, links, deploys, decisions."},{tone:"synthesis",title:"Synthesis",text:"The work the brain does on its own time \u2014 clustering captures into topics, summaries, and durable memory."},{tone:"share",title:"Share",text:"A small, opinionated public surface and an approved agent-to-agent protocol. Most memory stays private."}]},u7Q=new n$(to,{title:"Home diagram",mappings:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"headline",label:"Headline",type:"string"},{key:"intro",label:"Intro",type:"string"},{key:"primaryCta",label:"Primary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"secondaryCta",label:"Secondary CTA",type:"object",children:[{key:"label",label:"Label",type:"string"},{key:"href",label:"Href",type:"string"}]},{key:"inputs",label:"Inputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"outputs",label:"Outputs",type:"array",itemType:"object",itemMappings:[{key:"label",label:"Label",type:"string"},{key:"title",label:"Title",type:"string"},{key:"detail",label:"Detail",type:"string"}]},{key:"core",label:"Core",type:"object",children:[{key:"eyebrow",label:"Eyebrow",type:"string"},{key:"name",label:"Name",type:"string"},{key:"sub",label:"Sub",type:"string"}]},{key:"legend",label:"Legend",type:"array",itemType:"object",itemMappings:[{key:"tone",label:"Tone",type:"string"},{key:"title",label:"Title",type:"string"},{key:"text",label:"Text",type:"string"}]}]});function vR0(A){return u7Q.parse(A)}function c7Q(A){return u7Q.format(A)}h0();var oZ8=W.looseObject({query:W.object({routeId:W.string().default("home"),sectionId:W.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),sZ8={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class SjA{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,$){let w=oZ8.parse(A??{}),B=await this.fetchContent($,w.query.routeId,w.query.sectionId),X=await this.fetchCounts($);return Q.parse({...B,counts:X})}async fetchContent(A,Q,$){let w=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${$}`});if(!w?.content)return m7Q;return to.parse(vR0(w.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(sZ8).map(async([$,w])=>[$,await this.countOrZero(A,w)]));return yjA.parse(Object.fromEntries(Q))}async countOrZero(A,Q){if(!A.entityService.hasEntityType(Q))return 0;try{return await A.entityService.countEntities({entityType:Q})}catch{return 0}}}import{jsxDEV as C1}from"preact/jsx-dev-runtime";var p7Q=W.object({label:W.string(),href:W.string()}),aZ8=W.object({label:W.string(),value:W.string(),note:W.string()}),tZ8=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:p7Q,secondaryCta:p7Q,signals:W.array(aZ8)}),eZ8=W.object({phase:W.string(),title:W.string(),text:W.string()}),AW8=W.object({eyebrow:W.string(),title:W.string(),intro:W.string(),steps:W.array(eZ8)}),QW8=W.object({label:W.string(),title:W.string(),text:W.string()}),$W8=W.object({title:W.string(),intro:W.string(),cards:W.array(QW8)}),wW8=W.object({title:W.string(),intro:W.string(),points:W.array(W.string())}),BW8={title:"Relay is a collaborative team-memory brain.",intro:"It exists for teams that need to remember together: capturing what happened, summarizing why it matters, and coordinating with trusted peer brains when work crosses boundaries.",points:["Not a personal blog engine or portfolio shell.","Not a marketing automation stack.","A small public face for a larger private knowledge workflow."]},XW8="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function l7Q({href:A,label:Q}){return C1("a",{href:A,className:XW8,children:Q},void 0,!1,void 0,this)}function YW8({siteInfo:A,children:Q}){let $=[...A.navigation.primary,...A.navigation.secondary],w=A.cta??{buttonText:"Start here",buttonLink:"/about"};return C1(GPA,{children:[C1("nav",{className:"fixed left-0 right-0 top-0 z-[100] flex items-center justify-between border-b border-theme-light bg-nav-fade px-6 py-4 backdrop-blur-[12px] md:px-10 xl:px-20",children:[C1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[C1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),C1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),C1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex items-center gap-5 md:gap-8",children:[C1("div",{className:"hidden items-center gap-6 md:flex",children:$.map((B)=>C1(l7Q,{...B},`${B.href}-${B.label}`,!1,void 0,this))},void 0,!1,void 0,this),C1("a",{href:w.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:w.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("main",{children:Q},void 0,!1,void 0,this),C1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:C1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[C1("div",{children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),C1("p",{className:"mt-2 max-w-[560px] font-body text-body-xs text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex flex-wrap items-center gap-5",children:[$.map((B)=>C1(l7Q,{...B},`footer-${B.href}-${B.label}`,!1,void 0,this)),C1("button",{id:"themeToggle","aria-label":"Toggle light mode",className:"rounded-md border border-theme-light bg-transparent px-2.5 py-1.5 font-body text-label-md text-theme-light transition-colors hover:border-theme hover:text-theme",children:"\u2600 Light"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var ZW8=({sections:A,siteInfo:Q})=>C1(YW8,{siteInfo:Q,children:A},void 0,!1,void 0,this);function WW8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,signals:X}){return C1(go,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:C1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[C1("div",{children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),C1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:$},void 0,!1,void 0,this),C1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[C1(h70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(h70,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"rounded-[32px] border border-card-relay-border bg-card-relay-bg p-5 shadow-[0_24px_90px_var(--color-glow-relay)] backdrop-blur-sm",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),C1("div",{className:"mt-5 grid gap-3",children:X.map((Y)=>C1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[C1("div",{className:"flex items-center justify-between gap-4",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),C1("span",{className:"h-2 w-2 rounded-full bg-accent shadow-[0_0_22px_var(--color-accent)]"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-body-xs text-theme-muted",children:Y.note},void 0,!1,void 0,this)]},Y.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function HW8({eyebrow:A,title:Q,intro:$,steps:w}){return C1(go,{id:"operating-loop",className:"py-section",children:[C1("div",{className:"max-w-[840px]",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),C1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>C1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[C1("p",{className:"font-label text-label-sm text-accent",children:B.phase},void 0,!1,void 0,this),C1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:B.title},void 0,!1,void 0,this),C1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function KW8({title:A,intro:Q,cards:$}){return C1(go,{className:"py-section",children:C1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:C1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[C1("div",{children:[C1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),C1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"grid gap-4",children:$.map((w)=>C1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[C1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:w.label},void 0,!1,void 0,this),C1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:w.title},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:w.text},void 0,!1,void 0,this)]},w.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function UW8({title:A,intro:Q,points:$}){return C1(go,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[C1("div",{className:"max-w-[920px]",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),C1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),C1("p",{className:"mt-7 font-body text-body-lg text-theme-muted",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:$.map((w)=>C1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:w},w,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var GW8=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},DW8=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),z40=(A,Q,$=`${Q}s`)=>`${DW8(A)} ${A===1?Q:$}`;function qW8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:H,counts:K}){let U=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:z40(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:z40(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:z40(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:z40(K.summaries,"summary","summaries")}];return C1(go,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[C1("div",{className:"mx-auto max-w-[1040px] text-center",children:[C1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),C1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),C1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:$},void 0,!1,void 0,this),C1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[C1(h70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(h70,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mx-auto mt-20 max-w-[1020px] rounded-[32px] border border-theme-light bg-[radial-gradient(circle_at_1px_1px,rgb(255_255_255_/_0.05)_1px,transparent_0),linear-gradient(180deg,rgb(255_255_255_/_0.02),transparent)] bg-[length:24px_24px,100%_100%] px-6 py-14",children:[C1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[C1("div",{className:"flex flex-col gap-3.5",children:X.map((G)=>C1("div",{className:"rounded-2xl border border-card-panel-border border-l-2 border-l-accent bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),C1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),C1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this),C1("div",{className:"relative mx-auto grid aspect-square w-full max-w-[320px] place-items-center rounded-full bg-[radial-gradient(circle_at_center,rgb(232_119_34_/_0.25),transparent_65%)]",children:[C1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),C1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),U.map((G)=>C1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${G.className}`,children:G.label},G.key,!1,void 0,this)),C1("div",{className:"relative z-[1] px-6 text-center",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Z.eyebrow},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Z.name},void 0,!1,void 0,this),C1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Z.sub},void 0,!1,void 0,this),C1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[z40(K.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"flex flex-col gap-3.5",children:Y.map((G)=>C1("div",{className:"rounded-2xl border border-card-panel-border border-r-2 border-r-secondary bg-card-panel-bg px-4 py-4 text-left backdrop-blur-sm",children:[C1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),C1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),C1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((G)=>C1("div",{className:"text-left",children:[C1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[C1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${GW8(G.tone)}`},void 0,!1,void 0,this),G.title]},void 0,!0,void 0,this),C1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:G.text},void 0,!1,void 0,this)]},G.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var zW8=G2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:gjA,formatter:{parse:(A)=>gjA.parse({...vR0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>c7Q(to.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:qW8}}),VW8=(A)=>WW8(tZ8.parse(A)),JW8=(A)=>HW8(AW8.parse(A)),FW8=(A)=>KW8($W8.parse(A)),LW8=(A)=>UW8(wW8.parse(A)),i7Q={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},d7Q={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:VW8,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...i7Q,label:"Primary CTA"},secondaryCta:{...i7Q,label:"Secondary CTA"},signals:{type:"array",label:"Signals",minItems:1,items:{type:"object",label:"Signal",fields:{label:{type:"string",label:"Label"},value:{type:"string",label:"Value"},note:{type:"string",label:"Note"}}}}}},"home-loop":{title:"Home operating loop",description:"Relay capture, synthesis, and sharing loop",layout:JW8,fields:{eyebrow:{type:"string",label:"Eyebrow"},title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},steps:{type:"array",label:"Steps",minItems:1,items:{type:"object",label:"Step",fields:{phase:{type:"string",label:"Phase"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},"home-surface":{title:"Home surface",description:"Relay default template explanation cards",layout:FW8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},cards:{type:"array",label:"Cards",minItems:1,items:{type:"object",label:"Card",fields:{label:{type:"string",label:"Label"},title:{type:"string",label:"Title"},text:{type:"string",label:"Text"}}}}}},about:{title:"About Relay",description:"Default Relay about page",layout:LW8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},IW8=[{id:"home",path:"/",title:"Relay",description:"Collaborative team memory and synthesis brain",layout:"default",navigation:{show:!0,label:"Home",slot:"secondary",priority:10},sections:[{id:"diagram",template:"relay-site:home-diagram"}]},{id:"about",path:"/about",title:"About Relay",description:"What Relay is designed to do",layout:"default",navigation:{show:!0,label:"About",slot:"primary",priority:20},sections:[{id:"about",template:"relay-site:about",content:BW8}]}],n7Q=o9Q({packageName:"@brains/relay/site",themeProfile:"studio",layout:ZW8,routes:IW8,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":zW8},dataSources:[new SjA]}});var r7Q={name:"@brains/relay",version:"0.2.0-alpha.196",description:"Relay brain model \u2014 collaborative knowledge management",dependencies:{"@brains/a2a":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/auth-service":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/directory-sync":"workspace:*","@brains/discord":"workspace:*","@brains/doc":"workspace:*","@brains/email-resend":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-info":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@rizom/site-rizom":"workspace:*",preact:"^10.27.2"},devDependencies:{"@brains/ai-evaluation":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*",typescript:"^7.0.2"},exports:{".":"./src/index.ts","./env-schema":"./src/env-schema.ts"},files:["src","brain.eval.yaml","env.schema.template"],private:!0,scripts:{"build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms",eval:"brain-eval",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix","start:core":"bun run build:ui && cd test-apps/core && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:default":"bun run build:ui && cd test-apps/default && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:docs":"bun run build:ui && cd test-apps/docs && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:full":"bun run build:ui && cd test-apps/full && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var o7Q=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],s7Q=[...o7Q,"image","site-info","site-content","site-builder"],PW8=[...s7Q,"docs","decks"],bW8=["Relay is a collaborative team-memory and synthesis brain. Optimize for capturing shared context, finding what the team already knows, summarizing cross-source evidence, and coordinating with peer brains.","Relay is not Rover-for-teams: do not default to personal branding, blog publishing, newsletters, social media, portfolio, or marketing workflows unless the installed plugins and user request explicitly support them."],jW8=gk({name:"relay",version:r7Q.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:n7Q,theme:uo,presets:{core:o7Q,default:s7Q,full:PW8},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:bW8,capabilities:[["prompt",ny,void 0],["note",fy,{}],["link",Ry,{}],["image",FQ0,void 0],["topics",hO0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",TjA,{memoryVisibility:"shared"}],["docs",Y90,void 0],["decks",w90,void 0],["agents",df0,void 0],["assessment",$x0,void 0],["auth-service",W$0,void 0],["notifications",Kf0,void 0],["email-resend",Jb0,void 0],["cms",gy,{}],["dashboard",Fx,void 0],["directory-sync",RT,{seedContent:!0,seedContentPath:_W8(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Vy,{definitions:d7Q}],["rizom-ecosystem",ry,void 0],["site-info",Jy,void 0],["site-builder",zy,{}]],interfaces:[["mcp",PO,()=>({})],["discord",Wf,()=>({captureUrls:!0})],["a2a",Hn,()=>({})],["webserver",Lf,()=>({})],["web-chat",Wn,()=>({})]],permissions:{rules:[{pattern:"cli:*",level:"anchor"},{pattern:"mcp:stdio",level:"anchor"},{pattern:"mcp:http",level:"anchor"},{pattern:"discord:*",level:"public"},{pattern:"web-chat:*",level:"anchor"}],entityActions:{note:{create:"trusted",update:"trusted",delete:"anchor"},link:{create:"trusted",update:"trusted",delete:"anchor"},doc:{create:"trusted",update:"trusted",delete:"anchor"},deck:{create:"trusted",update:"trusted",delete:"anchor"},decision:{create:"trusted",update:"trusted",delete:"anchor"},"action-item":{create:"trusted",update:"trusted",delete:"anchor"},image:{create:"trusted",update:"trusted",delete:"anchor"}}},deployment:{cdn:{enabled:!0,provider:"bunny"}}}),a7Q=jW8;import{readFileSync as YG8}from"fs";import{join as ZG8}from"path";import{execSync as WG8}from"child_process";import{parseArgs as OW8}from"util";var fW8={model:{type:"string"},domain:{type:"string"},"content-repo":{type:"string"},backend:{type:"string"},"push-to":{type:"string"},"ai-api-key":{type:"string"},"no-interactive":{type:"boolean"},preview:{type:"boolean"},deploy:{type:"boolean"},regen:{type:"boolean"},all:{type:"boolean"},only:{type:"string"},"dry-run":{type:"boolean"},"startup-check":{type:"boolean"},"storage-dir":{type:"string"},yes:{type:"boolean"},remote:{type:"string"},token:{type:"string"},outputDir:{type:"string"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}};function AJ(A,Q){let $=A[Q];return typeof $==="string"?$:void 0}function Cx(A,Q){let $=A[Q];return typeof $==="boolean"?$:void 0}function t7Q(A){let{values:Q,positionals:$}=OW8({args:A,options:fW8,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:$[0]??"help",args:$.slice(1),flags:{model:AJ(Q,"model"),domain:AJ(Q,"domain"),"content-repo":AJ(Q,"content-repo"),backend:AJ(Q,"backend"),"push-to":AJ(Q,"push-to"),"ai-api-key":AJ(Q,"ai-api-key"),"no-interactive":Cx(Q,"no-interactive"),preview:Cx(Q,"preview"),deploy:Cx(Q,"deploy"),regen:Cx(Q,"regen"),all:Cx(Q,"all"),only:AJ(Q,"only"),"dry-run":Cx(Q,"dry-run"),"startup-check":Cx(Q,"startup-check"),"storage-dir":AJ(Q,"storage-dir"),yes:Cx(Q,"yes"),remote:AJ(Q,"remote"),token:AJ(Q,"token"),outputDir:AJ(Q,"outputDir")}}}V40();import{mkdirSync as sU8}from"fs";import{join as aU8}from"path";import{execSync as tU8}from"child_process";var hR0={name:"@rizom/brain",version:"0.2.0-alpha.196",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"Apache-2.0",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",zod:"^4.1.8"},devDependencies:{"@brains/app":"workspace:*","@brains/build-tools":"workspace:*","@brains/content-formatters":"workspace:*","@brains/deploy-support":"workspace:*","@brains/eslint-config":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/ranger":"workspace:*","@brains/relay":"workspace:*","@brains/rover":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-default":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./themes":{types:"./dist/themes.d.ts",import:"./dist/themes.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","dev:start":"bun scripts/build.ts && bun dist/brain.js start",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};import{mkdirSync as D4Q,writeFileSync as F40,chmodSync as L40,existsSync as ojA,readFileSync as sjA}from"fs";import{basename as ajA,dirname as tjA,join as pB,resolve as HH8}from"path";import{fileURLToPath as KH8}from"url";var e7Q=`ARG BUN_VERSION=1.3.10
14823
14823
  FROM oven/bun:\${BUN_VERSION}-slim AS runtime
14824
14824
 
14825
14825
  WORKDIR /app