@rizom/brain 0.2.0-alpha.204 → 0.2.0-alpha.206

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 QAA(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 _20=c(()=>{kD1();x4()});async function OD1(A,Q){let $=Q?.child("entity-migrate")??H6.getInstance().child("entity-migrate"),{db:w,client:B,url:X}=PD0(A);$.debug("Running entity database migrations...");try{await bD0(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 kk(w,{migrationsFolder:Z}),await jD0(B),$.debug("Entity database migrations completed successfully")}catch(Y){throw $.error("Entity database migration failed:",Y),Y}finally{B.close()}}var fD1=c(()=>{_20();Mo0();PX()});async function xD1(A,Q){let $=Q?.child("job-queue-migrate")??H6.getInstance().child("job-queue-migrate"),{db:w,client:B,url:X}=aW0(A);$.debug("Running job queue migrations...");try{await tW0(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 kk(w,{migrationsFolder:Z}),$.debug("Job queue migrations completed successfully")}catch(Y){throw $.error("Job queue migration failed:",Y),Y}finally{B.close()}}var RD1=c(()=>{_20();mc0();PX()});async function vD1(A,Q){let $=Q?.child("conversation-migrate")??H6.getInstance().child("conversation-migrate"),{db:w,client:B,url:X}=VC(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 kk(w,{migrationsFolder:Z}),$.debug("Conversation database migrations completed successfully")}catch(Y){throw $.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var CD1=c(()=>{_20();LD0();PX()});async function hD1(A,Q){let $=Q?.child("runtime-state-migrate")??H6.getInstance().child("runtime-state-migrate"),{db:w,client:B,url:X}=dz0(A);$.debug("Running runtime state migrations...");try{await nz0(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 kk(w,{migrationsFolder:Z}),$.debug("Runtime state migrations completed successfully")}catch(Y){throw $.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var ED1=c(()=>{_20();PX();IAA()});import{mkdir as sAA}from"fs/promises";function W30(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function H30(A=process.env){return zk(W30(A))}async function K30(A=process.env){let Q=W30(A);try{await sAA(Q.dataDir,{recursive:!0}),await sAA(Q.cacheDir,{recursive:!0}),await sAA(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 zk(Q)}var U30=c(()=>{Y30()});class P20{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>K30(),migrateEntities:OD1,migrateJobQueue:xD1,migrateConversations:vD1,migrateRuntimeState:hD1}}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 aAA=c(()=>{fD1();RD1();CD1();ED1();U30()});function e56(){return process.env[t56]}function TD1(){return e56()!=="production"}var t56="NODE_ENV";var G30;var tAA=c(()=>{v0();G30=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 gD1;var yD1=c(()=>{gD1={name:"@brains/chat-repl",version:"0.2.0-alpha.204",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((QB6,D30)=>{(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=s0,this.updater=I0||f0}function B(){}function X(e,z0,I0){this.props=e,this.context=z0,this.refs=s0,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 S: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 C0: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===C0)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 V(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 L(){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 F(e,z0,I0,M0,_0,t0){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:L}):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:t0}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function _(e,z0){return z0=F(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===C0&&(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 k(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),k(""+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 t0=typeof e;if(t0==="undefined"||t0==="boolean")e=null;var d0=!1;if(e===null)d0=!0;else switch(t0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch(e.$$typeof){case o:case t:d0=!0;break;case C0: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 JA=0;JA<e.length;JA++)M0=e[JA],t0=UA+v(M0,JA),d0+=O(M0,z0,I0,t0,_0);else if(JA=Q(e),typeof JA==="function")for(JA===e.entries&&(T0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),T0=!0),e=JA.call(e),JA=0;!(M0=e.next()).done;)M0=M0.value,t0=UA+v(M0,JA++),d0+=O(M0,z0,I0,t0,_0);else if(t0==="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 g(e,z0,I0){if(e==null)return e;var M0=[],_0=0;return O(e,M0,"","",function(t0){return z0.call(I0,t0,_0++)}),M0}function m(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 t0=e._ioInfo;t0!=null&&(t0.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 t0=e._ioInfo;t0!=null&&(t0.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 _20=c(()=>{kD1();x4()});async function OD1(A,Q){let $=Q?.child("entity-migrate")??H6.getInstance().child("entity-migrate"),{db:w,client:B,url:X}=PD0(A);$.debug("Running entity database migrations...");try{await bD0(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 kk(w,{migrationsFolder:Z}),await jD0(B),$.debug("Entity database migrations completed successfully")}catch(Y){throw $.error("Entity database migration failed:",Y),Y}finally{B.close()}}var fD1=c(()=>{_20();Mo0();PX()});async function xD1(A,Q){let $=Q?.child("job-queue-migrate")??H6.getInstance().child("job-queue-migrate"),{db:w,client:B,url:X}=aW0(A);$.debug("Running job queue migrations...");try{await tW0(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 kk(w,{migrationsFolder:Z}),$.debug("Job queue migrations completed successfully")}catch(Y){throw $.error("Job queue migration failed:",Y),Y}finally{B.close()}}var RD1=c(()=>{_20();mc0();PX()});async function vD1(A,Q){let $=Q?.child("conversation-migrate")??H6.getInstance().child("conversation-migrate"),{db:w,client:B,url:X}=VC(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 kk(w,{migrationsFolder:Z}),$.debug("Conversation database migrations completed successfully")}catch(Y){throw $.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var CD1=c(()=>{_20();LD0();PX()});async function hD1(A,Q){let $=Q?.child("runtime-state-migrate")??H6.getInstance().child("runtime-state-migrate"),{db:w,client:B,url:X}=dz0(A);$.debug("Running runtime state migrations...");try{await nz0(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 kk(w,{migrationsFolder:Z}),$.debug("Runtime state migrations completed successfully")}catch(Y){throw $.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var ED1=c(()=>{_20();PX();IAA()});import{mkdir as sAA}from"fs/promises";function W30(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function H30(A=process.env){return zk(W30(A))}async function K30(A=process.env){let Q=W30(A);try{await sAA(Q.dataDir,{recursive:!0}),await sAA(Q.cacheDir,{recursive:!0}),await sAA(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 zk(Q)}var U30=c(()=>{Y30()});class P20{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>K30(),migrateEntities:OD1,migrateJobQueue:xD1,migrateConversations:vD1,migrateRuntimeState:hD1}}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 aAA=c(()=>{fD1();RD1();CD1();ED1();U30()});function e56(){return process.env[t56]}function TD1(){return e56()!=="production"}var t56="NODE_ENV";var G30;var tAA=c(()=>{v0();G30=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 gD1;var yD1=c(()=>{gD1={name:"@brains/chat-repl",version:"0.2.0-alpha.206",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((QB6,D30)=>{(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=s0,this.updater=I0||f0}function B(){}function X(e,z0,I0){this.props=e,this.context=z0,this.refs=s0,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 S: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 C0: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===C0)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 V(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 L(){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 F(e,z0,I0,M0,_0,t0){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:L}):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:t0}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function _(e,z0){return z0=F(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===C0&&(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 k(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),k(""+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 t0=typeof e;if(t0==="undefined"||t0==="boolean")e=null;var d0=!1;if(e===null)d0=!0;else switch(t0){case"bigint":case"string":case"number":d0=!0;break;case"object":switch(e.$$typeof){case o:case t:d0=!0;break;case C0: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 JA=0;JA<e.length;JA++)M0=e[JA],t0=UA+v(M0,JA),d0+=O(M0,z0,I0,t0,_0);else if(JA=Q(e),typeof JA==="function")for(JA===e.entries&&(T0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),T0=!0),e=JA.call(e),JA=0;!(M0=e.next()).done;)M0=M0.value,t0=UA+v(M0,JA++),d0+=O(M0,z0,I0,t0,_0);else if(t0==="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 g(e,z0,I0){if(e==null)return e;var M0=[],_0=0;return O(e,M0,"","",function(t0){return z0.call(I0,t0,_0++)}),M0}function m(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 t0=e._ioInfo;t0!=null&&(t0.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 t0=e._ioInfo;t0!=null&&(t0.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}`,VW6);K=`${w.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:sA(_)})}}await this.reportProgress($,{progress:g6.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),V=DL1(G,D)+K,L;try{L=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:sA(_)}),r5.failure(_)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let F=KG.createImageEntity({dataUrl:L.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await YH({entityService:this.context.entityService,entity:{...F,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 fC(this.context.entityService,X,Y,this.logger);if(!_)return r5.failure(Error(`Target entity not found: ${X}/${Y}`));let j=Hh(_,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=sA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await PF({entityService:this.context.entityService,entityType:"image",id:H,error:U}),r5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}zA();v0();Kw();lZ();var LW6=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 NQA extends H8{context;constructor(A,Q){super(Q,{schema:LW6,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 r5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(w.type!=="image")return r5.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=KG.createImageEntity({dataUrl:uAA(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 YH({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=sA(w);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await PF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),r5.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 fC(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"?I20($,Q):Hh($,Q);await this.context.entities.update(B)}}zA();v0();Kw();lZ();p2();var wl={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function yJ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function gJ0(A){let Q=IW6(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 qL1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function IW6(A,Q){let $=A?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}var NW6=W.object({uploadId:W.string().min(1),imageId:W.string().min(1).optional(),title:W.string().optional()});class _QA extends H8{context;constructor(A,Q){super(A,{schema:NW6,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(wl).read(A.uploadId);if(!yJ0(w.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=gJ0({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=KG.createImageEntity({dataUrl:qL1(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 YH({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 PF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:sA(w)});return r5.failure(w)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var zL1={name:"@brains/image-plugin",version:"0.2.0-alpha.204",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 PW6="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",bW6=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 a3(A){let Q=A?.trim();if(!Q)return;return Q}function jW6(A){let Q=a3(A.prompt);if(Q)return Q;let $=a3(A.content);if($&&!IQA($))return $;return}function MW6(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return O1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function JL1(A){let Q=a3(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return O1(Q)}async function kW6(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 PQA(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 OW6(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 bQA extends c6{entityType=KG.entityType;schema=F20;adapter=KG;constructor(A={}){super("image",zL1,A,bW6)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,$){if(A.from?.kind===wl.refKind)return this.promoteUpload(A,$);let w=jW6(A),B=a3(A.targetEntityType),X=a3(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=a3(A.title)??Y,q=JL1({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 V=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:V,attachment:PQA(q)}}}}let H=await gZ($.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=EJ0(H.entity.content),U=JL1({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:PQA(U)}}}}async promoteUpload(A,Q){let $=A.from;if($?.kind!==wl.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w=$.id,B;try{B=await Q.uploads.scoped(wl).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!yJ0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=gJ0({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:OW6({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let $=a3(A.from.sourceEntityType),w=a3(A.from.sourceEntityId),B=a3(A.from.attachmentType);if(!$||!w||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await gZ(Q.entityService,$,w,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=a3(A.targetEntityType),Z=a3(A.targetEntityId),H;if(Y&&Z){let q=await gZ(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 kW6(Q,K),G=MW6(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:PQA(G,B)}}}}async createPendingImage(A,Q){let $=new Date().toISOString(),w=KG.createImageEntity({dataUrl:PW6,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 RC({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 TJ0(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 TJ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new NQA(A,this.logger)),A.jobs.registerHandler("upload-promote",new _QA(this.logger.child("UploadPromotionJobHandler"),A))}}function _Q0(A={}){return new bQA(A)}zA();import{StdioServerTransport as xW6}from"@modelcontextprotocol/sdk/server/stdio.js";v0();var fW6=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 VL1(){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 jQA(){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 SJ0(A){let Q=fW6.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 jQA()}class t3{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return t3.instance??=new t3(A),t3.instance}static resetInstance(){if(t3.instance)t3.instance.stop(),t3.instance=null}static createFresh(A){return new t3(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?SJ0(this.config.logger):VL1()}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 xW6,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 vW6,timingSafeEqual as CW6}from"crypto";import{WebStandardStreamableHTTPServerTransport as hW6}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as EW6}from"@modelcontextprotocol/sdk/types.js";v8();function RW6(A){return r0.async((Q)=>{let $=setTimeout(()=>Q(r0.void),A);return $.unref(),r0.sync(()=>clearTimeout($))})}class MQA{scope;fibers;activeSweeps=new Set;closePromise=null;closed=!1;constructor(A,Q,$={}){this.scope=r0.runSync(j2.make()),this.fibers=r0.runSync(j2.extend(CZ.make(),this.scope));let w=r0.flatMap(QH.currentTimeMillis,(Z)=>r0.tryPromise({try:()=>this.trackSweep(()=>Q(Z)),catch:(H)=>H}).pipe(r0.catchAll((H)=>r0.sync(()=>{$.onError?.(H)})))),B=Math.max(1,A),X=($.clock?r0.sleep(B):RW6(B)).pipe(r0.andThen(w),r0.forever),Y=$.clock?r0.withClock(X,$.clock):X;CZ.unsafeAdd(this.fibers,r0.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 r0.runPromiseExit(j2.close(this.scope,R2.void));if(await Promise.allSettled([...this.activeSweeps]),R2.isFailure(A))throw j$.squash(A.cause)}}v0();var TW6=1800000,yW6=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"},SW6=W.looseObject({code:W.string().optional()});function mW6(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 uF{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?SJ0(this.config.logger):jQA(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??TW6,!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 MQA(Math.min(this.sessionIdleTtlMs,yW6),(Q)=>this.evictIdleSessions(Q),{onError:(Q)=>{this.logger.error("Error sweeping idle MCP sessions:",Q)}})}static getInstance(A){return uF.instance??=new uF(A),uF.instance}static async resetInstance(){let A=uF.instance;uF.instance=null,await A?.stop()}static createFresh(A){return new uF(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:`${mW6(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries($).map(([B,X])=>`${B}="${uW6(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(!cW6(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(!$&&EW6(w))B=new hW6({sessionIdGenerator:()=>vW6(),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=SW6.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 uW6(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function cW6(A,Q){let $=Buffer.from(A),w=Buffer.from(Q);if($.length!==w.length)return!1;return CW6($,w)}import{randomUUID as oW6}from"crypto";import{chmod as pW6,mkdir as lW6,readFile as iW6,rename as FL1,writeFile as dW6}from"fs/promises";import{dirname as nW6}from"path";class DH{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 iW6(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 lW6(nW6(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await dW6(Q,`${JSON.stringify(A,null,2)}
1775
+ ${U}`,VW6);K=`${w.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:sA(_)})}}await this.reportProgress($,{progress:g6.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),V=DL1(G,D)+K,L;try{L=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:sA(_)}),r5.failure(_)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let F=KG.createImageEntity({dataUrl:L.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await YH({entityService:this.context.entityService,entity:{...F,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 fC(this.context.entityService,X,Y,this.logger);if(!_)return r5.failure(Error(`Target entity not found: ${X}/${Y}`));let j=Hh(_,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=sA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await PF({entityService:this.context.entityService,entityType:"image",id:H,error:U}),r5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}zA();v0();Kw();lZ();var LW6=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 NQA extends H8{context;constructor(A,Q){super(Q,{schema:LW6,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 r5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(w.type!=="image")return r5.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=KG.createImageEntity({dataUrl:uAA(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 YH({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=sA(w);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await PF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),r5.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 fC(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"?I20($,Q):Hh($,Q);await this.context.entities.update(B)}}zA();v0();Kw();lZ();p2();var wl={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function yJ0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function gJ0(A){let Q=IW6(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 qL1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function IW6(A,Q){let $=A?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}var NW6=W.object({uploadId:W.string().min(1),imageId:W.string().min(1).optional(),title:W.string().optional()});class _QA extends H8{context;constructor(A,Q){super(A,{schema:NW6,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(wl).read(A.uploadId);if(!yJ0(w.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=gJ0({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=KG.createImageEntity({dataUrl:qL1(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 YH({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 PF({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:sA(w)});return r5.failure(w)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var zL1={name:"@brains/image-plugin",version:"0.2.0-alpha.206",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 PW6="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",bW6=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 a3(A){let Q=A?.trim();if(!Q)return;return Q}function jW6(A){let Q=a3(A.prompt);if(Q)return Q;let $=a3(A.content);if($&&!IQA($))return $;return}function MW6(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return O1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function JL1(A){let Q=a3(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return O1(Q)}async function kW6(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 PQA(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 OW6(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 bQA extends c6{entityType=KG.entityType;schema=F20;adapter=KG;constructor(A={}){super("image",zL1,A,bW6)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,$){if(A.from?.kind===wl.refKind)return this.promoteUpload(A,$);let w=jW6(A),B=a3(A.targetEntityType),X=a3(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=a3(A.title)??Y,q=JL1({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 V=await $.jobs.enqueue({type:"image-generate",data:{prompt:w,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:V,attachment:PQA(q)}}}}let H=await gZ($.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=EJ0(H.entity.content),U=JL1({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:PQA(U)}}}}async promoteUpload(A,Q){let $=A.from;if($?.kind!==wl.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w=$.id,B;try{B=await Q.uploads.scoped(wl).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!yJ0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=gJ0({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:OW6({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let $=a3(A.from.sourceEntityType),w=a3(A.from.sourceEntityId),B=a3(A.from.attachmentType);if(!$||!w||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await gZ(Q.entityService,$,w,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=a3(A.targetEntityType),Z=a3(A.targetEntityId),H;if(Y&&Z){let q=await gZ(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 kW6(Q,K),G=MW6(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:PQA(G,B)}}}}async createPendingImage(A,Q){let $=new Date().toISOString(),w=KG.createImageEntity({dataUrl:PW6,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 RC({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 TJ0(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 TJ0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new NQA(A,this.logger)),A.jobs.registerHandler("upload-promote",new _QA(this.logger.child("UploadPromotionJobHandler"),A))}}function _Q0(A={}){return new bQA(A)}zA();import{StdioServerTransport as xW6}from"@modelcontextprotocol/sdk/server/stdio.js";v0();var fW6=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 VL1(){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 jQA(){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 SJ0(A){let Q=fW6.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 jQA()}class t3{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return t3.instance??=new t3(A),t3.instance}static resetInstance(){if(t3.instance)t3.instance.stop(),t3.instance=null}static createFresh(A){return new t3(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?SJ0(this.config.logger):VL1()}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 xW6,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 vW6,timingSafeEqual as CW6}from"crypto";import{WebStandardStreamableHTTPServerTransport as hW6}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as EW6}from"@modelcontextprotocol/sdk/types.js";v8();function RW6(A){return r0.async((Q)=>{let $=setTimeout(()=>Q(r0.void),A);return $.unref(),r0.sync(()=>clearTimeout($))})}class MQA{scope;fibers;activeSweeps=new Set;closePromise=null;closed=!1;constructor(A,Q,$={}){this.scope=r0.runSync(j2.make()),this.fibers=r0.runSync(j2.extend(CZ.make(),this.scope));let w=r0.flatMap(QH.currentTimeMillis,(Z)=>r0.tryPromise({try:()=>this.trackSweep(()=>Q(Z)),catch:(H)=>H}).pipe(r0.catchAll((H)=>r0.sync(()=>{$.onError?.(H)})))),B=Math.max(1,A),X=($.clock?r0.sleep(B):RW6(B)).pipe(r0.andThen(w),r0.forever),Y=$.clock?r0.withClock(X,$.clock):X;CZ.unsafeAdd(this.fibers,r0.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 r0.runPromiseExit(j2.close(this.scope,R2.void));if(await Promise.allSettled([...this.activeSweeps]),R2.isFailure(A))throw j$.squash(A.cause)}}v0();var TW6=1800000,yW6=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"},SW6=W.looseObject({code:W.string().optional()});function mW6(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 uF{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?SJ0(this.config.logger):jQA(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??TW6,!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 MQA(Math.min(this.sessionIdleTtlMs,yW6),(Q)=>this.evictIdleSessions(Q),{onError:(Q)=>{this.logger.error("Error sweeping idle MCP sessions:",Q)}})}static getInstance(A){return uF.instance??=new uF(A),uF.instance}static async resetInstance(){let A=uF.instance;uF.instance=null,await A?.stop()}static createFresh(A){return new uF(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:`${mW6(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries($).map(([B,X])=>`${B}="${uW6(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(!cW6(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(!$&&EW6(w))B=new hW6({sessionIdGenerator:()=>vW6(),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=SW6.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 uW6(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function cW6(A,Q){let $=Buffer.from(A),w=Buffer.from(Q);if($.length!==w.length)return!1;return CW6($,w)}import{randomUUID as oW6}from"crypto";import{chmod as pW6,mkdir as lW6,readFile as iW6,rename as FL1,writeFile as dW6}from"fs/promises";import{dirname as nW6}from"path";class DH{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 iW6(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 lW6(nW6(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await dW6(Q,`${JSON.stringify(A,null,2)}
1776
1776
  `,{mode:384}),await pW6(Q,384),await FL1(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 FL1(this.filePath,Q)}catch($){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,$)}}}function Bl(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function mJ0(){let A=new Date;return A.setDate(A.getDate()-1),A}function LL1(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function i4(){return Math.floor(Date.now()/1000)}v0();import{join as sW6}from"path";function IL1(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function NL1(A){try{return new URL(A)}catch{return}}function kQA(A,Q){if(A===Q)return!0;let $=NL1(A),w=NL1(Q);if(!$||!w)return!1;if(!IL1($.hostname)||!IL1(w.hostname))return!1;return $.protocol===w.protocol&&$.port===w.port&&rW6($.pathname,w.pathname)&&$.search===w.search&&$.hash===w.hash}function rW6(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function OQA(A,Q){return A.some(($)=>kQA($,Q))}var aW6="oauth-auth-codes.json",tW6=600,eW6=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}:{}})),AH6=W.looseObject({codes:W.array(W.unknown()).optional()});function QH6(A){let Q=AH6.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap($H6)??[]}}function $H6(A){let Q=eW6.safeParse(A);return Q.success?[Q.data]:[]}async function wH6(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class uJ0{store;constructor(A){this.store=new DH({filePath:sW6(A.storageDir,A.storeFile??aW6),parse:QH6,empty:()=>({codes:[]})})}async createCode(A){let Q=i4(),$={code:`ocd_${oW6()}`,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+tW6};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=i4(),$;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 e3("Authorization code not found");if(X.consumed_at!==void 0)throw new e3("Authorization code already consumed");if(X.expires_at<=Q)throw new e3("Authorization code expired");if(X.client_id!==A.clientId)throw new e3("Authorization code client mismatch");if(!kQA(X.redirect_uri,A.redirectUri))throw new e3("Authorization code redirect URI mismatch");let Y=await wH6(A.codeVerifier);if(X.code_challenge!==Y)throw new e3("PKCE verification failed");$={...X,consumed_at:Q},w.codes[B]=$,await this.store.write(w)}),!$)throw new e3("Authorization code not consumed");return $}}class e3 extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as _L1}from"crypto";v0();import{join as BH6}from"path";var XH6="oauth-clients.json",YH6=W.enum(["none","client_secret_basic","client_secret_post"]),ZH6=W.object({redirect_uris:W.array(W.url()).min(1),token_endpoint_auth_method:YH6.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()}),WH6=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}:{}})),HH6=W.looseObject({clients:W.array(W.unknown()).optional()});function KH6(){return`ocs_${_L1().replaceAll("-","")}`}function UH6(A){let Q=HH6.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(GH6)??[]}}function GH6(A){let Q=WH6.safeParse(A);return Q.success?[Q.data]:[]}class cJ0{store;constructor(A){this.store=new DH({filePath:BH6(A.storageDir,A.storeFile??XH6),parse:UH6,empty:()=>({clients:[]})})}async registerClient(A){let Q=ZH6.safeParse(A);if(!Q.success)throw new PQ0(Q.error.message);let $=Q.data,w=i4(),B=`oc_${_L1()}`,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:KH6(),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 PQ0 extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}v0();import{createHash as PL1,generateKeyPairSync as DH6}from"crypto";import{mkdir as qH6,readFile as bL1,writeFile as zH6,chmod as JH6}from"fs/promises";import{dirname as VH6,join as jL1}from"path";var FH6="oauth-signing-key.jwk",LH6="a2a-signing-key.jwk",ML1=W.object({kty:W.literal("EC"),crv:W.literal("P-256"),x:W.string(),y:W.string(),d:W.string(),kid:W.string().optional()}),kL1=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),d:W.string(),kid:W.string().optional()});function IH6(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return PL1("sha256").update(Q).digest("base64url")}function NH6(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return PL1("sha256").update(Q).digest("base64url")}function _H6(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function PH6(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function bH6(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=ML1.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 OL1(Q.data)}function jH6(){let{privateKey:A}=DH6("ed25519"),Q=kL1.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return fL1(Q.data)}function OL1(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??IH6(A),use:"sig",alg:"ES256"}}function fL1(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??NH6(A),use:"sig",alg:"EdDSA"}}class pJ0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=jL1(A.storageDir,A.keyFile??FH6)}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 bH6();return await xL1(this.keyFile,Q),Q}async getPublicJwk(){return _H6(await this.getPrivateJwk())}async readExistingKey(){try{let A=ML1.safeParse(JSON.parse(await bL1(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return OL1(A.data)}catch(A){if(RL1(A))return;throw A}}}class fQA{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=jL1(A.storageDir,A.keyFile??LH6)}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=jH6();return await xL1(this.keyFile,Q),Q}async getPublicJwk(){return PH6(await this.getPrivateJwk())}async readExistingKey(){try{let A=kL1.safeParse(JSON.parse(await bL1(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return fL1(A.data)}catch(A){if(RL1(A))return;throw A}}}async function xL1(A,Q){await qH6(VH6(A),{recursive:!0,mode:448}),await zH6(A,`${JSON.stringify(Q,null,2)}
1777
1777
  `,{mode:384}),await JH6(A,384)}function RL1(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var q6={};P6(q6,{trimPadding:()=>CL1,toUTF8String:()=>hH6,toBuffer:()=>xH6,toBase64:()=>vH6,isBase64URL:()=>TH6,isBase64:()=>EH6,fromUTF8String:()=>CH6,fromBuffer:()=>RH6});var vL1=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),$=64;for(let w=0;w<64;w++)Q[A.charCodeAt(w)]=w;return Q},MH6=vL1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),kH6=vL1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),OH6=/^[-A-Za-z0-9\-_]*$/,fH6=/^[-A-Za-z0-9+/]*={0,3}$/,cF={};cF.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?kH6:MH6;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};cF.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};cF.toString=(A,Q)=>{return new TextDecoder().decode(cF.toArrayBuffer(A,Q))};cF.fromString=(A,Q)=>{return cF.fromArrayBuffer(new TextEncoder().encode(A),Q)};cF.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?OH6.test(A):fH6.test(A)}catch($){return!1}};cF.base64=cF;var $P=cF;function xH6(A,Q="base64url"){let $=$P.toArrayBuffer(A,Q==="base64url");return new Uint8Array($)}function RH6(A,Q="base64url"){let $=new Uint8Array(A);return $P.fromArrayBuffer($.buffer,Q==="base64url")}function vH6(A){let Q=$P.toArrayBuffer(A,!0);return $P.fromArrayBuffer(Q)}function CH6(A){return $P.fromString(A,!0)}function hH6(A){return $P.toString(A,!0)}function EH6(A){return $P.validate(A,!1)}function TH6(A){return A=CL1(A),$P.validate(A,!0)}function CL1(A){return A.replace(/=/g,"")}var qH={};P6(qH,{encode:()=>wK6,decodeFirst:()=>$K6});function Xl(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 lJ0=0,bQ0=1,xQA=2,RQA=3,vQA=4,CQA=5,hQA=6,hL1=7;function pF(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==bQ0){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 dJ0{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 EL1(A,Q,$){return Xl(A,Q,$)}function yH6(A,Q,$){let[w,B]=EL1(A,Q,$);return[-w-1,B]}function TL1(A,Q,$){let[w,B]=Xl(A,Q,$),X=$+B;return[new Uint8Array(A.buffer.slice(X,X+w)),B+w]}var gH6=new TextDecoder;function SH6(A,Q,$){let[w,B]=TL1(A,Q,$);return[gH6.decode(w),B]}function mH6(A,Q,$){if(Q===0)return[[],1];let[w,B]=Xl(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]=fh(A,$+X);Y.push(K),X+=U}return[Y,X]}var iJ0="Map is not supported or well formed";function uH6(A,Q,$){if(Q===0)return[new Map,1];let[w,B]=Xl(A,Q,$),X=B,Y=new Map;for(let Z=0;Z<w;Z++){let H=A.byteLength-$-X;if(H<=0)throw Error(iJ0);let[K,U]=fh(A,$+X);if(X+=U,H-=U,H<=0)throw Error(iJ0);if(typeof K!=="string"&&typeof K!=="number")throw Error(iJ0);if(Y.has(K))throw Error(iJ0);let[G,D]=fh(A,$+X);X+=D,Y.set(K,G)}return[Y,X]}function cH6(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 pH6(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 lH6(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 iH6(A,Q,$){let[w,B]=Xl(A,Q,$),[X,Y]=fh(A,$+B);return[new dJ0(w,X),B+Y]}function fh(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 lJ0:return EL1(A,B,Q);case bQ0:return yH6(A,B,Q);case xQA:return TL1(A,B,Q);case RQA:return SH6(A,B,Q);case vQA:return mH6(A,B,Q);case CQA:return uH6(A,B,Q);case hQA:return iH6(A,B,Q);case hL1: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 cH6(A,Q);case 26:return pH6(A,Q);case 27:return lH6(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function dH6(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 rH6(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return pF(bQ0,Math.abs(A));else return pF(lJ0,A);return[nH6(A)]}else if(A<0n)return pF(bQ0,A*-1n);else return pF(lJ0,A)}var oH6=new TextEncoder;function sH6(A,Q){Q.push(...pF(RQA,A.length)),Q.push(oH6.encode(A))}function aH6(A,Q){Q.push(...pF(xQA,A.length)),Q.push(A)}function tH6(A,Q){Q.push(...pF(vQA,A.length));for(let $ of A)jQ0($,Q)}function eH6(A,Q){Q.push(new Uint8Array(pF(CQA,A.size)));for(let[$,w]of A.entries())jQ0($,Q),jQ0(w,Q)}function AK6(A,Q){Q.push(...pF(hQA,A.tag)),jQ0(A.value,Q)}function jQ0(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(dH6(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...rH6(A));return}if(typeof A=="string"){sH6(A,Q);return}if(A instanceof Uint8Array){aH6(A,Q);return}if(Array.isArray(A)){tH6(A,Q);return}if(A instanceof Map){eH6(A,Q);return}if(A instanceof dJ0){AK6(A,Q);return}throw Error("Not implemented")}function EQA(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return fh(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return fh(new DataView(A),Q);return fh(A,Q)}function TQA(A){let Q=[];jQ0(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 $K6(A){let Q=new Uint8Array(A),$=EQA(Q,0),[w]=$;return w}function wK6(A){return TQA(A)}var iF={};P6(iF,{verify:()=>Fb1,getRandomValues:()=>uL1,digest:()=>mL1});function yL1(A){let Q=A.get(Z6.kty);return yQA(Q)&&Q===GG.OKP}function ik(A){let Q=A.get(Z6.kty);return yQA(Q)&&Q===GG.EC2}function Yl(A){let Q=A.get(Z6.kty);return yQA(Q)&&Q===GG.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 GG;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(GG||(GG={}));function yQA(A){return Object.values(GG).indexOf(A)>=0}var nZ;(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"})(nZ||(nZ={}));function gL1(A){return Object.values(nZ).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 lF(A){return Object.values(r6).indexOf(A)>=0}function dk(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 MQ0=void 0;function mq(){return new Promise((Q,$)=>{if(MQ0)return Q(MQ0);let w=XK6.stubThisGlobalThisCrypto();if(w)return MQ0=w,Q(MQ0);return $(new SL1)})}class SL1 extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var XK6={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{MQ0=A}};async function mL1(A,Q){let $=await mq(),w=dk(Q),B=await $.subtle.digest(w,A);return new Uint8Array(B)}async function uL1(A){return(await mq()).getRandomValues(A),A}async function Zl(A){let Q=await mq(),{keyData:$,algorithm:w}=A;return Q.subtle.importKey("jwk",$,w,!1,["verify"])}async function nJ0(A){let{cosePublicKey:Q,signature:$,data:w,shaHashOverride:B}=A,X=await mq(),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===nZ.P256)U="P-256";else if(Z===nZ.P384)U="P-384";else if(Z===nZ.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 Zl({keyData:G,algorithm:{name:"ECDSA",namedCurve:U}}),V=dk(Y);if(B)V=dk(B);let L={name:"ECDSA",hash:{name:V}};return X.subtle.verify(L,q,$,w)}function gQA(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 rJ0(A){let{cosePublicKey:Q,signature:$,data:w,shaHashOverride:B}=A,X=await mq(),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(!lF(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:gQA(Y),hash:{name:dk(Y)}},G={name:gQA(Y)};if(B)U.hash.name=dk(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 Zl({keyData:K,algorithm:U});return X.subtle.verify(G,D,$,w)}function oJ0(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 F=X.algorithms.map((_)=>_.alg)
2344
2344
  </form>
2345
2345
  </main>
2346
2346
  </body>
2347
- </html>`}function K$0(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(e8A(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function YL(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as vD6}from"crypto";function Rj1(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function RD6(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([...vj1(X),...vj1(H)])}function vj1(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 QwA(A,Q){let $={typ:"JWT",alg:"ES256",kid:A.kid},w=`${Rj1($)}.${Rj1(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(RD6(X)).toString("base64url")}`}var CD6=600;class $wA{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 K$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 bi(xj1($.params,w))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return K$0(A);let $=await A.formData(),w=await this.validateAuthorizationRequest(new URLSearchParams(o8A($)));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_${vD6()}`;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)+CD6}),$}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(!OQA(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 NG($,201)}catch($){if($ instanceof PQ0)return Y9("invalid_client_metadata",$.message);throw $}}async handleTokenRequest(A,Q){let $=await r8A(A),w=$.get("grant_type"),B=a8A(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=s8A(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||!OQA(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 e3)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 jP)return Y9("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),$=900,w=await QwA(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 NG({access_token:w,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await r8A(A),$=a8A(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=s8A(X,$);if(Y)return Y9("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,w),new Response(null,{status:200})}}class wwA{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(OF0(A));return NG(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(),OF0(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:Y$0(A)});return NG({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(OF0(A));return NG(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),OF0(A));if(!Q.verified)return Y9("access_denied","Passkey authentication failed");let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Y$0(A)});return NG({verified:!0},200,{"Set-Cookie":$.cookie})}}function OF0(A){let Q=IO(A),$=new URL(Q);return{origin:$.origin,rpID:$.hostname}}import{randomUUID as hD6}from"crypto";var U$0=86400;class BwA{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??U$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_${hD6()}`,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 KJ(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:KJ(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:O8A(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 bi(Oj1(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupStateStore.recordDelivery(A,Q,$)}}class fF0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=HJ(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>HJ(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??LO(this.issuer),this.keyStore=new pJ0({storageDir:A.storageDir}),this.a2aKeyStore=new fQA({storageDir:A.storageDir}),this.clientStore=new cJ0({storageDir:A.storageDir}),this.authCodeStore=new uJ0({storageDir:A.storageDir}),this.sessionStore=new PF0({storageDir:A.storageDir}),this.peerTrustStore=new LF0({storageDir:A.storageDir}),this.passkeyService=new FF0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new BwA({setupStateStore:new f8A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??U$0}),this.oauthEndpoints=new $wA({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new IF0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new wwA({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(LO(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:KJ(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=HJ(A);return{issuer:Q,authorization_endpoint:KJ(Q,"/authorize"),token_endpoint:KJ(Q,"/token"),registration_endpoint:KJ(Q,"/register"),revocation_endpoint:KJ(Q,"/revoke"),jwks_uri:KJ(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:[HJ(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 K$0(A)}async verifyBearerToken(A,Q={}){let $=n8A(A);if(!$)return;let w=Q.issuer?HJ(Q.issuer):this.resolveRequestIssuer(A);return d8A($,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"&&jj1($))return Mj1();if(A.method==="GET"){if($==="/.well-known/oauth-authorization-server")return bO(NG(this.getAuthorizationServerMetadata(Q)));if($==="/.well-known/jwks.json")return bO(NG(await this.getJwks()));if($==="/.well-known/oauth-protected-resource")return bO(NG(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 bO(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&$==="/token")return bO(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&$==="/revoke")return bO(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=IO(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&LO(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=t8A(new URL(A.url).searchParams.get("return_to"));return bi(e8A(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=t8A(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":R8A(Y$0(A)),"Cache-Control":"no-store"}})}}K20();zA();v0();var Cj1={name:"@brains/auth-service",version:"0.2.0-alpha.204",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 TD6=W.union([W.string().email(),W.object({to:W.string().email(),subject:W.string().min(1),body:W.string().min(1)}).strict()]),yD6=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(U$0),setupEmail:TD6.optional()}),xF0;function vY(){return xF0}class XwA extends d6{service;constructor(A={}){super("auth-service",Cj1,A,yD6)}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 fF0({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(),xF0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(xF0===this.service)xF0=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:Bh,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=H20.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:hj1(A.subject,Q),body:hj1(A.body,Q)}}function hj1(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 G$0(A={}){return new XwA(A)}v0();var YwA=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)});v0();import{createHash as cD6,randomUUID as pD6}from"crypto";function SD6(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function D$0(A,Q){let $=A?.[Q];return typeof $==="string"&&$.length>0?$:void 0}function mD6(A){let Q=SD6(A.data)?A.data:void 0,$=A.args,w=D$0(Q,"entityId")??D$0(Q,"id"),B=A.jobId??D$0(Q,"jobId"),X=D$0($,"entityType")??D$0($,"type");if(!w&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...w?{entityId:w}:{},...B?{jobId:B}:{}}}function uD6(A){return A?.map(mD6).filter((Q)=>Q!==void 0)??[]}function ZwA(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=uD6(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 Ej1=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.")}),Tj1=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 yj1(A,Q,$,w){let B=A.conversationId??$??w??`conversation-${pD6()}`,X=cD6("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function gj1(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 Sj1(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:Ej1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Ej1.parse($),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=yj1(B,w.userId,w.conversationId,w.channelId),Z=gj1(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 ZwA(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:Tj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Tj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=yj1(B,w.userId,w.conversationId,w.channelId),Z=gj1(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 ZwA(H,{conversationId:Y.handle})}}]}zA();function WwA(A,Q){A.messaging.subscribe("job-progress",async($)=>{let w=$m.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 mj1={name:"@brains/mcp",version:"0.2.0-alpha.204",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 jO extends bF{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",mj1,Q,YwA)}async getTools(){return Sj1(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"});WwA(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=vY();return this.httpServer=uF.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=vY(),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=t3.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(){t3.resetInstance(),await uF.resetInstance()}}zA();function q$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 K$0(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(e8A(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function YL(A){return A.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}import{randomUUID as vD6}from"crypto";function Rj1(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function RD6(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([...vj1(X),...vj1(H)])}function vj1(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 QwA(A,Q){let $={typ:"JWT",alg:"ES256",kid:A.kid},w=`${Rj1($)}.${Rj1(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(RD6(X)).toString("base64url")}`}var CD6=600;class $wA{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 K$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 bi(xj1($.params,w))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return K$0(A);let $=await A.formData(),w=await this.validateAuthorizationRequest(new URLSearchParams(o8A($)));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_${vD6()}`;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)+CD6}),$}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(!OQA(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 NG($,201)}catch($){if($ instanceof PQ0)return Y9("invalid_client_metadata",$.message);throw $}}async handleTokenRequest(A,Q){let $=await r8A(A),w=$.get("grant_type"),B=a8A(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=s8A(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||!OQA(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 e3)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 jP)return Y9("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),$=900,w=await QwA(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 NG({access_token:w,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await r8A(A),$=a8A(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=s8A(X,$);if(Y)return Y9("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,w),new Response(null,{status:200})}}class wwA{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(OF0(A));return NG(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(),OF0(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:Y$0(A)});return NG({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(OF0(A));return NG(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),OF0(A));if(!Q.verified)return Y9("access_denied","Passkey authentication failed");let $=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Y$0(A)});return NG({verified:!0},200,{"Set-Cookie":$.cookie})}}function OF0(A){let Q=IO(A),$=new URL(Q);return{origin:$.origin,rpID:$.hostname}}import{randomUUID as hD6}from"crypto";var U$0=86400;class BwA{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??U$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_${hD6()}`,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 KJ(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:KJ(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:O8A(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 bi(Oj1(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,$={}){await this.setupStateStore.recordDelivery(A,Q,$)}}class fF0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=HJ(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>HJ(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??LO(this.issuer),this.keyStore=new pJ0({storageDir:A.storageDir}),this.a2aKeyStore=new fQA({storageDir:A.storageDir}),this.clientStore=new cJ0({storageDir:A.storageDir}),this.authCodeStore=new uJ0({storageDir:A.storageDir}),this.sessionStore=new PF0({storageDir:A.storageDir}),this.peerTrustStore=new LF0({storageDir:A.storageDir}),this.passkeyService=new FF0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new BwA({setupStateStore:new f8A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??U$0}),this.oauthEndpoints=new $wA({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new IF0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new wwA({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(LO(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:KJ(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=HJ(A);return{issuer:Q,authorization_endpoint:KJ(Q,"/authorize"),token_endpoint:KJ(Q,"/token"),registration_endpoint:KJ(Q,"/register"),revocation_endpoint:KJ(Q,"/revoke"),jwks_uri:KJ(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:[HJ(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 K$0(A)}async verifyBearerToken(A,Q={}){let $=n8A(A);if(!$)return;let w=Q.issuer?HJ(Q.issuer):this.resolveRequestIssuer(A);return d8A($,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"&&jj1($))return Mj1();if(A.method==="GET"){if($==="/.well-known/oauth-authorization-server")return bO(NG(this.getAuthorizationServerMetadata(Q)));if($==="/.well-known/jwks.json")return bO(NG(await this.getJwks()));if($==="/.well-known/oauth-protected-resource")return bO(NG(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 bO(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&$==="/token")return bO(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&$==="/revoke")return bO(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=IO(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&LO(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=t8A(new URL(A.url).searchParams.get("return_to"));return bi(e8A(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=t8A(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":R8A(Y$0(A)),"Cache-Control":"no-store"}})}}K20();zA();v0();var Cj1={name:"@brains/auth-service",version:"0.2.0-alpha.206",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 TD6=W.union([W.string().email(),W.object({to:W.string().email(),subject:W.string().min(1),body:W.string().min(1)}).strict()]),yD6=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(U$0),setupEmail:TD6.optional()}),xF0;function vY(){return xF0}class XwA extends d6{service;constructor(A={}){super("auth-service",Cj1,A,yD6)}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 fF0({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(),xF0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(xF0===this.service)xF0=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:Bh,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=H20.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:hj1(A.subject,Q),body:hj1(A.body,Q)}}function hj1(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 G$0(A={}){return new XwA(A)}v0();var YwA=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)});v0();import{createHash as cD6,randomUUID as pD6}from"crypto";function SD6(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function D$0(A,Q){let $=A?.[Q];return typeof $==="string"&&$.length>0?$:void 0}function mD6(A){let Q=SD6(A.data)?A.data:void 0,$=A.args,w=D$0(Q,"entityId")??D$0(Q,"id"),B=A.jobId??D$0(Q,"jobId"),X=D$0($,"entityType")??D$0($,"type");if(!w&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...w?{entityId:w}:{},...B?{jobId:B}:{}}}function uD6(A){return A?.map(mD6).filter((Q)=>Q!==void 0)??[]}function ZwA(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=uD6(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 Ej1=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.")}),Tj1=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 yj1(A,Q,$,w){let B=A.conversationId??$??w??`conversation-${pD6()}`,X=cD6("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function gj1(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 Sj1(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:Ej1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Ej1.parse($),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=yj1(B,w.userId,w.conversationId,w.channelId),Z=gj1(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 ZwA(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:Tj1.shape,visibility:"public",sideEffects:"writes",handler:async($,w)=>{let B=Tj1.parse($),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=yj1(B,w.userId,w.conversationId,w.channelId),Z=gj1(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 ZwA(H,{conversationId:Y.handle})}}]}zA();function WwA(A,Q){A.messaging.subscribe("job-progress",async($)=>{let w=$m.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 mj1={name:"@brains/mcp",version:"0.2.0-alpha.206",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 jO extends bF{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",mj1,Q,YwA)}async getTools(){return Sj1(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"});WwA(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=vY();return this.httpServer=uF.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=vY(),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=t3.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(){t3.resetInstance(),await uF.resetInstance()}}zA();function q$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}iD6(X,Q,w,(Z)=>{B=Z})}if(B)w.push(B);return w}function iD6(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}dD6(Y,Q,$,(H)=>{B=H})}w(B)}function dD6(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 xG=k1(bYA(),1);zA();v0();var jYA=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),...cA0.shape,captureUrlEmoji:W.string().default("\uD83D\uDD16")});var tX2={name:"@brains/discord",version:"0.2.0-alpha.204",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 e80=2000,_1$={completed:"Action completed",declined:"Action declined",failed:"Action failed"},P1$={completed:2278750,declined:9741240,failed:15680580},b1$=8388608,j1$=8000,M1$=100;function sN0(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class Kf extends R3{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;eventHandlerController=new AbortController;activeEventHandlers=new Set;eventHandlerStopPromise=null;eventHandlersClosed=!1;constructor(A,Q={}){super("discord",tX2,A,jYA);this.fetchText=Q.fetchText??lG1}async onRegister(A){await super.onRegister(A),this.client=new xG.Client({intents:[xG.GatewayIntentBits.Guilds,xG.GatewayIntentBits.GuildMessages,xG.GatewayIntentBits.MessageContent,xG.GatewayIntentBits.DirectMessages],partials:[xG.Partials.Channel]}),this.client.on(xG.Events.MessageCreate,(Q)=>{this.runEventHandler("message",($)=>this.handleMessage(Q,$))}),this.client.on(xG.Events.InteractionCreate,(Q)=>{this.runEventHandler("interaction",($)=>this.handleInteraction(Q,$))}),this.client.once(xG.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(!sN0($))return;let w=q$0(Q,e80);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(!sN0($))return;if(typeof Q!=="string")return(await $.send(Q)).id;let w=q$0(Q,e80),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(!sN0(w))return!1;try{return await(await w.messages.fetch(Q)).edit($.slice(0,e80)),!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((V)=>this.logger.error("URL capture failed",{error:V,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 V of A.attachments.values()){let L=V.name,F=V.contentType??void 0,_=V.size;if(!this.isUploadableTextFile(L,F))continue;if(!this.isFileSizeAllowed(_))continue;try{let j=await this.fetchText(V.url);Q.throwIfAborted(),U+=`
2354
+ `:"")+X}if(w)Q.push(w);return Q}p2();var xG=k1(bYA(),1);zA();v0();var jYA=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),...cA0.shape,captureUrlEmoji:W.string().default("\uD83D\uDD16")});var tX2={name:"@brains/discord",version:"0.2.0-alpha.206",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 e80=2000,_1$={completed:"Action completed",declined:"Action declined",failed:"Action failed"},P1$={completed:2278750,declined:9741240,failed:15680580},b1$=8388608,j1$=8000,M1$=100;function sN0(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class Kf extends R3{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;eventHandlerController=new AbortController;activeEventHandlers=new Set;eventHandlerStopPromise=null;eventHandlersClosed=!1;constructor(A,Q={}){super("discord",tX2,A,jYA);this.fetchText=Q.fetchText??lG1}async onRegister(A){await super.onRegister(A),this.client=new xG.Client({intents:[xG.GatewayIntentBits.Guilds,xG.GatewayIntentBits.GuildMessages,xG.GatewayIntentBits.MessageContent,xG.GatewayIntentBits.DirectMessages],partials:[xG.Partials.Channel]}),this.client.on(xG.Events.MessageCreate,(Q)=>{this.runEventHandler("message",($)=>this.handleMessage(Q,$))}),this.client.on(xG.Events.InteractionCreate,(Q)=>{this.runEventHandler("interaction",($)=>this.handleInteraction(Q,$))}),this.client.once(xG.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(!sN0($))return;let w=q$0(Q,e80);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(!sN0($))return;if(typeof Q!=="string")return(await $.send(Q)).id;let w=q$0(Q,e80),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(!sN0(w))return!1;try{return await(await w.messages.fetch(Q)).edit($.slice(0,e80)),!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((V)=>this.logger.error("URL capture failed",{error:V,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 V of A.attachments.values()){let L=V.name,F=V.contentType??void 0,_=V.size;if(!this.isUploadableTextFile(L,F))continue;if(!this.isFileSizeAllowed(_))continue;try{let j=await this.fetchText(V.url);Q.throwIfAborted(),U+=`
2355
2355
 
2356
2356
  `+this.formatFileUploadMessage(L,j)}catch(j){this.logger.error("Failed to download attachment",{error:j,filename:L})}}}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:lW(A,M1$),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(sN0(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=EC(G.cards);if(D.length>0)this.pendingConfirmations.set(Z,new Set(D.map((V)=>V.id)));else if(G.pendingConfirmations)this.pendingConfirmations.set(Z,new Set(G.pendingConfirmations.map((V)=>V.id)));else this.pendingConfirmations.delete(Z);let q=await this.sendMessageWithId({channelId:Y,message:Lc(G.text,D),approvalCards:D});if(q&&G.toolResults){for(let V of G.toolResults)if(V.jobId)this.trackAgentResponseForJob(V.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:lW(A.trim().length>0?`${A}
2357
2357
 
@@ -2467,7 +2467,7 @@ ${A.value}
2467
2467
  ${rWA(A)}
2468
2468
  \`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToMrkdwn(Q))}};function nP2(A){return Jw0(A,(Q,$)=>`<@${$}>`)}function dKA(A){if(!(A.contextId||A.privateMetadata))return;return JSON.stringify({c:A.contextId,m:A.privateMetadata})}function rP2(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 AP0(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(qK$)}}function qK$(A){switch(A.type){case"text_input":return zK$(A);case"select":return JK$(A);case"external_select":return VK$(A);case"radio_select":return FK$(A);case"text":return Ab2(A);case"fields":return $b2(A);default:throw Error(`Unknown modal child type: ${A.type}`)}}function QP0(A){return{text:{type:"plain_text",text:A.label},value:A.value,...A.description?{description:{type:"plain_text",text:A.description}}:{}}}function zK$(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 JK$(A){let Q=A.options.map(QP0),$={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 VK$(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=QP0(A.initialOption);return{type:"input",block_id:A.id,optional:A.optional??!1,label:{type:"plain_text",text:A.label},element:Q}}function FK$(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 nKA=/^[A-Z0-9_]+$/,oP2=/^U[A-Z0-9]+$/,sP2=2500;function LK$(A,Q){let $=Buffer.from(A,"utf8"),w=Buffer.from(Q,"utf8");if($.length!==w.length)return!1;return SH$($,w)}function IK$(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 aP2(A){let Q=A.indexOf("<@"),$=A.indexOf("<#");if(Q===-1)return $;if($===-1)return Q;return Math.min(Q,$)}var tP2=/\/$/,NK$=2000,_K$=150,PK$=/^https?:\/\/[^/]+\.slack\.com\/archives\/([A-Z0-9]+)\/p(\d+)(?:\?.*)?$/;function bK$(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 rKA=4,jK$=new Set(["feature_not_enabled","method_deprecated","unknown_method"]);function MK$(A){let Q=A;return Q?.code==="slack_webapi_platform_error"?Q.data?.error:void 0}function kK$(A){if(A===void 0)return;if(typeof A==="function")return A;return()=>A}var OK$=class A{name="slack";userName;_client;tokenClientCache=new Map;slackApiUrl;webClientOptions;signingSecret;webhookVerifier;defaultBotTokenProvider;chat=null;logger;_botUserId=null;_botId=null;formatConverter=new DK$;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 pd("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 pd("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 sKA.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=kK$(X);if(this.slackApiUrl=Q.apiUrl??process.env.SLACK_API_URL,this.webClientOptions=Q.webClientOptions,this._client=new sKA.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 $HA("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=XV2(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 pd("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:$V2($.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&&BV2(B.botToken))return{...B,botToken:wV2(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 pd("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&&LK$(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 kJ2(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),sP2)}),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:sP2}),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(QP0)}));return new Response(JSON.stringify({option_groups:B}),{status:200,headers:{"Content-Type":"application/json"}})}let w=Q.slice(0,100).map(QP0);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}=rP2(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}=rP2(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=dKA({contextId:$,privateMetadata:w.privateMetadata});return{response_action:"update",view:AP0(w,B)}}case"push":{let w=this.convertModalJSX(Q.modal),B=dKA({contextId:$,privateMetadata:w.privateMetadata});return{response_action:"push",view:AP0(w,B)}}default:return{}}}convertModalJSX(Q){if(lJ2(Q)){let $=iJ2(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 oKA.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 oKA.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 L=(await this._client.conversations.replies(await this.withToken({channel:Q.item.channel,ts:Q.item.ts,limit:1}))).messages?.[0];if(L?.thread_ts)w=L.thread_ts}catch(V){this.logger.warn("Failed to resolve parent thread for reaction, using message ts",{error:String(V),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=ud.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:pKA(Q.context)}:{}});$?.waitUntil?.(w)}this.chat.processAppHomeOpened({userId:Q.user,channelId:Q.channel,tab:Q.tab,adapter:this,...Q.context?{entities:pKA(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:pKA(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>rKA)this.logger.warn(`Slack shows at most ${rKA} suggested prompts; dropping the rest`,{configured:w.length}),w=w.slice(0,rKA);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 V=q.indexOf(">");if(V===-1)continue;let L=q.slice(0,V);if(L.startsWith("@")){let F=L.slice(1),_=F.indexOf("|"),j=_>=0?F.slice(0,_):F;if(nKA.test(j))w.add(j)}else if(L.startsWith("#")){let F=L.slice(1);if(F.indexOf("|")===-1&&nKA.test(F))B.add(F)}}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 V=await this.lookupUser(q);return[q,V?.displayName??q]})),Promise.all([...B].map(async(q)=>{let V=await this.lookupChannel(q);return[q,V]}))]),H=new Map(Y),K=new Map(Z),U="",G=Q,D=aP2(G);while(D!==-1){U+=G.slice(0,D),G=G.slice(D);let q=G.indexOf(">");if(q===-1)break;let V=G[1],L=G.slice(2,q),F=L.indexOf("|"),_=F>=0?L.slice(0,F):L;if(V==="@"&&nKA.test(_)){let j=H.get(_);U+=j?`<@${_}|${j}>`:`<@${_}>`}else if(V==="#"&&F===-1&&K.has(_)){let j=K.get(_);U+=`<#${_}|${j}>`}else U+=G.slice(0,q+1);G=G.slice(q+1),D=aP2(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(tP2,""))||w.get(`${B}/`);if(Y)return{...X,...Y};return X})}createLinkPreview(Q){let $=PK$.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 QHA({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()+NK$,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,_K$))}if(!Y)return Q;return Q.map((Z)=>{if(Z.title)return Z;let H=Y[Z.url]||Y[Z.url.replace(tP2,"")]||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 zw0("slack",`Failed to fetch file: ${w.status} ${w.statusText}`);if((w.headers.get("content-type")??"").includes("text/html"))throw new zw0("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 pd("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(Jw0(Q,(Z,H)=>{if(oP2.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 Jw0(Q,(Z,H)=>{if(oP2.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=XHA(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=zT(w);if(!(D||q))return{id:`file-${Date.now()}`,threadId:Q,raw:{files:H,uploadedFileIds:Z}}}let K=zT(w);if(K){let D=iw0(K),q=dw0(K);this.logger.debug("Slack API: chat.postMessage (blocks)",{channel:B,threadTs:Y,blockCount:D.length});let V;try{V=await this._client.chat.postMessage(await this.withToken({channel:B,thread_ts:Y,text:q,blocks:D,unfurl_links:!1,unfurl_media:!1}))}catch(L){throw IK$(L,D,this.logger)}return this.logger.debug("Slack API: chat.postMessage response",{messageId:V.ts,ok:V.ok}),{id:V.ts,threadId:Q,raw:Z===void 0?V:{...V,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=zT(B);if(H){let G=iw0(H),D=dw0(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(XHA(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=zT(B);if(q){let j=iw0(q),b=dw0(q);this.logger.debug("Slack API: chat.scheduleMessage (blocks)",{channel:X,threadTs:Z,postAt:H,blockCount:j.length});let k=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=k.scheduled_message_id,R=this;return{scheduledMessageId:v,channelId:X,postAt:w.postAt,raw:k,async cancel(){await R._client.chat.deleteScheduledMessage({token:await G(),channel:X,scheduled_message_id:v})}}}let V=this.formatConverter.toSlackPayload(B);this.logger.debug("Slack API: chat.scheduleMessage",{channel:X,threadTs:Z,postAt:H,payloadKey:"markdown_text"in V?"markdown_text":"text"});let L=await this._client.chat.scheduleMessage({token:D,channel:X,thread_ts:Z,post_at:H,...V,unfurl_links:!1,unfurl_media:!1}),F=L.scheduled_message_id,_=this;return{scheduledMessageId:F,channelId:X,postAt:w.postAt,raw:L,async cancel(){await _._client.chat.deleteScheduledMessage({token:await G(),channel:X,scheduled_message_id:F})}}}catch(q){this.handleSlackError(q)}}async openModal(Q,$,w){let B=dKA({contextId:w,privateMetadata:$.privateMetadata}),X=AP0($,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=AP0($);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 aJ2(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=zT(B);if(Z){let U=iw0(Z),G=dw0(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 qw0(qT(Q.markdown));if("ast"in Q)return qw0(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=ud.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=ud.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 cJ2({wrapTablesForAppend:!1}),G={message:null,mode:"native",nativeRendered:!1},D=w?.updateIntervalMs??1000,q="",V=0,L=async(O)=>{let g=U.getCommittableText();if(g.length===0||g===q)return;let m=Date.now();if(!(O||m-V>=D))return;if(G.message)await this.editMessage(Q,G.message.id,g);else G.message=await this.postMessage(Q,g);q=g,V=m},F=(O)=>{G.mode="fallback";let g=MK$(O);if(g&&jK$.has(g))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 L(O);return}let g=U.getCommittableText(),m=g.slice(K.length);if(m.length===0)return;try{if(await H.append({markdown_text:m,token:Z}))G.nativeRendered=!0;K=g}catch(l){if(G.nativeRendered)throw l;F(l),await L(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(g){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:g})}};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 k=[...w?.stopBlocks??[],...this.feedbackButtons?[bK$(this.feedbackButtons)]:[]],v;try{v=await H.stop({token:Z,...k.length>0?{blocks:k}:{}})}catch(O){if(G.nativeRendered)throw O;return F(O),await L(!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 zw0("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((V)=>this.parseSlackMessage(V,w))),q;if(U>0||H.has_more){let V=G[0];if(V?.ts)q=V.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 QHA({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}`,V=await this.parseSlackMessage(G,q,{skipSelfMention:!1});return{id:q,rootMessage:V,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 sJ2("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=zT(Z);if(H)B={replace_original:!0,text:dw0(H),blocks:iw0(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 zw0("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 wb2(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 $HA("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 OK$(Y)}var fK$=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:xK$(),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 xK$(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function $P0(A){return new fK$}v0();var RK$=W.object({subscribedAt:W.string().datetime(),routingMode:W.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:W.boolean().optional()});var vK$="chat.discord.subscriptions",CK$="chat.slack.subscriptions";function hK$(A){return A==="discord"?vK$:CK$}function aKA(A,Q){return A.scoped({namespace:hK$(Q),schema:RK$})}function Bb2(A){return aKA(A,"discord")}function Xb2(A){return aKA(A,"slack")}function Yb2(A,Q,$=$P0()){let w=new Map;for(let B of Q)w.set(B,aKA(A,B));return new Zb2($,w)}class Zb2{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 Wb2(A,Q){if(!A)throw Error(Q);return A}function Hb2(A){let{discord:Q,slack:$}=A,w=Q?bJ2({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds}):void 0;if(w)A.gatewayLoop.setAdapter(w);let X=$?wb2($.mode==="socket"?{botToken:$.botToken,mode:"socket",appToken:Wb2($.appToken,"Slack app token is required in socket mode")}:{botToken:$.botToken,signingSecret:Wb2($.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?Yb2(A.runtimeState,Z):$P0();return new WZ2({userName:A.userName,adapters:Y,...Q||$?{concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"}}:{},state:H})}class tKA{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 eKA{deps;constructor(A){this.deps=A}async build(A,Q,$,w){let B={message:EK$(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=v_(H,"upload"),U=Gk(K,Z.mimeType),G=Z.size??0,D=Dq0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!qq0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let V=C_({filename:K,mediaType:U,content:q,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let L=await Y.save({filename:V.filename,mediaType:V.mediaType,content:q,metadata:this.buildMetadata(A,Q,$)});B.attachments.push(Kb2(L.filename,L.mediaType,q,L.ref,V.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 AUA(A,Q,$,w){return Kb2(A,Q,$,w,Dk(A,Q))}function EK$(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 Kb2(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 QUA="discord-chat-upload",$UA="slack-chat-upload",wP0="upload";function Ub2(){return{namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}}function wUA(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function BUA(){return{namespace:"slack-chat",refKind:"slack-chat-upload",routePath:"/api/webhooks/chat/slack/uploads"}}function Lf(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 TK$(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let $=Q.channel_id;return typeof $==="string"?$:void 0}function Gb2(A,Q){if(A.isDM)return!1;let $=Lf(A.id);if(!$.threadId)return!1;let w=TK$(Q);return w!==void 0&&w!==$.threadId}function BP0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let $=Lf(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 XP0(A,Q,$){if(A.isDM&&!$.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return BP0(A,$)}function XUA(A,Q){if(!Q)return!1;if(A.isDM&&!Q.allowDMs)return!1;return BP0(A,Q)}function nw0(A,Q){let $=Lf(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 Xn(A){return A.isDM?"DM":A.channelId}var yK$="https://discord.com/api/v10";async function Db2(A){let Q=Lf(A.threadId),$=Q.threadId??Q.channelId;if(!$)return;let w=A.fetchFn??fetch;try{let B=await w(`${yK$}/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 qb2={name:"@brains/chat",version:"0.2.0-alpha.204",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 SK$=/https?:\/\/\S+/i,mK$=/[\s\S]+/,uK$=/^(?:(?:confirmation|approval) required|please confirm(?: this action)?)\.?$/i,cK$=1000,pK$=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()}),lK$=W.object({card:W.custom((A)=>pK$.safeParse(A).success),fallbackText:W.string().optional()});class YP0 extends R3{threadRegistry=new aN0;pendingApprovals;uploadContinuity;promptActions=new kYA(cK$);pendingJobArtifacts=new Map;toolStatusMessenger=new OYA(this.threadRegistry);compactingSlackApprovalToolStatuses=new Set;activeSlackConfirmationConversations=new Set;cardBuilder=new RYA({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new vYA({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new CYA({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let $=this.config.adapters.discord?.botToken;if(!$)return;await Db2({threadId:A,messageId:Q,botToken:$,logger:this.logger})}});subscriptionRouter=new tKA({getSubscriptions:(A)=>A==="discord"?this.discordSubscriptions:A==="slack"?this.slackSubscriptions:void 0,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:Gb2,logger:this.logger});chatInputBuilder=new eKA({getUploadStore:(A)=>A==="discord"||A==="slack"?this.getCanonicalUploadStore():void 0,getThreadIdParts:Lf,logger:this.logger});gatewayLoop;slackSocketLoop;chatApp;discordSubscriptions;slackSubscriptions;chatAppRunning=!1;constructor(A={}){super("chat",qb2,A,MYA);this.gatewayLoop=new hYA({getApp:()=>this.chatApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.slackSocketLoop=new EYA({listenerRunMs:this.config.gatewayRunMs,restartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.chatApp=new TYA({discord:this.config.adapters.discord,slack:this.config.adapters.slack,getUploadStore:(Q)=>this.getUploadStore(Q),buildApp:(Q)=>Hb2({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 nA0({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=Bb2(A.runtimeState);if(this.config.adapters.slack)this.slackSubscriptions=Xb2(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 Qw0(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 Qw0(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=lK$.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(A_0(A)==="slack"&&$.fallbackText)return $.fallbackText;return $}formatProgressOutput(A){return xYA(A)}formatCompletionOutput(A){return xYA(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=A_0(A.channelId)==="slack",$=Q&&this.activeSlackConfirmationConversations.has(A.conversationId);if(Q&&this.compactingSlackApprovalToolStatuses.has(Wk(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 wY2(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&&XP0(Q,$,B)&&!Q.isDM&&this.config.adapters.discord.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,$);else if(X==="slack"&&B&&XP0(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(mK$,async(Q,$,w)=>{let B=this.getPlatformConfig(Q);if(!B||B.requireMention)return;await this.handleRoutedMessage(Q,$,w)});A.onNewMessage(SK$,async(Q,$)=>{await this.handlePassiveUrlCapture(Q,$)}),A.onAction([tN0,fYA],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(Aw0,async(Q)=>{await this.handlePromptAction(Q)}),A.onAction(async(Q)=>{if(!Q.actionId.startsWith(`${Aw0}:`))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(!XUA($,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,nw0($,{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:Xn($),...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(!XUA($,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,nw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}}));await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===tN0,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(!XP0(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 Qw0(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=nw0(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:Xn(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),$=yC(A.response,{deniedCardIds:Q.deniedCardIds});this.rememberPendingJobArtifacts($,A.channelId,A.userPermissionLevel,Q.deliveredCardIds,Q.deniedCardIds);let w=!1;if(A.confirmation){let b=Nc(A.response,A.confirmation.confirmed?"approved":"declined");w=await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,{title:rA0(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)&&uK$.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,V=U||q,L=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText($,Q.deniedCardIds),F=V?void 0:await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:L,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=TC(X);if(b)await A.thread.post(b)}else await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,X);let j=_??F;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(!pA0(A,w))return!1;let Y=$q0({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:Xn(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 qw0(qT(Q.markdown));if("ast"in Q)return qw0(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=ud.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=ud.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 cJ2({wrapTablesForAppend:!1}),G={message:null,mode:"native",nativeRendered:!1},D=w?.updateIntervalMs??1000,q="",V=0,L=async(O)=>{let g=U.getCommittableText();if(g.length===0||g===q)return;let m=Date.now();if(!(O||m-V>=D))return;if(G.message)await this.editMessage(Q,G.message.id,g);else G.message=await this.postMessage(Q,g);q=g,V=m},F=(O)=>{G.mode="fallback";let g=MK$(O);if(g&&jK$.has(g))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 L(O);return}let g=U.getCommittableText(),m=g.slice(K.length);if(m.length===0)return;try{if(await H.append({markdown_text:m,token:Z}))G.nativeRendered=!0;K=g}catch(l){if(G.nativeRendered)throw l;F(l),await L(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(g){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:g})}};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 k=[...w?.stopBlocks??[],...this.feedbackButtons?[bK$(this.feedbackButtons)]:[]],v;try{v=await H.stop({token:Z,...k.length>0?{blocks:k}:{}})}catch(O){if(G.nativeRendered)throw O;return F(O),await L(!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 zw0("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((V)=>this.parseSlackMessage(V,w))),q;if(U>0||H.has_more){let V=G[0];if(V?.ts)q=V.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 QHA({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}`,V=await this.parseSlackMessage(G,q,{skipSelfMention:!1});return{id:q,rootMessage:V,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 sJ2("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=zT(Z);if(H)B={replace_original:!0,text:dw0(H),blocks:iw0(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 zw0("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 wb2(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 $HA("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 OK$(Y)}var fK$=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:xK$(),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 xK$(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function $P0(A){return new fK$}v0();var RK$=W.object({subscribedAt:W.string().datetime(),routingMode:W.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:W.boolean().optional()});var vK$="chat.discord.subscriptions",CK$="chat.slack.subscriptions";function hK$(A){return A==="discord"?vK$:CK$}function aKA(A,Q){return A.scoped({namespace:hK$(Q),schema:RK$})}function Bb2(A){return aKA(A,"discord")}function Xb2(A){return aKA(A,"slack")}function Yb2(A,Q,$=$P0()){let w=new Map;for(let B of Q)w.set(B,aKA(A,B));return new Zb2($,w)}class Zb2{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 Wb2(A,Q){if(!A)throw Error(Q);return A}function Hb2(A){let{discord:Q,slack:$}=A,w=Q?bJ2({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds}):void 0;if(w)A.gatewayLoop.setAdapter(w);let X=$?wb2($.mode==="socket"?{botToken:$.botToken,mode:"socket",appToken:Wb2($.appToken,"Slack app token is required in socket mode")}:{botToken:$.botToken,signingSecret:Wb2($.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?Yb2(A.runtimeState,Z):$P0();return new WZ2({userName:A.userName,adapters:Y,...Q||$?{concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"}}:{},state:H})}class tKA{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 eKA{deps;constructor(A){this.deps=A}async build(A,Q,$,w){let B={message:EK$(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=v_(H,"upload"),U=Gk(K,Z.mimeType),G=Z.size??0,D=Dq0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!qq0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let V=C_({filename:K,mediaType:U,content:q,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let L=await Y.save({filename:V.filename,mediaType:V.mediaType,content:q,metadata:this.buildMetadata(A,Q,$)});B.attachments.push(Kb2(L.filename,L.mediaType,q,L.ref,V.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 AUA(A,Q,$,w){return Kb2(A,Q,$,w,Dk(A,Q))}function EK$(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 Kb2(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 QUA="discord-chat-upload",$UA="slack-chat-upload",wP0="upload";function Ub2(){return{namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"}}function wUA(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function BUA(){return{namespace:"slack-chat",refKind:"slack-chat-upload",routePath:"/api/webhooks/chat/slack/uploads"}}function Lf(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 TK$(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let $=Q.channel_id;return typeof $==="string"?$:void 0}function Gb2(A,Q){if(A.isDM)return!1;let $=Lf(A.id);if(!$.threadId)return!1;let w=TK$(Q);return w!==void 0&&w!==$.threadId}function BP0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let $=Lf(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 XP0(A,Q,$){if(A.isDM&&!$.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return BP0(A,$)}function XUA(A,Q){if(!Q)return!1;if(A.isDM&&!Q.allowDMs)return!1;return BP0(A,Q)}function nw0(A,Q){let $=Lf(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 Xn(A){return A.isDM?"DM":A.channelId}var yK$="https://discord.com/api/v10";async function Db2(A){let Q=Lf(A.threadId),$=Q.threadId??Q.channelId;if(!$)return;let w=A.fetchFn??fetch;try{let B=await w(`${yK$}/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 qb2={name:"@brains/chat",version:"0.2.0-alpha.206",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 SK$=/https?:\/\/\S+/i,mK$=/[\s\S]+/,uK$=/^(?:(?:confirmation|approval) required|please confirm(?: this action)?)\.?$/i,cK$=1000,pK$=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()}),lK$=W.object({card:W.custom((A)=>pK$.safeParse(A).success),fallbackText:W.string().optional()});class YP0 extends R3{threadRegistry=new aN0;pendingApprovals;uploadContinuity;promptActions=new kYA(cK$);pendingJobArtifacts=new Map;toolStatusMessenger=new OYA(this.threadRegistry);compactingSlackApprovalToolStatuses=new Set;activeSlackConfirmationConversations=new Set;cardBuilder=new RYA({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new vYA({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new CYA({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let $=this.config.adapters.discord?.botToken;if(!$)return;await Db2({threadId:A,messageId:Q,botToken:$,logger:this.logger})}});subscriptionRouter=new tKA({getSubscriptions:(A)=>A==="discord"?this.discordSubscriptions:A==="slack"?this.slackSubscriptions:void 0,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:Gb2,logger:this.logger});chatInputBuilder=new eKA({getUploadStore:(A)=>A==="discord"||A==="slack"?this.getCanonicalUploadStore():void 0,getThreadIdParts:Lf,logger:this.logger});gatewayLoop;slackSocketLoop;chatApp;discordSubscriptions;slackSubscriptions;chatAppRunning=!1;constructor(A={}){super("chat",qb2,A,MYA);this.gatewayLoop=new hYA({getApp:()=>this.chatApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.slackSocketLoop=new EYA({listenerRunMs:this.config.gatewayRunMs,restartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.chatApp=new TYA({discord:this.config.adapters.discord,slack:this.config.adapters.slack,getUploadStore:(Q)=>this.getUploadStore(Q),buildApp:(Q)=>Hb2({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 nA0({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=Bb2(A.runtimeState);if(this.config.adapters.slack)this.slackSubscriptions=Xb2(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 Qw0(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 Qw0(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=lK$.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(A_0(A)==="slack"&&$.fallbackText)return $.fallbackText;return $}formatProgressOutput(A){return xYA(A)}formatCompletionOutput(A){return xYA(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=A_0(A.channelId)==="slack",$=Q&&this.activeSlackConfirmationConversations.has(A.conversationId);if(Q&&this.compactingSlackApprovalToolStatuses.has(Wk(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 wY2(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&&XP0(Q,$,B)&&!Q.isDM&&this.config.adapters.discord.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,$);else if(X==="slack"&&B&&XP0(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(mK$,async(Q,$,w)=>{let B=this.getPlatformConfig(Q);if(!B||B.requireMention)return;await this.handleRoutedMessage(Q,$,w)});A.onNewMessage(SK$,async(Q,$)=>{await this.handlePassiveUrlCapture(Q,$)}),A.onAction([tN0,fYA],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(Aw0,async(Q)=>{await this.handlePromptAction(Q)}),A.onAction(async(Q)=>{if(!Q.actionId.startsWith(`${Aw0}:`))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(!XUA($,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,nw0($,{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:Xn($),...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(!XUA($,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,nw0($,{author:{isMe:A.user.isMe,isBot:A.user.isBot}}));await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===tN0,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(!XP0(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 Qw0(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=nw0(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:Xn(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),$=yC(A.response,{deniedCardIds:Q.deniedCardIds});this.rememberPendingJobArtifacts($,A.channelId,A.userPermissionLevel,Q.deliveredCardIds,Q.deniedCardIds);let w=!1;if(A.confirmation){let b=Nc(A.response,A.confirmation.confirmed?"approved":"declined");w=await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,{title:rA0(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)&&uK$.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,V=U||q,L=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText($,Q.deniedCardIds),F=V?void 0:await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:L,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=TC(X);if(b)await A.thread.post(b)}else await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,X);let j=_??F;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(!pA0(A,w))return!1;let Y=$q0({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:Xn(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=Hq0({response:A,confirmed:Q,remainingApprovalHelp:$,deniedCardIds:w,formatCard:(X)=>this.cardBuilder.formatStructuredCard(X,w),formatPendingConfirmationHelp:TC});return{card:{type:"card",title:rA0(B.variant),children:B.parts.map((X)=>({type:"text",content:X}))},fallbackText:B.parts.join(`
2473
2473
 
@@ -2539,7 +2539,7 @@ ${rWA(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 ab2={name:"@brains/webserver",version:"0.2.0-alpha.204",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 Nf extends bF{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",ab2,A,PUA)}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 FP0({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&&!tb2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(eb2(this.config.previewDistDir,"index.html"),bUA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!tb2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(eb2(this.config.productionDistDir,"index.html"),bUA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Kw();zA();v0();eC();var Aj2={name:"@brains/web-chat",version:"0.2.0-alpha.204",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 Qj2(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 wj2({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=O_("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=f_(X.metadata,B,"document",Y.mimeType);return Bj2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function $j2(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 wj2({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=O_("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=f_(X.metadata,B,"image",Y.mimeType);return Bj2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function wj2(A){let Q={entityType:A.entityType,id:A.id},$=await x_({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 Bj2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":Kk({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}v0();zA();var A50="upload",Xj2=Uc;var SU$={namespace:"upload",refKind:A50,routePath:"/api/chat/uploads"};function LP0(){return SU$}zA();La0();var Yj2=Uq0;var Zj2=Gq0;var mU$="file",uU$=16384;async function Wj2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=Number(A.headers.get("content-length"));if(Number.isFinite($)&&$>Zj2+uU$)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(mU$);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=C_({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 Hj2(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 Gj2($,Q.getUploadStore());if(w instanceof Response)return w;let{record:B,content:X}=w,Y=Dj2(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":Kk({disposition:Z,filename:B.filename})}})}function Kj2(A){let Q=v_(A.filename??Yj2),$=pU$(A.url);if(!$)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let w=C_({filename:Q,mediaType:A.mediaType,content:$.buffer});if(!w.ok)return new Response(w.message,{status:400});return qj2(w,$.buffer)}async function Uj2(A,Q){let $=await Gj2(A,Q);if($ instanceof Response)return $;let{record:w,content:B}=$,X=Dj2(w,B);if(X instanceof Response)return X;return qj2(X,B,{kind:A50,id:A})}async function Gj2(A,Q){try{return await Q.read(A)}catch($){if($ instanceof jF)return cU$($);throw $}}function Dj2(A,Q){let $=C_({filename:A.filename,mediaType:A.mediaType,content:Q});if(!$.ok)return new Response($.message,{status:400});return $}function qj2(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 cU$(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 pU$(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 lU$=W.object({type:W.literal("text"),text:W.string()}),iU$=W.object({type:W.literal("file"),mediaType:W.string().optional(),filename:W.string().optional(),url:W.string()}),dU$=W.looseObject({state:W.literal("approval-responded"),toolCallId:W.string().optional(),toolName:W.string().optional(),input:W.record(W.string(),W.unknown()).optional(),title:W.string().optional(),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()}),zj2=W.object({id:W.string().optional(),messages:W.array(nU$).min(1),trigger:W.string().optional()}),rU$=W.object({kind:W.literal(A50),id:W.string().regex(Xj2)}),oU$=W.object({type:W.literal("data-upload"),data:W.object({ref:rU$})});async function Jj2(A,Q){let $=sU$(A);if(!$)return{message:"",attachments:[]};let w=[],B=[];for(let Y of $.parts??[]){let Z=lU$.safeParse(Y);if(Z.success){if(Z.data.text.length>0)w.push(Z.data.text);continue}let H=iU$.safeParse(Y);if(H.success){let U=Kj2(H.data);if(U instanceof Response)return U;B.push(U);continue}let K=oU$.safeParse(Y);if(K.success){let U=await Uj2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(aU$(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:w.length>0?w.join(`
2542
+ </html>`;var ab2={name:"@brains/webserver",version:"0.2.0-alpha.206",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 Nf extends bF{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",ab2,A,PUA)}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 FP0({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&&!tb2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(eb2(this.config.previewDistDir,"index.html"),bUA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!tb2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(eb2(this.config.productionDistDir,"index.html"),bUA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Kw();zA();v0();eC();var Aj2={name:"@brains/web-chat",version:"0.2.0-alpha.206",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 Qj2(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 wj2({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=O_("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=f_(X.metadata,B,"document",Y.mimeType);return Bj2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function $j2(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 wj2({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=O_("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=f_(X.metadata,B,"image",Y.mimeType);return Bj2({requestUrl:w,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function wj2(A){let Q={entityType:A.entityType,id:A.id},$=await x_({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 Bj2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":Kk({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}v0();zA();var A50="upload",Xj2=Uc;var SU$={namespace:"upload",refKind:A50,routePath:"/api/chat/uploads"};function LP0(){return SU$}zA();La0();var Yj2=Uq0;var Zj2=Gq0;var mU$="file",uU$=16384;async function Wj2(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let $=Number(A.headers.get("content-length"));if(Number.isFinite($)&&$>Zj2+uU$)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(mU$);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=C_({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 Hj2(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 Gj2($,Q.getUploadStore());if(w instanceof Response)return w;let{record:B,content:X}=w,Y=Dj2(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":Kk({disposition:Z,filename:B.filename})}})}function Kj2(A){let Q=v_(A.filename??Yj2),$=pU$(A.url);if(!$)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let w=C_({filename:Q,mediaType:A.mediaType,content:$.buffer});if(!w.ok)return new Response(w.message,{status:400});return qj2(w,$.buffer)}async function Uj2(A,Q){let $=await Gj2(A,Q);if($ instanceof Response)return $;let{record:w,content:B}=$,X=Dj2(w,B);if(X instanceof Response)return X;return qj2(X,B,{kind:A50,id:A})}async function Gj2(A,Q){try{return await Q.read(A)}catch($){if($ instanceof jF)return cU$($);throw $}}function Dj2(A,Q){let $=C_({filename:A.filename,mediaType:A.mediaType,content:Q});if(!$.ok)return new Response($.message,{status:400});return $}function qj2(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 cU$(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 pU$(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 lU$=W.object({type:W.literal("text"),text:W.string()}),iU$=W.object({type:W.literal("file"),mediaType:W.string().optional(),filename:W.string().optional(),url:W.string()}),dU$=W.looseObject({state:W.literal("approval-responded"),toolCallId:W.string().optional(),toolName:W.string().optional(),input:W.record(W.string(),W.unknown()).optional(),title:W.string().optional(),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()}),zj2=W.object({id:W.string().optional(),messages:W.array(nU$).min(1),trigger:W.string().optional()}),rU$=W.object({kind:W.literal(A50),id:W.string().regex(Xj2)}),oU$=W.object({type:W.literal("data-upload"),data:W.object({ref:rU$})});async function Jj2(A,Q){let $=sU$(A);if(!$)return{message:"",attachments:[]};let w=[],B=[];for(let Y of $.parts??[]){let Z=lU$.safeParse(Y);if(Z.success){if(Z.data.text.length>0)w.push(Z.data.text);continue}let H=iU$.safeParse(Y);if(H.success){let U=Kj2(H.data);if(U instanceof Response)return U;B.push(U);continue}let K=oU$.safeParse(Y);if(K.success){let U=await Uj2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(aU$(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 Vj2(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map(($)=>dU$.safeParse($)).filter(($)=>$.success).map(($)=>({...$.data.approval,...$.data.toolCallId?{toolCallId:$.data.toolCallId}:{},...$.data.toolName?{toolName:$.data.toolName}:{},...$.data.input?{input:$.data.input}:{},...$.data.title?{title:$.data.title}:{}}))}function sU$(A){for(let Q=A.messages.length-1;Q>=0;Q-=1){let $=A.messages[Q];if($?.role==="user")return $}return}function aU$(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}zA();var tU$=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function Q50(A){return A.replace(tU$,"").trimEnd()}zA();function Fj2(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 jUA(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=Fq0(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
 
@@ -5830,7 +5830,7 @@ ${fj2}</style></head><body>${w50(A)}<main id="root" data-web-chat-root>Brain Cha
5830
5830
  `);X=Z.pop()??"";for(let H of Z){let K=H.split(`
5831
5831
  `).find((F)=>F.startsWith("data: "));if(!K)continue;let U;try{let F=dG$.safeParse(JSON.parse(K.slice(6)));if(!F.success)continue;U=F.data}catch{return await SUA(w),{success:!1,error:"Malformed SSE event from remote agent"}}let G=U.result;if(!G?.final)continue;await SUA(w);let D=G.status,q=D?.state??"unknown",L=(D?.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:q,response:L}}}Y=await ZM2(w,Q,$)}return{success:!1,error:"Stream ended without a terminal event"}}class mUA extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class X50 extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function HM2(A,Q,$,w,B){return yUA((X)=>A(Q,{...$,signal:X}),{timeoutMs:w,onTimeout:()=>new mUA(w),signal:B})}async function ZM2(A,Q,$){try{return await yUA(()=>A.read(),{timeoutMs:Q,onTimeout:()=>new X50(Q),signal:$})}catch(w){if(w instanceof X50||$?.aborted)await SUA(A,w);throw w}}async function SUA(A,Q){try{await A.cancel(Q)}catch{}}function QD$(A){if(A instanceof mUA||A instanceof X50)return!1;return A instanceof Error}function gUA(A,Q){let $=Q>1?` after ${Q} attempts`:"";if(A instanceof X50)return`${A.message}${$}`;let w=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${$}: ${w}`}async function uUA(A,Q={},$={}){let w=Q.fetch??globalThis.fetch,B=$.signal;B?.throwIfAborted();let X={requestTimeoutMs:Q.requestTimeoutMs??nG$,streamIdleTimeoutMs:Q.streamIdleTimeoutMs??rG$,maxNetworkAttempts:Q.maxNetworkAttempts??oG$},Y=tG$(A.agent);if(!Y.ok)return{success:!1,error:Y.error};let{agentId:Z}=Y;if(!Q.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let H=await Q.entityService.getEntity({entityType:"agent",id:Z,visibilityScope:p7("agent_call is anchor-only and resolves saved remote agents at any visibility")});if(B?.throwIfAborted(),!H){if($.requireSaved)return{success:!1,error:`Agent ${Z} is not saved or approved.`,code:"agent_not_saved"};if(!eG$(Z))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 D=`https://${Z}`,q=await XM2(D,w,X.requestTimeoutMs,B);if(!q)return{success:!1,error:`Could not verify an A2A Agent Card for ${Z}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let V=BM2(q.url,Z);if(!V.ok)return{success:!1,error:V.error};let L=await YM2(q.url,A.message,w,Q.requestSigner,X,B);if("success"in L&&L.success===!0){let F=typeof L.data==="object"&&L.data!==null?L.data:{};return{...L,data:{...F,agentCall:{mode:"one-shot",agent:Z},agentContactCandidate:{source:{kind:"url",url:Y.sourceUrl??Z}}}}}return L}if(H.metadata.status==="archived")return{success:!1,error:`Agent ${Z} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(H.metadata.status!=="approved")return{success:!1,error:`Agent ${Z} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let K=`https://${Z}`,U=await XM2(K,w,X.requestTimeoutMs,B);if(!U)return{success:!1,error:`Could not fetch Agent Card from ${K}`};let G=BM2(U.url,Z);if(!G.ok)return{success:!1,error:G.error};return YM2(U.url,A.message,w,Q.requestSigner,X,B)}function KM2(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:sG$,visibility:"trusted",sideEffects:"external",handler:async(Q,$)=>{let w=aG$.safeParse(Q);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};return uUA(w.data,A,{...$.signal?{signal:$.signal}:{}})}}}zA();v0();var $D$=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 UM2(A,Q){A.messaging.subscribe("a2a:call:request",async($)=>{let w=$D$.safeParse($.payload);if(!w.success)return{success:!1,error:"Invalid A2A call request"};let{agent:B,instruction:X,selection:Y}=w.data,Z=await uUA({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 cUA={name:"@brains/a2a",version:"0.2.0-alpha.204",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 BD$={"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 Gn extends bF{agentCard;taskManager=new EUA;turnSupervisor=new TUA;agentService;jwksResolver=new CUA;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",cUA,A,dj2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,UM2(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)=>$10.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=nj2({character:Q,profile:$,version:cUA.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}`,IO(A)),B=await pj2({method:A.method,url:w.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await vY()?.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(BD$))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 Zn;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 rj2(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=aj2.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=QM2.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=$M2(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 tj2(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=vY();if(!A)return;let Q=A.getIssuer();if(LO(Q)||new URL(Q).protocol!=="https:")return;return async($)=>{let w=await A.getA2ASigningKey();await cj2($,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[KM2(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();v0();var GM2={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 DM2={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 qM2={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 zM2={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 JM2={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 VM2={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 FM2={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 LM2={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 IM2={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 qD$=W.object({type:W.string()}).catchall(W.unknown()),zD$=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(),qD$)})})})});function MJ(A){return zD$.parse(A)}var i8={"ai.rizom.brain.card":MJ(GM2),"ai.rizom.brain.deck":MJ(DM2),"ai.rizom.brain.link":MJ(qM2),"ai.rizom.brain.note":MJ(zM2),"ai.rizom.brain.post":MJ(JM2),"ai.rizom.brain.project":MJ(VM2),"ai.rizom.brain.series":MJ(FM2),"ai.rizom.brain.socialPost":MJ(LM2),"ai.rizom.brain.topic":MJ(IM2)},JD$="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function tP(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:JD$}}var NM2={"ai.rizom.brain.card":tP("@brains/atproto"),"ai.rizom.brain.deck":tP("@brains/decks"),"ai.rizom.brain.link":tP("@brains/link"),"ai.rizom.brain.note":tP("@brains/note"),"ai.rizom.brain.post":tP("@brains/blog"),"ai.rizom.brain.project":tP("@brains/portfolio"),"ai.rizom.brain.series":tP("@brains/series"),"ai.rizom.brain.socialPost":tP("@brains/social-media"),"ai.rizom.brain.topic":tP("@brains/topics")};function Dn(){return Object.values(i8)}function bP0(A){if(!(A in i8))return;return i8[A]}function jP0(){return Object.entries(NM2).map(([A,Q])=>({id:A,...Q}))}v0();function MP0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var VD$=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function FD$(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)=>VD$.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 _M2(A){switch(A.type){case"string":return FD$(A);case"integer":return W.number().int();case"boolean":return W.boolean();case"array":{let Q=A.items?_M2(A.items):W.unknown(),$=W.array(Q);if(A.maxLength!==void 0)$=$.max(A.maxLength);return $}case"object":return LD$(A);case"blob":return W.custom(MP0,{message:"expected blob"});default:return W.unknown()}}function PM2(A){let Q=new Set(A.required??[]),$={};for(let[w,B]of Object.entries(A.properties??{})){let X=_M2(B);$[w]=Q.has(w)?X:X.optional()}return $}function LD$(A){return W.object(PM2(A)).passthrough()}function pUA(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 ID$(A,Q){if(pUA(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),MP0(A.brain))pUA(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(MP0(A.anchor))pUA(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function kJ(A){let Q=W.object({...PM2(A.defs.main.record),$type:W.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(ID$):Q}var lUA={"ai.rizom.brain.card":kJ(i8["ai.rizom.brain.card"]),"ai.rizom.brain.deck":kJ(i8["ai.rizom.brain.deck"]),"ai.rizom.brain.link":kJ(i8["ai.rizom.brain.link"]),"ai.rizom.brain.note":kJ(i8["ai.rizom.brain.note"]),"ai.rizom.brain.post":kJ(i8["ai.rizom.brain.post"]),"ai.rizom.brain.project":kJ(i8["ai.rizom.brain.project"]),"ai.rizom.brain.series":kJ(i8["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":kJ(i8["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":kJ(i8["ai.rizom.brain.topic"])};function ND$(A,Q){let $=A;for(let w of Q){if(typeof w==="symbol")return;if(Array.isArray($)){$=$[Number(w)];continue}if(!MP0($))return;$=$[String(w)]}return $}function _D$(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"&&ND$(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 eP(A,Q){let $=kJ(A).safeParse(Q);if($.success)return;let w=$.error.issues[0];if(!w)throw $.error;throw Error(_D$(A,Q,w))}v0();var Y50="atproto:brain-card-discovered",iUA="atproto:brain-discovered",dUA="atproto:brain-card-refreshed",PD$=W.custom((A)=>lUA["ai.rizom.brain.card"].safeParse(A).success),nUA=W.object({repoDid:W.string().min(1),uri:W.string().min(1),cid:W.string().min(1),record:PD$}).strict(),bD$=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}`)}}v0();var bM2={name:"@brains/atproto-registry",version:"0.2.0-alpha.204",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 MM2=W.object({enabled:W.boolean().default(!0)}),rUA="/atproto/lexicons",MD$=W.strictObject({nsid:W.string(),record:W.record(W.string(),W.unknown())});function jM2(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 cUA={name:"@brains/a2a",version:"0.2.0-alpha.206",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 BD$={"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 Gn extends bF{agentCard;taskManager=new EUA;turnSupervisor=new TUA;agentService;jwksResolver=new CUA;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",cUA,A,dj2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,UM2(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)=>$10.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=nj2({character:Q,profile:$,version:cUA.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}`,IO(A)),B=await pj2({method:A.method,url:w.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await vY()?.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(BD$))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 Zn;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 rj2(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=aj2.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=QM2.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=$M2(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 tj2(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=vY();if(!A)return;let Q=A.getIssuer();if(LO(Q)||new URL(Q).protocol!=="https:")return;return async($)=>{let w=await A.getA2ASigningKey();await cj2($,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[KM2(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();v0();var GM2={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 DM2={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 qM2={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 zM2={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 JM2={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 VM2={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 FM2={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 LM2={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 IM2={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 qD$=W.object({type:W.string()}).catchall(W.unknown()),zD$=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(),qD$)})})})});function MJ(A){return zD$.parse(A)}var i8={"ai.rizom.brain.card":MJ(GM2),"ai.rizom.brain.deck":MJ(DM2),"ai.rizom.brain.link":MJ(qM2),"ai.rizom.brain.note":MJ(zM2),"ai.rizom.brain.post":MJ(JM2),"ai.rizom.brain.project":MJ(VM2),"ai.rizom.brain.series":MJ(FM2),"ai.rizom.brain.socialPost":MJ(LM2),"ai.rizom.brain.topic":MJ(IM2)},JD$="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function tP(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:JD$}}var NM2={"ai.rizom.brain.card":tP("@brains/atproto"),"ai.rizom.brain.deck":tP("@brains/decks"),"ai.rizom.brain.link":tP("@brains/link"),"ai.rizom.brain.note":tP("@brains/note"),"ai.rizom.brain.post":tP("@brains/blog"),"ai.rizom.brain.project":tP("@brains/portfolio"),"ai.rizom.brain.series":tP("@brains/series"),"ai.rizom.brain.socialPost":tP("@brains/social-media"),"ai.rizom.brain.topic":tP("@brains/topics")};function Dn(){return Object.values(i8)}function bP0(A){if(!(A in i8))return;return i8[A]}function jP0(){return Object.entries(NM2).map(([A,Q])=>({id:A,...Q}))}v0();function MP0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var VD$=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function FD$(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)=>VD$.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 _M2(A){switch(A.type){case"string":return FD$(A);case"integer":return W.number().int();case"boolean":return W.boolean();case"array":{let Q=A.items?_M2(A.items):W.unknown(),$=W.array(Q);if(A.maxLength!==void 0)$=$.max(A.maxLength);return $}case"object":return LD$(A);case"blob":return W.custom(MP0,{message:"expected blob"});default:return W.unknown()}}function PM2(A){let Q=new Set(A.required??[]),$={};for(let[w,B]of Object.entries(A.properties??{})){let X=_M2(B);$[w]=Q.has(w)?X:X.optional()}return $}function LD$(A){return W.object(PM2(A)).passthrough()}function pUA(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 ID$(A,Q){if(pUA(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),MP0(A.brain))pUA(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(MP0(A.anchor))pUA(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function kJ(A){let Q=W.object({...PM2(A.defs.main.record),$type:W.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(ID$):Q}var lUA={"ai.rizom.brain.card":kJ(i8["ai.rizom.brain.card"]),"ai.rizom.brain.deck":kJ(i8["ai.rizom.brain.deck"]),"ai.rizom.brain.link":kJ(i8["ai.rizom.brain.link"]),"ai.rizom.brain.note":kJ(i8["ai.rizom.brain.note"]),"ai.rizom.brain.post":kJ(i8["ai.rizom.brain.post"]),"ai.rizom.brain.project":kJ(i8["ai.rizom.brain.project"]),"ai.rizom.brain.series":kJ(i8["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":kJ(i8["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":kJ(i8["ai.rizom.brain.topic"])};function ND$(A,Q){let $=A;for(let w of Q){if(typeof w==="symbol")return;if(Array.isArray($)){$=$[Number(w)];continue}if(!MP0($))return;$=$[String(w)]}return $}function _D$(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"&&ND$(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 eP(A,Q){let $=kJ(A).safeParse(Q);if($.success)return;let w=$.error.issues[0];if(!w)throw $.error;throw Error(_D$(A,Q,w))}v0();var Y50="atproto:brain-card-discovered",iUA="atproto:brain-discovered",dUA="atproto:brain-card-refreshed",PD$=W.custom((A)=>lUA["ai.rizom.brain.card"].safeParse(A).success),nUA=W.object({repoDid:W.string().min(1),uri:W.string().min(1),cid:W.string().min(1),record:PD$}).strict(),bD$=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}`)}}v0();var bM2={name:"@brains/atproto-registry",version:"0.2.0-alpha.206",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 MM2=W.object({enabled:W.boolean().default(!0)}),rUA="/atproto/lexicons",MD$=W.strictObject({nsid:W.string(),record:W.record(W.string(),W.unknown())});function jM2(A){return new Response(`${JSON.stringify(A,null,2)}
5834
5834
  `,{headers:{"Content-Type":"application/json"}})}class oUA extends d6{constructor(A={}){super("atproto-registry",bM2,A,MM2)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${rUA}/index.json`,method:"GET",public:!0,handler:()=>jM2(this.getIndex())},...Dn().map((A)=>({path:`${rUA}/${A.id}.json`,method:"GET",public:!0,handler:()=>jM2(A)}))]}getIndex(){return{lexicons:jP0().map((A)=>({...A,path:`${rUA}/${A.id}.json`}))}}getLexicon(A){return bP0(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=MD$.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 eP($,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:Dn().length,nsids:Dn().map((A)=>A.id),metadata:jP0()}})}}}function Z50(A={}){return new oUA(A)}zA();class sUA{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 $q$}from"events";import{stat as wq$,Stats as Lk5}from"fs";import{readdir as Bq$,stat as Xq$}from"fs/promises";import*as D8 from"path";import{lstat as kM2,readdir as kD$,realpath as OD$,stat as fD$}from"fs/promises";import{join as xD$,relative as RD$,resolve as OM2,sep as vD$}from"path";import{Readable as CD$}from"stream";var mG={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},aUA={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:mG.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(aUA);var vM2="READDIRP_RECURSIVE_ERROR",hD$=new Set(["ENOENT","EPERM","EACCES","ELOOP",vM2]),fM2=[mG.DIR_TYPE,mG.EVERYTHING_TYPE,mG.FILE_DIR_TYPE,mG.FILE_TYPE],ED$=new Set([mG.DIR_TYPE,mG.EVERYTHING_TYPE,mG.FILE_DIR_TYPE]),TD$=new Set([mG.EVERYTHING_TYPE,mG.FILE_DIR_TYPE,mG.FILE_TYPE]),yD$=(A)=>hD$.has(A.code),gD$=process.platform==="win32",xM2=(A)=>!0,RM2=(A)=>{if(A===void 0)return xM2;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 xM2};class tUA extends CD${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={...aUA,...A},{root:$,type:w}=Q;this._fileFilter=RM2(Q.fileFilter),this._directoryFilter=RM2(Q.directoryFilter);let B=Q.lstat?kM2:fD$;if(gD$)this._stat=(X)=>B(X,{bigint:!0});else this._stat=B;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:aUA.depth,this._wantsDir=w?ED$.has(w):!1,this._wantsFile=w?TD$.has(w):!1,this._wantsEverything=w===mG.EVERYTHING_TYPE,this._root=OM2($),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 kD$(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=OM2(xD$(Q,w));$={path:RD$(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(yD$(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 OD$($),B=await kM2(w);if(B.isFile())return"file";if(B.isDirectory()){let X=w.length;if($.startsWith(w)&&$.substr(X,1)===vD$){let Y=Error(`Circular symlink detected: "${$}" points to "${w}"`);return Y.code=vM2,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 CM2(A,Q={}){let $=Q.entryType||Q.type;if($==="both")$=mG.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($&&!fM2.includes($))throw Error(`readdirp: Invalid type passed. Use one of ${fM2.join(", ")}`);return Q.root=A,new tUA(Q)}import{watch as SD$,unwatchFile as hM2,watchFile as mD$}from"fs";import{realpath as eUA,lstat as uD$,open as cD$,stat as TM2}from"fs/promises";import{type as pD$}from"os";import*as TB from"path";var lD$="data",$GA="end",yM2="close",xP0=()=>{};var RP0=process.platform,wGA=RP0==="win32",iD$=RP0==="darwin",dD$=RP0==="linux",nD$=RP0==="freebsd",gM2=pD$()==="OS400",YB={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},OJ=YB,rD$="watch",oD$={lstat:uD$,stat:TM2},kT="listeners",kP0="errHandlers",qn="rawEmitters",sD$=[kT,kP0,qn],aD$=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"]),tD$=(A)=>aD$.has(TB.extname(A).slice(1).toLowerCase()),QGA=(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($)},eD$=(A)=>(Q)=>{let $=A[Q];if($ instanceof Set)$.clear();else delete A[Q]},H50=(A,Q,$)=>{let w=A[Q];if(w instanceof Set)w.delete($);else if(w===$)delete A[Q]},SM2=(A)=>A instanceof Set?A.size===0:!A,OP0=new Map;function EM2(A,Q,$,w,B){let X=(Y,Z)=>{if($(A),B(Y,Z,{watchedPath:A}),Z&&A!==Z)fP0(TB.resolve(A,Z),kT,TB.join(A,Z))};try{return SD$(A,{persistent:Q.persistent},X)}catch(Y){w(Y);return}}var fP0=(A,Q,$,w,B)=>{let X=OP0.get(A);if(!X)return;QGA(X[Q],(Y)=>{Y($,w,B)})},Aq$=(A,Q,$,w)=>{let{listener:B,errHandler:X,rawEmitter:Y}=w,Z=OP0.get(Q),H;if(!$.persistent){if(H=EM2(A,$,B,X,Y),!H)return;return H.close.bind(H)}if(Z)W50(Z,kT,B),W50(Z,kP0,X),W50(Z,qn,Y);else{if(H=EM2(A,$,fP0.bind(null,Q,kT),X,fP0.bind(null,Q,qn)),!H)return;H.on(OJ.ERROR,async(K)=>{let U=fP0.bind(null,Q,kP0);if(Z)Z.watcherUnusable=!0;if(wGA&&K.code==="EPERM")try{await(await cD$(A,"r")).close(),U(K)}catch(G){}else U(K)}),Z={listeners:B,errHandlers:X,rawEmitters:Y,watcher:H},OP0.set(Q,Z)}return()=>{if(H50(Z,kT,B),H50(Z,kP0,X),H50(Z,qn,Y),SM2(Z.listeners))Z.watcher.close(),OP0.delete(Q),sD$.forEach(eD$(Z)),Z.watcher=void 0,Object.freeze(Z)}},AGA=new Map,Qq$=(A,Q,$,w)=>{let{listener:B,rawEmitter:X}=w,Y=AGA.get(Q),Z=Y&&Y.options;if(Z&&(Z.persistent<$.persistent||Z.interval>$.interval))hM2(Q),Y=void 0;if(Y)W50(Y,kT,B),W50(Y,qn,X);else Y={listeners:B,rawEmitters:X,options:$,watcher:mD$(Q,$,(H,K)=>{QGA(Y.rawEmitters,(G)=>{G(OJ.CHANGE,Q,{curr:H,prev:K})});let U=H.mtimeMs;if(H.size!==K.size||U>K.mtimeMs||U===0)QGA(Y.listeners,(G)=>G(A,H))})},AGA.set(Q,Y);return()=>{if(H50(Y,kT,B),H50(Y,qn,X),SM2(Y.listeners))AGA.delete(Q),hM2(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class BGA{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=xP0;let H;if($.usePolling){let K=$.interval!==$.binaryInterval;Z.interval=K&&tD$(B)?$.binaryInterval:$.interval,H=Qq$(A,Y,Z,{listener:Q,rawEmitter:this.fsw._emitRaw})}else H=Aq$(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(rD$,A,5))return;if(!U||U.mtimeMs===0)try{let G=await TM2(A);if(this.fsw.closed)return;let{atimeMs:D,mtimeMs:q}=G;if(!D||D<=q||q!==Y.mtimeMs)this.fsw._emit(OJ.CHANGE,A,G);if((iD$||dD$||nD$)&&Y.ino!==G.ino){this.fsw._closeFile(K),Y=G;let V=this._watchWithNodeFs(A,Z);if(V)this.fsw._addPathCloser(K,V)}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(OJ.CHANGE,A,U);Y=U}},H=this._watchWithNodeFs(A,Z);if(!($&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(OJ.ADD,A,0))return;this.fsw._emit(OJ.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 eUA($)}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(OJ.CHANGE,$,A.stats)}else X.add(w),this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(OJ.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(lD$,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(OJ.ERROR,this._boundHandleError),new Promise((G,D)=>{if(!U)return D();U.once($GA,()=>{if(this.fsw.closed){U=void 0;return}let q=Y?Y.clear():!1;if(G(void 0),H.getChildren().filter((V)=>{return V!==A&&!K.has(V)}).forEach((V)=>{this.fsw._remove(A,V)}),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(OJ.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 oD$[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 eUA(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 eUA(A):A;if(this.fsw.closed)return;let G=TB.dirname(Y.watchPath);if(this.fsw._getWatchedDir(G).add(Y.watchPath),this.fsw._emit(OJ.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 XGA="/",Yq$="//",lM2=".",Zq$="..",Wq$="string",Hq$=/\\/g,iM2=/\/\//g,Kq$=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,Uq$=/^\.[/\\]/;function vP0(A){return Array.isArray(A)?A:[A]}var YGA=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function Gq$(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 Dq$(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(iM2,"/"),Q)A="/"+A;return A}function mM2(A,Q,$){let w=Dq$(Q);for(let B=0;B<A.length;B++){let X=A[B];if(X(w,$))return!0}return!1}function qq$(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let w=vP0(A).map((B)=>Gq$(B));if(Q==null)return(B,X)=>{return mM2(w,B,X)};return mM2(w,Q)}var uM2=(A)=>{let Q=vP0(A).flat();if(!Q.every(($)=>typeof $===Wq$))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(dM2)},cM2=(A)=>{let Q=A.replace(Hq$,XGA),$=!1;if(Q.startsWith(Yq$))$=!0;if(Q=Q.replace(iM2,XGA),$)Q=XGA+Q;return Q},dM2=(A)=>cM2(D8.normalize(cM2(A))),pM2=(A="")=>(Q)=>{if(typeof Q==="string")return dM2(D8.isAbsolute(Q)?Q:D8.join(A,Q));else return Q},zq$=(A,Q)=>{if(D8.isAbsolute(A))return A;return D8.join(Q,A)},Jq$=Object.freeze(new Set);class nM2{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!==lM2&&A!==Zq$)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 Bq$($)}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=xP0,this.items=Jq$,Object.freeze(this)}}var Vq$="stat",Fq$="lstat";class rM2{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,$){this.fsw=$;let w=A;this.path=A=A.replace(Uq$,""),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?Vq$:Fq$}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 ZGA extends $q${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?vP0(A.ignored):vP0([]),awaitWriteFinish:Q===!0?$:typeof Q==="object"?{...$,...Q}:!1};if(gM2)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=xP0,this._readyEmitted=!0,process.nextTick(()=>this.emit(YB.READY))},this._emitRaw=(...Z)=>this.emit(YB.RAW,...Z),this._boundRemove=this._remove.bind(this),this.options=w,this._nodeFsHandler=new BGA(this),Object.freeze(w)}_addIgnoredPath(A){if(YGA(A)){for(let Q of this._ignoredPaths)if(YGA(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(YGA(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=uM2(A);if(w)B=B.map((X)=>{return zq$(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=uM2(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,$):$)||lM2;A[B]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==YB.ERROR)this.emit(YB.ALL,A,...Q)}async _emit(A,Q,$){if(this.closed)return;let w=this.options;if(wGA)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===YB.UNLINK)return this._pendingUnlinks.set(Q,[A,...B]),setTimeout(()=>{this._pendingUnlinks.forEach((Z,H)=>{this.emit(...Z),this.emit(YB.ALL,...Z),this._pendingUnlinks.delete(H)})},typeof w.atomic==="number"?w.atomic:100),this;if(A===YB.ADD&&this._pendingUnlinks.has(Q))A=YB.CHANGE,this._pendingUnlinks.delete(Q)}if(X&&(A===YB.ADD||A===YB.CHANGE)&&this._readyEmitted){let Z=(H,K)=>{if(H)A=YB.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===YB.CHANGE){if(!this._throttle(YB.CHANGE,Q,50))return this}if(w.alwaysStat&&$===void 0&&(A===YB.ADD||A===YB.ADD_DIR||A===YB.CHANGE)){let Z=w.cwd?D8.join(w.cwd,Q):Q,H;try{H=await Xq$(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(YB.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){wq$(Z,(D,q)=>{if(D||!K.has(A)){if(D&&D.code!=="ENOENT")w(D);return}let V=Number(new Date);if(G&&q.size!==G.size)K.get(A).lastChange=V;let L=K.get(A);if(V-L.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&&Kq$.test(A))return!0;if(!this._userIgnored){let{cwd:$}=this.options,B=(this.options.ignored||[]).map(pM2($)),Y=[...[...this._ignoredPaths].map(pM2($)),...B];this._userIgnored=qq$(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new rM2(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=D8.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new nM2(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()===YB.ADD)return}this._watched.delete(w),this._watched.delete(B);let U=$?YB.UNLINK_DIR:YB.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:YB.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},w=CM2(A,$);return this._streams.add(w),w.once(yM2,()=>{w=void 0}),w.once($GA,()=>{if(w)this._streams.delete(w),w=void 0}),w}}function Lq$(A,Q={}){let $=new ZGA(Q);return $.add(A),$}var oM2={watch:Lq$,FSWatcher:ZGA};v8();import{extname as Iq$}from"path";var CP0=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function OT(A){let Q=Iq$(A).toLowerCase();return CP0.includes(Q)}function sM2(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 WGA(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as Nq$,relative as _q$,sep as aM2,join as Pq$}from"path";function Gz(A,Q){return Nq$(Q)?Q:Pq$(A,Q)}function zn(A,Q){let $=Gz(A,Q),w=_q$(A,$);return aM2==="/"?w:w.split(aM2).join("/")}function bq$(A,Q){if(!zn(Q,A).startsWith("image/"))return!1;return OT(A)}function jq$(A,Q){if(zn(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return bq$(A,Q)}class HGA{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=r0.runSync(j2.make()),this.delayedBatches=r0.runSync(j2.extend(zw.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=oM2.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||!jq$(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let $=zn(this.syncPath,Q);this.pendingChanges.set($,A);let w=r0.sleep(500).pipe(r0.andThen(r0.sync(()=>this.startPendingProcessing()))),B=this.clock?r0.withClock(w,this.clock):w;zw.unsafeSet(this.delayedBatches,"file-change-batch",r0.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=Gz(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 r0.runPromiseExit(j2.close(this.delayScope,R2.void));if(R2.isFailure(A))throw j$.squash(A.cause)}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}async function tM2(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return Mq$(Q)}async function eM2(A){await A?.stop()}function Ak2(A,Q){if(A)A.setCallback(Q)}async function Mq$(A){let{logger:Q,syncPath:$,watchInterval:w,importEntities:B,jobQueueCallback:X,fileOperations:Y,deleteOnFileRemoval:Z}=A,H=new sUA(Q,B,X,Y,Z),K=new HGA({syncPath:$,watchInterval:w,logger:Q,onFileChange:async(U,G)=>{await H.handleFileChange(U,G)}});return await K.start(),K}async function Qk2(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 KGA{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 UGA{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new KGA({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 GGA{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 vq$,dirname as Cq$,extname as hq$}from"path";import{extname as kq$}from"path";var hP0=[".pdf"],$k2=".meta.json";function fT(A){let Q=kq$(A).toLowerCase();return hP0.includes(Q)}function wk2(A){return A.toLowerCase().endsWith($k2)}function DGA(A){return`${A}${$k2}`}function Bk2(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as Oq$,join as EP0}from"path";function TP0(A,Q){let w=zn(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]=Xk2(Z);Y=X.join(":")}else Y=Xk2(X[0]??"");return{entityType:B,id:Y}}function Yk2(A,Q,$,w=".md"){let B=Q.split(":").filter((K)=>K.length>0),X=$==="note";if(B.length===1)return X?EP0(A,`${B[0]}${w}`):EP0(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 EP0(A,...H,`${Z}${w}`);return EP0(A,$,...H,`${Z}${w}`)}function Zk2(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return WGA(Q);let $=A.content.match(/^data:image\/([a-z+]+);base64,/i);return $?.[1]?WGA($[1]):".md"}function Xk2(A){let Q=Oq$(A).toLowerCase();return Q===".md"||CP0.includes(Q)||hP0.includes(Q)?A.slice(0,-Q.length):A}v0();yZ();import{mkdir as Eq$,readFile as Jn,writeFile as zGA,stat as Tq$,utimes as yq$}from"fs/promises";import{join as yP0}from"path";import{mkdir as Wk2,readdir as xq$,stat as Rq$}from"fs/promises";import{access as fq$}from"fs/promises";async function D7(A){try{return await fq$(A),!0}catch{return!1}}async function qGA(A,Q){return Gk2(A,Q,{includeDocuments:!1,includeImages:!1})}async function Hk2(A,Q){return Gk2(A,Q,{includeDocuments:!0,includeImages:!0})}async function Kk2(A,Q){if(!await D7(A))await Wk2(A,{recursive:!0});for(let $ of Q)if($!=="note")await Wk2(yP0(A,$),{recursive:!0})}async function Uk2(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=yP0(A,X),Z=await Rq$(Y),{entityType:H}=TP0(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 Gk2(A,Q,$){let w=[];if(!await D7(A))return w;let B=async(X,Y="",Z=!1,H=!1)=>{let K=await xq$(X,{withFileTypes:!0});for(let U of K){let G=Y?yP0(Y,U.name):U.name;if(U.isFile()&&!U.name.endsWith(".invalid")&&!wk2(U.name)){if(U.name.endsWith(".md"))w.push(G);else if($.includeImages&&Z&&OT(U.name))w.push(G);else if($.includeDocuments&&H&&fT(U.name))w.push(G)}else if(U.isDirectory()&&!U.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(U.name))continue;let D=yP0(X,U.name),q=U.name==="image"&&Y==="",V=U.name==="document"&&Y==="";await B(D,G,Z||q,H||V)}}};return await B(A),w}var gq$=W.record(W.string(),W.unknown());class JGA{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return TP0(this.syncPath,A)}async readEntity(A){let Q=Gz(this.syncPath,A),$=await Tq$(Q),{entityType:w,id:B}=this.parseEntityFromPath(A),X=$.birthtime.getTime()>0?$.birthtime:$.mtime,Y=$.mtime,Z,H;if(OT(A)||fT(A)){let G=(await Jn(Q)).toString("base64"),D=hq$(A);if(Z=`data:${fT(A)?Bk2(D):sM2(D)};base64,${G}`,fT(A))H=await this.readDocumentSidecar(Q,A)}else Z=await Jn(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:vq$(Q)},w=DGA(A);if(!await D7(w))return $;try{let B=await Jn(w,"utf-8"),X=gq$.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 Jn(Q),U=u6(K.toString("base64")),G=u6(Z.toString("base64"));if(U===G)H=!0}if(!H)await this.ensureEntityDirectory(A,Q),await zGA(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 Jn(Q,"utf-8"),Z=u6(Y),H=u6(X);if(Z===H)return}await this.ensureEntityDirectory(A,Q),await zGA(Q,X,"utf-8")}let B=new Date(A.updated);await yq$(Q,B,B)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await Eq$(Cq$(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=DGA(Q),X=`${JSON.stringify(w,null,2)}
5835
5835
  `;if(await D7(B)){if(await Jn(B,"utf-8")===X)return}await this.ensureEntityDirectory(A,B),await zGA(B,X,"utf-8")}getFilePath(A,Q,$=".md"){return Yk2(this.syncPath,A,Q,$)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,Zk2(A))}async getAllMarkdownFiles(){return qGA(this.syncPath,this.entityService)}async getAllSyncFiles(){return Hk2(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await Kk2(this.syncPath,A)}shouldUpdateEntity(A,Q){let $=u6(Q.content);return A.contentHash!==$}async gatherFileStatus(){return Uk2(this.syncPath,this.entityService)}async syncDirectoryExists(){return D7(this.syncPath)}async fileExists(A){return D7(A)}}lZ();v0();u4();p2();lZ();async function gP0(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}=jk(Y),H=Wh(Z),K=Mk(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 Dk2=W.object({title:W.string(),slug:W.string().optional(),coverImageUrl:W.url(),coverImageId:W.string().optional(),coverImageAlt:W.string().optional()});class VGA{entityService;fetcher;logger;constructor(A,Q,$=yq){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=Dk2.safeParse($);if(!w.success)return null;if(w.data.coverImageId)return null;let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=w.data;if(!Zh(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=Dk2.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(!Zh(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:OC(U,Q.content),converted:!0,imageId:K}}catch(K){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:sA(K)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:$,sourceUrl:w,customAlt:B}=A,X=`Cover image for ${Q}`;return gP0({id:`${$}-cover`,title:X,alt:B??X,sourceUrl:w},this.entityService,this.fetcher,this.logger)}}lZ();class K50{entityService;fetcher;logger;constructor(A,Q,$=yq){this.entityService=A,this.fetcher=$,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let $=[],w=iAA(A);for(let B of w){if(!Zh(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:sA(Z)})}return{content:w,converted:B>0,convertedCount:B}}async createImageEntity(A,Q){let{sourceUrl:$,alt:w,postSlug:B}=A;return gP0({id:`${B}-inline-${Q}`,title:w||`Inline image ${Q+1} for ${B}`,alt:w||"",sourceUrl:$},this.entityService,this.fetcher,this.logger)}}class FGA{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 Sq$,appendFile as mq$,readFile as uq$,writeFile as cq$,access as pq$}from"fs/promises";import{join as qk2}from"path";class LGA{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return lD0(A)}async quarantineInvalidFile(A,Q,$,w){let B=w(A),X=`${B}.invalid`;try{await Sq$(B,X),$.quarantined++,$.quarantinedFiles.push(A);let Y=qk2(this.syncPath,".import-errors.log"),Z=new Date().toISOString(),H=sA(Q),K=`${Z} - ${A}: ${H}
5836
5836
  \u2192 ${A}.invalid
@@ -5859,7 +5859,7 @@ ${fj2}</style></head><body>${w50(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 Kb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:NDA,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 Ub0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:IDA,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();v8();var WF$=300000,HF$=500;async function tx2(A){if(A.jobIds.length===0)return;let Q=A.maxWaitMs??WF$,$=A.pollIntervalMs??HF$;A.logger.debug(`Waiting for ${A.jobIds.length} import jobs to complete`);let w=r0.gen(function*(){let Y=yield*QH.currentTimeMillis;yield*r0.gen(function*(){let K=(yield*r0.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*QH.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*r0.tryPromise({try:()=>A.reporter.report({progress:50+Math.round(G*0.05),message:`Processing ${K}/${A.jobIds.length} entities`}),catch:(D)=>D}),!1}).pipe(r0.repeat({schedule:JK.spaced($),until:(H)=>H}))}),B=A.clock?r0.withClock(w,A.clock):w,X=await r0.runPromiseExit(B);if(R2.isFailure(X))throw j$.squash(X.cause)}class Gb0 extends H8{getDirectorySync;context;constructor(A,Q,$){super(A,{schema:FDA,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 tx2({jobIds:A,entityService:this.context.entityService,reporter:Q,logger:this.logger})}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}zA();class Db0 extends H8{context;getDirectorySync;getGitSync;constructor(A,Q,$,w){super(A,{schema:LDA,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`}),KF$(X)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function KF$(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}zA();class qb0 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();v0();var UF$=W.object({});class zb0 extends H8{directorySync;constructor(A,Q){super(A,{schema:UF$,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();lZ();u4();Kw();v0();lZ();import{readFile as GF$,writeFile as DF$}from"fs/promises";var qF$=_DA,zF$=W.record(W.string(),W.unknown());class Jb0 extends H8{context;fetcher;constructor(A,Q,$=yq){super(Q,{schema:qF$,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 GF$(w,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:w,error:sA(F)}),r5.failure(F)}let K;try{K=t8(H)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:w,error:sA(F)}),r5.failure(F)}let U=zF$.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 F;try{F=await this.fetcher(B)}catch(R){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:sA(R)}),r5.failure(R)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let{base64:_}=jk(F),j=Wh(_),b=Mk(_);if(!j||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),r5.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let k=`Cover image for ${X}`,v=Z??k;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:F,metadata:{title:k,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 V={...G};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=q;let L=OC(V,K.content);try{await DF$(w,L,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:w,error:sA(F)}),r5.failure(F)}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:sA(H)}),r5.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}zA();lZ();Kw();import{readFile as JF$,writeFile as VF$}from"fs/promises";class Vb0 extends H8{converter;constructor(A,Q,$=yq){super(Q,{schema:PDA,jobTypeName:"inline-image-convert"});this.converter=new K50(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 JF$(w,"utf-8")}catch(H){let K=sA(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 VF$(w,Z.content,"utf-8")}catch(H){let K=sA(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=sA(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 ex2(A,Q,$,w=()=>Q,B){let X=(Y)=>$.child(Y);A.jobs.registerHandler("directory-sync",new Gb0(X("DirectorySyncJobHandler"),A,w)),A.jobs.registerHandler("directory-export",new Kb0(X("DirectoryExportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-import",new Ub0(X("DirectoryImportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-delete",new qb0(X("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new zb0(X("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Jb0(A,X("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Vb0(A,X("InlineImageConversionJobHandler"))),$.debug("Registered async job handlers")}zA();v0();import{unlink as FF$,access as LF$}from"fs/promises";var IF$=W.record(W.string(),W.unknown());function AR2(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 LF$(U).then(()=>!0,()=>!1))await FF$(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 bDA(A,Q,$,w){Q.setJobQueueCallback(async(B)=>{let X=await w?.startRun("watcher","importing"),Y=[{type:B.type,data:IF$.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 wR2,mkdir as _F$,copyFile as PF$}from"fs/promises";import{join as $R2,resolve as jDA}from"path";import{join as NF$}from"path";async function QR2(A){if(!await D7(NF$(A,".git")))return!1;try{return await fJ(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function bF$(A,Q){if(!await D7(A))return!0;if((await wR2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await QR2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function BR2(A,Q){let $=await wR2(A,{withFileTypes:!0});for(let w of $){let B=$R2(A,w.name),X=$R2(Q,w.name);if(w.isDirectory()){if(!await D7(X))await _F$(X,{recursive:!0});await BR2(B,X)}else await PF$(B,X)}}async function XR2(A,Q,$){let w=jDA(process.cwd(),A);$=$?jDA($):jDA(process.cwd(),"seed-content");let B=await bF$(w,Q);if(B&&await D7($))Q.debug("Copying seed content to brain-data directory"),await BR2($,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 YR2(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 XR2(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:vC.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){w.error("Initial sync failed",H),await A.messaging.send({type:vC.initialSyncCompleted,payload:{success:!1,error:sA(H)},...{broadcast:!0}})}};A.messaging.subscribe(vC.pluginsRegistered,async()=>{return w.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}function ZR2(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 WR2(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 V=await Q.queueSyncBatch($,"periodic-sync");return{files:q.files,result:V}},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 KR2}from"child_process";import{cpSync as jF$,existsSync as HR2,mkdirSync as MF$,mkdtempSync as kF$,rmSync as OF$}from"fs";import{tmpdir as fF$}from"os";import{fileURLToPath as xF$}from"url";import{join as RF$,resolve as vF$}from"path";function jf(A,Q){let $=KR2("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 CF$(A){return A.startsWith("file://")}function hF$(A){return xF$(A)}function EF$(A,Q){return KR2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function UR2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!CF$(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",$=hF$(A.gitUrl),w=vF$(A.seedContentPath);if(!HR2(w))throw Error(`Seed content path not found: ${w}`);if(!HR2($))A.logger.debug("Creating local bare content remote",{remotePath:$,branch:Q}),MF$($,{recursive:!0}),jf(process.cwd(),["init","--bare",`--initial-branch=${Q}`,$]);if(EF$($,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=kF$(RF$(fF$(),"directory-sync-seed-"));try{jf(B,["init",`--initial-branch=${Q}`]),jf(B,["config","user.name",A.authorName??"Brain"]),jf(B,["config","user.email",A.authorEmail??"brain@localhost"]),jF$(w,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),jf(B,["add","."]),jf(B,["commit","-m","seed content remote"]),jf(B,["remote","add","origin",A.gitUrl]),jf(B,["push","-u","origin",Q])}finally{OF$(B,{recursive:!0,force:!0})}}function GR2(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 TF$(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 TF$(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();v0();async function Fb0(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();v0();function DR2(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 kY(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function qR2(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 Fb0({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 kY(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 kY(Y instanceof Error?Y.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(w)X.push(DR2($,w));return X}zA();v0();import{isAbsolute as zR2,relative as yF$}from"path";var IR2=W.enum(["manual","periodic","watcher","save"]),gF$=W.enum(["pulling","scanning","importing","settling"]),NR2={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()},SF$=W.object({id:W.string().min(1),source:IR2,state:gF$,startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...NR2}),mF$=W.object({id:W.string().min(1),source:IR2,outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1).max(240),...NR2}),uF$=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()}),JR2=W.object({activeRun:SF$.optional(),recentRuns:W.array(mF$).max(5),issues:W.array(uF$).max(8)}),cF$=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()}),VR2={imported:0,skipped:0,failed:0,quarantined:0,exported:0},pF$={recentRuns:[],issues:[]},lF$="directory-sync.operation-status",FR2="current";class MDA{store;jobs;logger;syncPath;statePromise;writeQueue=Promise.resolve();constructor(A,Q,$,w){this.store=A.scoped({namespace:lF$,schema:JR2}),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(),...VR2},$})}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=Lb0(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,...VR2,...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=cF$.safeParse(iF$($.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(FR2).then((A)=>A??structuredClone(pF$)),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(FR2,JR2.parse(A))}prependRecent(A,Q,$,w){let B={id:Q.id,source:Q.source,outcome:$,startedAt:Q.startedAt,completedAt:new Date().toISOString(),summary:Lb0(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}:${$??Lb0(Q.message,80)}`,kind:Q.kind,...$?{path:$}:{},message:Lb0(Q.message),occurredAt:new Date().toISOString()};A.issues=[w,...A.issues.filter((B)=>B.id!==w.id)].slice(0,8)}safePath(A){if(!zR2(A))return LR2(A);let Q=yF$(this.syncPath,A);if(Q.startsWith("..")||zR2(Q))return"content file";return LR2(Q)}}function iF$(A){if(typeof A!=="string")return A;try{return JSON.parse(A)}catch{return A}}function LR2(A){return A.replaceAll("\\","/").replace(/^\.\//,"").slice(0,300)||"content file"}function Lb0(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();v0();import{basename as dF$}from"path";var nF$=W.object({workspaceUrl:W.string()}),rF$=W.object({type:W.literal("sync-now")}),_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()},oF$=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(),..._R2}).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),..._R2})),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 kDA{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 oF$.parse({health:X,directory:{displayPath:dF$(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(!rF$.safeParse(w).success)throw Error("Invalid directory sync workspace action");let Y={interfaceType:"cms",userId:B.userId,userPermissionLevel:B.userPermissionLevel},Z=await Fb0({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:h_,payload:A});if(!("success"in Q)||!Q.success)return;let $=nF$.safeParse(Q.data);return $.success?$.data.workspaceUrl:void 0}toSafeGitStatus(A){let Q=A.files.slice(0,20).map((w)=>({path:sF$(w.path),status:w.status.trim()||"changed"})),$=aF$(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 sF$(A){let Q=A.replaceAll("\\","/").replace(/^\.\//,"");if(Q.startsWith("../")||Q.startsWith("/"))return"content file";return Q.slice(0,300)||"content file"}function aF$(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$/,"")}`}}v8();class Ib0{resourceScope;scheduleScope;periodicScope;delayScope;scheduleFibers;periodicFibers;delayedFibers;clock;activeOperations=new Set;activeFailures=[];nextPeriodicId=0;closePromise=null;closed=!1;constructor(A={}){this.resourceScope=r0.runSync(j2.make()),this.scheduleScope=r0.runSync(j2.make()),this.periodicScope=r0.runSync(j2.make()),this.delayScope=r0.runSync(j2.make()),this.scheduleFibers=r0.runSync(j2.extend(CZ.make(),this.scheduleScope)),this.periodicFibers=r0.runSync(j2.extend(zw.make(),this.periodicScope)),this.delayedFibers=r0.runSync(j2.extend(zw.make(),this.delayScope)),this.clock=A.clock}async acquire(A,Q){if(this.closed)throw Error("Directory sync runtime is closed");let $=r0.acquireRelease(r0.promise(A),(B)=>r0.promise(()=>Q(B))),w=await r0.runPromiseExit(j2.extend($,this.resourceScope));if(R2.isFailure(w))throw j$.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||zw.unsafeHas(this.periodicFibers,$))return;let Y=r0.tryPromise({try:Q,catch:(Z)=>Z}).pipe(r0.catchAll((Z)=>r0.sync(()=>{this.activeFailures.push(Z)})));zw.unsafeSet(this.periodicFibers,$,r0.runFork(Y),{onlyIfMissing:!0})},B=r0.sleep(A).pipe(r0.andThen(r0.sync(w)),r0.forever),X=this.clock?r0.withClock(B,this.clock):B;CZ.unsafeAdd(this.scheduleFibers,r0.runFork(X))}scheduleTrailing(A,Q,$){if(this.closed)return;let w=r0.sleep(Q).pipe(r0.andThen(r0.sync(()=>{this.trackActive($)}))),B=this.clock?r0.withClock(w,this.clock):w,X=r0.runFork(B);zw.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 r0.runPromiseExit(j2.close(A,R2.void));if(R2.isFailure(Q))throw j$.squash(Q.cause)}}function PR2(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 bR2(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 jR2={name:"@brains/directory-sync",version:"0.2.0-alpha.204",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 ODA extends d6{directorySync;gitSync;operationStatus;workspaceProvider;cmsWorkspaceUrl;runtime=new Ib0;directorySyncFacade=PR2(()=>this.requireDirectorySync());gitSyncFacade=bR2(()=>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",jR2,A,_50)}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:P50,basePrompt:"",formatter:new Hb0,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 MDA(A.runtimeState,A.jobs,this.logger.child("OperationStatus"),Q),await this.operationStatus.initialize(),this.config.autoSync)bDA(A,this.directorySync,Q,this.operationStatus);if(await this.registerJobHandlers(A),AR2(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 Db0(this.logger.child("DirectorySyncRequestJobHandler"),A,()=>this.requireDirectorySync(),()=>this.requireGitSync()));if(this.config.initialSync)YR2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync?this.gitSyncFacade:void 0);this.workspaceProvider=new kDA({context:A,pluginId:this.id,config:this.config,getDirectorySync:()=>this.requireDirectorySync(),getGitSync:()=>this.gitSync,operationStatus:this.operationStatus}),GR2(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 qR2(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 Ib0,w=this.createDirectorySync(Q,A),B;try{if(await w.initializeDirectory(),this.config.autoSync)bDA(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 mP0({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 UR2({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 VDA({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)ZR2($.messaging,()=>this.requireGitSync(),this.config.commitDebounce,this.logger.child("GitAutoCommit"),this.runtimeScheduler,this.operationStatus),this.gitAutoCommitRegistered=!0;if(this.config.autoSync)WR2(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){ex2(A,this.directorySyncFacade,this.logger,()=>this.requireDirectorySync(),this.requireOperationStatus())}}function CT(A={}){return new ODA(A)}v0();var Nb0="email:send",MR2=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();v0();var kR2={name:"@brains/email-resend",version:"0.2.0-alpha.204",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 AL$=W.object({apiKey:W.string().min(1).optional(),from:W.string().min(1).optional()}),QL$=W.looseObject({id:W.string().optional()});class OR2 extends d6{fetchImpl;constructor(A={},Q={}){super("email-resend",kR2,A,AL$);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(Nb0,async($)=>{let w=MR2.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=QL$.parse(await w.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function _b0(A={}){return new OR2(A)}zA();import{render as qn2}from"preact-render-to-string";import{h as zy}from"preact";function fR2(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]&&($=fR2(A[Q]))&&(w&&(w+=" "),w+=$)}else for($ in A)A[$]&&(w&&(w+=" "),w+=$);return w}function kn(){for(var A,Q,$=0,w="",B=arguments.length;$<B;$++)(A=arguments[$])&&(Q=fR2(A))&&(w&&(w+=" "),w+=Q);return w}var $L$=(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 $},wL$=(A,Q)=>({classGroupId:A,validator:Q}),yR2=(A=new Map,Q=null,$)=>({nextPart:A,validators:Q,classGroupId:$});var xR2=[];var BL$=(A)=>{let Q=YL$(A),{conflictingClassGroups:$,conflictingClassGroupModifiers:w}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return XL$(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return gR2(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=w[Y],K=$[Y];if(H){if(K)return $L$(K,H);return H}return K||xR2}return $[Y]||xR2}}},gR2=(A,Q,$)=>{if(A.length-Q===0)return $.classGroupId;let B=A[Q],X=$.nextPart.get(B);if(X){let K=gR2(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},XL$=(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})(),YL$=(A)=>{let{theme:Q,classGroups:$}=A;return ZL$($,Q)},ZL$=(A,Q)=>{let $=yR2();for(let w in A){let B=A[w];RDA(B,$,w,Q)}return $},RDA=(A,Q,$,w)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];WL$(Y,Q,$,w)}},WL$=(A,Q,$,w)=>{if(typeof A==="string"){HL$(A,Q,$);return}if(typeof A==="function"){KL$(A,Q,$,w);return}UL$(A,Q,$,w)},HL$=(A,Q,$)=>{let w=A===""?Q:SR2(Q,A);w.classGroupId=$},KL$=(A,Q,$,w)=>{if(GL$(A)){RDA(A(w),Q,$,w);return}if(Q.validators===null)Q.validators=[];Q.validators.push(wL$($,A))},UL$=(A,Q,$,w)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];RDA(H,SR2(Q,Z),$,w)}},SR2=(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=yR2(),$.nextPart.set(Y,Z);$=Z}return $},GL$=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,DL$=(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 qL$=[],RR2=(A,Q,$,w,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:$,maybePostfixModifierPosition:w,isExternal:B}),zL$=(A)=>{let{prefix:Q,experimentalParseClassName:$}=A,w=(B)=>{let X=[],Y=0,Z=0,H=0,K,U=B.length;for(let L=0;L<U;L++){let F=B[L];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(H,L)),H=L+1;continue}if(F==="/"){K=L;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")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 V=K&&K>H?K-H:void 0;return RR2(X,q,D,V)};if(Q){let B=Q+":",X=w;w=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):RR2(qL$,!1,Y,void 0,!0)}if($){let B=w;w=(X)=>$({className:X,parseClassName:B})}return w},JL$=(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}},VL$=(A)=>({cache:DL$(A.cacheSize),parseClassName:zL$(A),sortModifiers:JL$(A),postfixLookupClassGroupIds:FL$(A),...BL$(A)}),FL$=(A)=>{let Q=Object.create(null),$=A.postfixLookupClassGroups;if($)for(let w=0;w<$.length;w++)Q[$[w]]=!0;return Q},LL$=/\s+/,IL$=(A,Q)=>{let{parseClassName:$,getClassGroupId:w,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(LL$),K="";for(let U=H.length-1;U>=0;U-=1){let G=H[U],{isExternal:D,modifiers:q,hasImportantModifier:V,baseClassName:L,maybePostfixModifierPosition:F}=$(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!F,j;if(_){let O=L.substring(0,F);j=w(O);let g=j&&Y[j]?w(L):void 0;if(g&&g!==j)j=g,_=!1}else j=w(L);if(!j){if(!_){K=G+(K.length>0?" "+K:K);continue}if(j=w(L),!j){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=q.length===0?"":q.length===1?q[0]:X(q).join(":"),k=V?b+"!":b,v=k+j;if(Z.indexOf(v)>-1)continue;Z.push(v);let R=B(j,_);for(let O=0;O<R.length;++O){let g=R[O];Z.push(k+g)}K=G+(K.length>0?" "+K:K)}return K},NL$=(...A)=>{let Q=0,$,w,B="";while(Q<A.length)if($=A[Q++]){if(w=mR2($))B&&(B+=" "),B+=w}return B},mR2=(A)=>{if(typeof A==="string")return A;let Q,$="";for(let w=0;w<A.length;w++)if(A[w]){if(Q=mR2(A[w]))$&&($+=" "),$+=Q}return $},vR2=(A,...Q)=>{let $,w,B,X,Y=(H)=>{let K=Q.reduce((U,G)=>G(U),A());return $=VL$(K),w=$.cache.get,B=$.cache.set,X=Z,Z(H)},Z=(H)=>{let K=w(H);if(K)return K;let U=IL$(H,$);return B(H,U),U};return X=Y,(...H)=>X(NL$(...H))},_L$=[],$X=(A)=>{let Q=($)=>$[A]||_L$;return Q.isThemeGetter=!0,Q},uR2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,cR2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,PL$=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,bL$=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,jL$=/\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$/,ML$=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,kL$=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,OL$=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,Mf=(A)=>PL$.test(A),S$=(A)=>!!A&&!Number.isNaN(Number(A)),RL=(A)=>!!A&&Number.isInteger(Number(A)),fDA=(A)=>A.endsWith("%")&&S$(A.slice(0,-1)),Qb=(A)=>bL$.test(A),pR2=()=>!0,fL$=(A)=>jL$.test(A)&&!ML$.test(A),vDA=()=>!1,xL$=(A)=>kL$.test(A),RL$=(A)=>OL$.test(A),vL$=(A)=>!a2(A)&&!$Q(A),CL$=(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)),hL$=(A)=>kf(A,dR2,vDA),a2=(A)=>uR2.test(A),hT=(A)=>kf(A,nR2,fL$),CR2=(A)=>kf(A,cL$,S$),EL$=(A)=>kf(A,oR2,pR2),TL$=(A)=>kf(A,rR2,vDA),hR2=(A)=>kf(A,lR2,vDA),yL$=(A)=>kf(A,iR2,RL$),Pb0=(A)=>kf(A,sR2,xL$),$Q=(A)=>cR2.test(A),b50=(A)=>ET(A,nR2),gL$=(A)=>ET(A,rR2),ER2=(A)=>ET(A,lR2),SL$=(A)=>ET(A,dR2),mL$=(A)=>ET(A,iR2),bb0=(A)=>ET(A,sR2,!0),uL$=(A)=>ET(A,oR2,!0),kf=(A,Q,$)=>{let w=uR2.exec(A);if(w){if(w[1])return Q(w[1]);return $(w[2])}return!1},ET=(A,Q,$=!1)=>{let w=cR2.exec(A);if(w){if(w[1])return Q(w[1]);return $}return!1},lR2=(A)=>A==="position"||A==="percentage",iR2=(A)=>A==="image"||A==="url",dR2=(A)=>A==="length"||A==="size"||A==="bg-size",nR2=(A)=>A==="length",cL$=(A)=>A==="number",rR2=(A)=>A==="family-name",oR2=(A)=>A==="number"||A==="weight",sR2=(A)=>A==="shadow";var TR2=()=>{let A=$X("color"),Q=$X("font"),$=$X("text"),w=$X("font-weight"),B=$X("tracking"),X=$X("leading"),Y=$X("breakpoint"),Z=$X("container"),H=$X("spacing"),K=$X("radius"),U=$X("shadow"),G=$X("inset-shadow"),D=$X("text-shadow"),q=$X("drop-shadow"),V=$X("blur"),L=$X("perspective"),F=$X("aspect"),_=$X("ease"),j=$X("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],k=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...k(),$Q,a2],R=()=>["auto","hidden","clip","visible","scroll"],O=()=>["auto","contain","none"],g=()=>[$Q,a2,H],m=()=>[Mf,"full","auto",...g()],l=()=>[RL,"none","subgrid",$Q,a2],a=()=>["auto",{span:["full",RL,$Q,a2]},RL,$Q,a2],B0=()=>[RL,"auto",$Q,a2],p=()=>["auto","min","max","fr",$Q,a2],f=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],T=()=>["start","end","center","stretch","center-safe","end-safe"],E=()=>["auto",...g()],o=()=>[Mf,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...g()],t=()=>[Mf,"screen","full","dvw","lvw","svw","min","max","fit",...g()],q0=()=>[Mf,"screen","full","lh","dvh","lvh","svh","min","max","fit",...g()],S=()=>[A,$Q,a2],Y0=()=>[...k(),ER2,hR2,{position:[$Q,a2]}],F0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],d=()=>["auto","cover","contain",SL$,hL$,{size:[$Q,a2]}],c0=()=>[fDA,b50,hT],i0=()=>["","none","full",K,$Q,a2],N0=()=>["",S$,b50,hT],b0=()=>["solid","dashed","dotted","double"],C0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[S$,fDA,ER2,hR2],k0=()=>["","none",V,$Q,a2],O0=()=>["none",S$,$Q,a2],f0=()=>["none",S$,$Q,a2],m0=()=>[S$,$Q,a2],s0=()=>[Mf,"full",...g()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Qb],breakpoint:[Qb],color:[pR2],container:[Qb],"drop-shadow":[Qb],ease:["in","out","in-out"],font:[vL$],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Qb],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Qb],shadow:[Qb],spacing:["px",S$],text:[Qb],"text-shadow":[Qb],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",Mf,a2,$Q,F]}],container:["container"],"container-type":[{"@container":["","normal","size",$Q,a2]}],"container-named":[CL$],columns:[{columns:[S$,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:m()}],"inset-x":[{"inset-x":m()}],"inset-y":[{"inset-y":m()}],start:[{"inset-s":m(),start:m()}],end:[{"inset-e":m(),end:m()}],"inset-bs":[{"inset-bs":m()}],"inset-be":[{"inset-be":m()}],top:[{top:m()}],right:[{right:m()}],bottom:[{bottom:m()}],left:[{left:m()}],visibility:["visible","invisible","collapse"],z:[{z:[RL,"auto",$Q,a2]}],basis:[{basis:[Mf,"full","auto",Z,...g()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[S$,Mf,"auto","initial","none",a2]}],grow:[{grow:["",S$,$Q,a2]}],shrink:[{shrink:["",S$,$Q,a2]}],order:[{order:[RL,"first","last","none",$Q,a2]}],"grid-cols":[{"grid-cols":l()}],"col-start-end":[{col:a()}],"col-start":[{"col-start":B0()}],"col-end":[{"col-end":B0()}],"grid-rows":[{"grid-rows":l()}],"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:g()}],"gap-x":[{"gap-x":g()}],"gap-y":[{"gap-y":g()}],"justify-content":[{justify:[...f(),"normal"]}],"justify-items":[{"justify-items":[...T(),"normal"]}],"justify-self":[{"justify-self":["auto",...T()]}],"align-content":[{content:["normal",...f()]}],"align-items":[{items:[...T(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...T(),{baseline:["","last"]}]}],"place-content":[{"place-content":f()}],"place-items":[{"place-items":[...T(),"baseline"]}],"place-self":[{"place-self":["auto",...T()]}],p:[{p:g()}],px:[{px:g()}],py:[{py:g()}],ps:[{ps:g()}],pe:[{pe:g()}],pbs:[{pbs:g()}],pbe:[{pbe:g()}],pt:[{pt:g()}],pr:[{pr:g()}],pb:[{pb:g()}],pl:[{pl:g()}],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":g()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":g()}],"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",$,b50,hT]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[w,uL$,EL$]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",fDA,a2]}],"font-family":[{font:[gL$,TL$,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":[S$,"none",$Q,CR2]}],leading:[{leading:[X,...g()]}],"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:S()}],"text-color":[{text:S()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...b0(),"wavy"]}],"text-decoration-thickness":[{decoration:[S$,"from-font","auto",$Q,hT]}],"text-decoration-color":[{decoration:S()}],"underline-offset":[{"underline-offset":[S$,"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:g()}],"tab-size":[{tab:[RL,$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"]},RL,$Q,a2],radial:["",$Q,a2],conic:[RL,$Q,a2]},mL$,yL$]}],"bg-color":[{bg:S()}],"gradient-from-pos":[{from:c0()}],"gradient-via-pos":[{via:c0()}],"gradient-to-pos":[{to:c0()}],"gradient-from":[{from:S()}],"gradient-via":[{via:S()}],"gradient-to":[{to:S()}],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:S()}],"border-color-x":[{"border-x":S()}],"border-color-y":[{"border-y":S()}],"border-color-s":[{"border-s":S()}],"border-color-e":[{"border-e":S()}],"border-color-bs":[{"border-bs":S()}],"border-color-be":[{"border-be":S()}],"border-color-t":[{"border-t":S()}],"border-color-r":[{"border-r":S()}],"border-color-b":[{"border-b":S()}],"border-color-l":[{"border-l":S()}],"divide-color":[{divide:S()}],"outline-style":[{outline:[...b0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[S$,$Q,a2]}],"outline-w":[{outline:["",S$,b50,hT]}],"outline-color":[{outline:S()}],shadow:[{shadow:["","none",U,bb0,Pb0]}],"shadow-color":[{shadow:S()}],"inset-shadow":[{"inset-shadow":["none",G,bb0,Pb0]}],"inset-shadow-color":[{"inset-shadow":S()}],"ring-w":[{ring:N0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:S()}],"ring-offset-w":[{"ring-offset":[S$,hT]}],"ring-offset-color":[{"ring-offset":S()}],"inset-ring-w":[{"inset-ring":N0()}],"inset-ring-color":[{"inset-ring":S()}],"text-shadow":[{"text-shadow":["none",D,bb0,Pb0]}],"text-shadow-color":[{"text-shadow":S()}],opacity:[{opacity:[S$,$Q,a2]}],"mix-blend":[{"mix-blend":[...C0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":C0()}],"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":[S$]}],"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":S()}],"mask-image-linear-to-color":[{"mask-linear-to":S()}],"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":S()}],"mask-image-t-to-color":[{"mask-t-to":S()}],"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":S()}],"mask-image-r-to-color":[{"mask-r-to":S()}],"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":S()}],"mask-image-b-to-color":[{"mask-b-to":S()}],"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":S()}],"mask-image-l-to-color":[{"mask-l-to":S()}],"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":S()}],"mask-image-x-to-color":[{"mask-x-to":S()}],"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":S()}],"mask-image-y-to-color":[{"mask-y-to":S()}],"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":S()}],"mask-image-radial-to-color":[{"mask-radial-to":S()}],"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":k()}],"mask-image-conic-pos":[{"mask-conic":[S$]}],"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":S()}],"mask-image-conic-to-color":[{"mask-conic-to":S()}],"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:[S$,$Q,a2]}],contrast:[{contrast:[S$,$Q,a2]}],"drop-shadow":[{"drop-shadow":["","none",q,bb0,Pb0]}],"drop-shadow-color":[{"drop-shadow":S()}],grayscale:[{grayscale:["",S$,$Q,a2]}],"hue-rotate":[{"hue-rotate":[S$,$Q,a2]}],invert:[{invert:["",S$,$Q,a2]}],saturate:[{saturate:[S$,$Q,a2]}],sepia:[{sepia:["",S$,$Q,a2]}],"backdrop-filter":[{"backdrop-filter":["","none",$Q,a2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[S$,$Q,a2]}],"backdrop-contrast":[{"backdrop-contrast":[S$,$Q,a2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",S$,$Q,a2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[S$,$Q,a2]}],"backdrop-invert":[{"backdrop-invert":["",S$,$Q,a2]}],"backdrop-opacity":[{"backdrop-opacity":[S$,$Q,a2]}],"backdrop-saturate":[{"backdrop-saturate":[S$,$Q,a2]}],"backdrop-sepia":[{"backdrop-sepia":["",S$,$Q,a2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":g()}],"border-spacing-x":[{"border-spacing-x":g()}],"border-spacing-y":[{"border-spacing-y":g()}],"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:[S$,"initial",$Q,a2]}],ease:[{ease:["linear","initial",_,$Q,a2]}],delay:[{delay:[S$,$Q,a2]}],animate:[{animate:["none",j,$Q,a2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[L,$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:s0()}],"translate-x":[{"translate-x":s0()}],"translate-y":[{"translate-y":s0()}],"translate-z":[{"translate-z":s0()}],"translate-none":["translate-none"],zoom:[{zoom:[RL,$Q,a2]}],accent:[{accent:S()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:S()}],"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":S()}],"scrollbar-track-color":[{"scrollbar-track":S()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":g()}],"scroll-mx":[{"scroll-mx":g()}],"scroll-my":[{"scroll-my":g()}],"scroll-ms":[{"scroll-ms":g()}],"scroll-me":[{"scroll-me":g()}],"scroll-mbs":[{"scroll-mbs":g()}],"scroll-mbe":[{"scroll-mbe":g()}],"scroll-mt":[{"scroll-mt":g()}],"scroll-mr":[{"scroll-mr":g()}],"scroll-mb":[{"scroll-mb":g()}],"scroll-ml":[{"scroll-ml":g()}],"scroll-p":[{"scroll-p":g()}],"scroll-px":[{"scroll-px":g()}],"scroll-py":[{"scroll-py":g()}],"scroll-ps":[{"scroll-ps":g()}],"scroll-pe":[{"scroll-pe":g()}],"scroll-pbs":[{"scroll-pbs":g()}],"scroll-pbe":[{"scroll-pbe":g()}],"scroll-pt":[{"scroll-pt":g()}],"scroll-pr":[{"scroll-pr":g()}],"scroll-pb":[{"scroll-pb":g()}],"scroll-pl":[{"scroll-pl":g()}],"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",...S()]}],"stroke-w":[{stroke:[S$,b50,hT,CR2]}],stroke:[{stroke:["none",...S()]}],"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"]}},pL$=(A,{cacheSize:Q,prefix:$,experimentalParseClassName:w,extend:B={},override:X={}})=>{return On(A,"cacheSize",Q),On(A,"prefix",$),On(A,"experimentalParseClassName",w),jb0(A.theme,X.theme),jb0(A.classGroups,X.classGroups),jb0(A.conflictingClassGroups,X.conflictingClassGroups),jb0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),On(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),On(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),Mb0(A.theme,B.theme),Mb0(A.classGroups,B.classGroups),Mb0(A.conflictingClassGroups,B.conflictingClassGroups),Mb0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),xDA(A,B,"postfixLookupClassGroups"),xDA(A,B,"orderSensitiveModifiers"),A},On=(A,Q,$)=>{if($!==void 0)A[Q]=$},jb0=(A,Q)=>{if(Q)for(let $ in Q)On(A,$,Q[$])},Mb0=(A,Q)=>{if(Q)for(let $ in Q)xDA(A,Q,$)},xDA=(A,Q,$)=>{let w=Q[$];if(w!==void 0)A[$]=A[$]?A[$].concat(w):w},kb0=(A,...Q)=>typeof A==="function"?vR2(TR2,A,...Q):vR2(()=>pL$(TR2(),A),...Q);var lL$=kb0({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 lL$(kn(A))}var aR2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,tR2=kn,B5=(A,Q)=>($)=>{var w;if((Q===null||Q===void 0?void 0:Q.variants)==null)return tR2(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=aR2(U)||aR2(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((V)=>{let[L,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[L]):{...X,...Z}[L]===F})?[...K,G,D]:K},[]);return tR2(A,Y,H,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className)};import{jsxDEV as CDA}from"preact/jsx-dev-runtime";var eR2=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 hDA({variant:A,title:Q,children:$,className:w}){return CDA("div",{className:wQ(eR2({variant:A}),w),role:"alert",children:[Q&&CDA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),CDA("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 iL$}from"preact/jsx-dev-runtime";var Av2=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 TT({variant:A,size:Q,className:$,children:w,ssrOnClick:B,type:X="button",...Y}){return iL$("button",{type:X,className:wQ(Av2({variant:A,size:Q}),$),...Y,...B&&{onclick:B},children:w},void 0,!1,void 0,this)}import{jsxDEV as dL$}from"preact/jsx-dev-runtime";var Qv2=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 wX({href:A,children:Q,variant:$,size:w,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return dL$("a",{href:A,className:wQ(Qv2({variant:$,size:w}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as Ob0}from"preact/jsx-dev-runtime";var $v2=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"}}),nL$={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function fn({variant:A,size:Q,className:$}){let w=nL$[Q??"md"];return Ob0("button",{onclick:"toggleTheme()",type:"button",className:wQ($v2({variant:A,size:Q}),$),"aria-label":"Toggle dark mode",children:Ob0("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:[Ob0("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),Ob0("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 EDA}from"preact/jsx-dev-runtime";var wv2=B5("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function fb0({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 EDA("ul",{className:wQ(wv2({orientation:w}),Q),children:[X.map((Y)=>EDA("li",{children:EDA("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 Th5}from"preact/jsx-dev-runtime";import{jsxDEV as Sh5}from"preact/jsx-dev-runtime";import{createContext as rL$,h as oL$}from"preact";import{useContext as sL$}from"preact/hooks";var TDA=rL$(null);function xn({headCollector:A,children:Q}){return oL$(TDA.Provider,{value:A},Q)}function Bv2(){return sL$(TDA)}function E6(A){let Q=Bv2();if(Q)Q.setHeadProps(A);return null}import{createContext as kM$,h as OM$}from"preact";import{useContext as fM$}from"preact/hooks";$QA();var qT2=k1(DT2(),1),jM$=new xJ0({gfm:!0,breaks:!0}),MM$={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 ZzA(A,Q){let{imageRenderer:$}=Q??{},B=($?new xJ0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return $(X,Y,Z)??!1}}}):jM$).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
5862
+ `)}}zA();class Kb0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:NDA,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 Ub0 extends H8{directorySync;operationStatus;constructor(A,Q,$,w){super(A,{schema:IDA,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();v8();var WF$=300000,HF$=500;async function tx2(A){if(A.jobIds.length===0)return;let Q=A.maxWaitMs??WF$,$=A.pollIntervalMs??HF$;A.logger.debug(`Waiting for ${A.jobIds.length} import jobs to complete`);let w=r0.gen(function*(){let Y=yield*QH.currentTimeMillis;yield*r0.gen(function*(){let K=(yield*r0.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*QH.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*r0.tryPromise({try:()=>A.reporter.report({progress:50+Math.round(G*0.05),message:`Processing ${K}/${A.jobIds.length} entities`}),catch:(D)=>D}),!1}).pipe(r0.repeat({schedule:JK.spaced($),until:(H)=>H}))}),B=A.clock?r0.withClock(w,A.clock):w,X=await r0.runPromiseExit(B);if(R2.isFailure(X))throw j$.squash(X.cause)}class Gb0 extends H8{getDirectorySync;context;constructor(A,Q,$){super(A,{schema:FDA,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 tx2({jobIds:A,entityService:this.context.entityService,reporter:Q,logger:this.logger})}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}zA();class Db0 extends H8{context;getDirectorySync;getGitSync;constructor(A,Q,$,w){super(A,{schema:LDA,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`}),KF$(X)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function KF$(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}zA();class qb0 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();v0();var UF$=W.object({});class zb0 extends H8{directorySync;constructor(A,Q){super(A,{schema:UF$,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();lZ();u4();Kw();v0();lZ();import{readFile as GF$,writeFile as DF$}from"fs/promises";var qF$=_DA,zF$=W.record(W.string(),W.unknown());class Jb0 extends H8{context;fetcher;constructor(A,Q,$=yq){super(Q,{schema:qF$,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 GF$(w,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:w,error:sA(F)}),r5.failure(F)}let K;try{K=t8(H)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:w,error:sA(F)}),r5.failure(F)}let U=zF$.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 F;try{F=await this.fetcher(B)}catch(R){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:sA(R)}),r5.failure(R)}await this.reportProgress($,{progress:g6.GENERATE,message:"Creating image entity"});let{base64:_}=jk(F),j=Wh(_),b=Mk(_);if(!j||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),r5.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let k=`Cover image for ${X}`,v=Z??k;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:F,metadata:{title:k,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 V={...G};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=q;let L=OC(V,K.content);try{await DF$(w,L,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:w,error:sA(F)}),r5.failure(F)}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:sA(H)}),r5.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}zA();lZ();Kw();import{readFile as JF$,writeFile as VF$}from"fs/promises";class Vb0 extends H8{converter;constructor(A,Q,$=yq){super(Q,{schema:PDA,jobTypeName:"inline-image-convert"});this.converter=new K50(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 JF$(w,"utf-8")}catch(H){let K=sA(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 VF$(w,Z.content,"utf-8")}catch(H){let K=sA(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=sA(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 ex2(A,Q,$,w=()=>Q,B){let X=(Y)=>$.child(Y);A.jobs.registerHandler("directory-sync",new Gb0(X("DirectorySyncJobHandler"),A,w)),A.jobs.registerHandler("directory-export",new Kb0(X("DirectoryExportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-import",new Ub0(X("DirectoryImportJobHandler"),A,Q,B)),A.jobs.registerHandler("directory-delete",new qb0(X("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new zb0(X("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new Jb0(A,X("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new Vb0(A,X("InlineImageConversionJobHandler"))),$.debug("Registered async job handlers")}zA();v0();import{unlink as FF$,access as LF$}from"fs/promises";var IF$=W.record(W.string(),W.unknown());function AR2(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 LF$(U).then(()=>!0,()=>!1))await FF$(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 bDA(A,Q,$,w){Q.setJobQueueCallback(async(B)=>{let X=await w?.startRun("watcher","importing"),Y=[{type:B.type,data:IF$.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 wR2,mkdir as _F$,copyFile as PF$}from"fs/promises";import{join as $R2,resolve as jDA}from"path";import{join as NF$}from"path";async function QR2(A){if(!await D7(NF$(A,".git")))return!1;try{return await fJ(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function bF$(A,Q){if(!await D7(A))return!0;if((await wR2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await QR2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function BR2(A,Q){let $=await wR2(A,{withFileTypes:!0});for(let w of $){let B=$R2(A,w.name),X=$R2(Q,w.name);if(w.isDirectory()){if(!await D7(X))await _F$(X,{recursive:!0});await BR2(B,X)}else await PF$(B,X)}}async function XR2(A,Q,$){let w=jDA(process.cwd(),A);$=$?jDA($):jDA(process.cwd(),"seed-content");let B=await bF$(w,Q);if(B&&await D7($))Q.debug("Copying seed content to brain-data directory"),await BR2($,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 YR2(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 XR2(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:vC.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){w.error("Initial sync failed",H),await A.messaging.send({type:vC.initialSyncCompleted,payload:{success:!1,error:sA(H)},...{broadcast:!0}})}};A.messaging.subscribe(vC.pluginsRegistered,async()=>{return w.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}function ZR2(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 WR2(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 V=await Q.queueSyncBatch($,"periodic-sync");return{files:q.files,result:V}},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 KR2}from"child_process";import{cpSync as jF$,existsSync as HR2,mkdirSync as MF$,mkdtempSync as kF$,rmSync as OF$}from"fs";import{tmpdir as fF$}from"os";import{fileURLToPath as xF$}from"url";import{join as RF$,resolve as vF$}from"path";function jf(A,Q){let $=KR2("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 CF$(A){return A.startsWith("file://")}function hF$(A){return xF$(A)}function EF$(A,Q){return KR2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function UR2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!CF$(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",$=hF$(A.gitUrl),w=vF$(A.seedContentPath);if(!HR2(w))throw Error(`Seed content path not found: ${w}`);if(!HR2($))A.logger.debug("Creating local bare content remote",{remotePath:$,branch:Q}),MF$($,{recursive:!0}),jf(process.cwd(),["init","--bare",`--initial-branch=${Q}`,$]);if(EF$($,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=kF$(RF$(fF$(),"directory-sync-seed-"));try{jf(B,["init",`--initial-branch=${Q}`]),jf(B,["config","user.name",A.authorName??"Brain"]),jf(B,["config","user.email",A.authorEmail??"brain@localhost"]),jF$(w,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),jf(B,["add","."]),jf(B,["commit","-m","seed content remote"]),jf(B,["remote","add","origin",A.gitUrl]),jf(B,["push","-u","origin",Q])}finally{OF$(B,{recursive:!0,force:!0})}}function GR2(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 TF$(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 TF$(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();v0();async function Fb0(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();v0();function DR2(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 kY(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function qR2(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 Fb0({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 kY(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 kY(Y instanceof Error?Y.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(w)X.push(DR2($,w));return X}zA();v0();import{isAbsolute as zR2,relative as yF$}from"path";var IR2=W.enum(["manual","periodic","watcher","save"]),gF$=W.enum(["pulling","scanning","importing","settling"]),NR2={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()},SF$=W.object({id:W.string().min(1),source:IR2,state:gF$,startedAt:W.string().datetime(),jobId:W.string().min(1).optional(),batchId:W.string().min(1).optional(),...NR2}),mF$=W.object({id:W.string().min(1),source:IR2,outcome:W.enum(["succeeded","attention","failed"]),startedAt:W.string().datetime(),completedAt:W.string().datetime(),summary:W.string().min(1).max(240),...NR2}),uF$=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()}),JR2=W.object({activeRun:SF$.optional(),recentRuns:W.array(mF$).max(5),issues:W.array(uF$).max(8)}),cF$=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()}),VR2={imported:0,skipped:0,failed:0,quarantined:0,exported:0},pF$={recentRuns:[],issues:[]},lF$="directory-sync.operation-status",FR2="current";class MDA{store;jobs;logger;syncPath;statePromise;writeQueue=Promise.resolve();constructor(A,Q,$,w){this.store=A.scoped({namespace:lF$,schema:JR2}),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(),...VR2},$})}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=Lb0(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,...VR2,...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=cF$.safeParse(iF$($.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(FR2).then((A)=>A??structuredClone(pF$)),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(FR2,JR2.parse(A))}prependRecent(A,Q,$,w){let B={id:Q.id,source:Q.source,outcome:$,startedAt:Q.startedAt,completedAt:new Date().toISOString(),summary:Lb0(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}:${$??Lb0(Q.message,80)}`,kind:Q.kind,...$?{path:$}:{},message:Lb0(Q.message),occurredAt:new Date().toISOString()};A.issues=[w,...A.issues.filter((B)=>B.id!==w.id)].slice(0,8)}safePath(A){if(!zR2(A))return LR2(A);let Q=yF$(this.syncPath,A);if(Q.startsWith("..")||zR2(Q))return"content file";return LR2(Q)}}function iF$(A){if(typeof A!=="string")return A;try{return JSON.parse(A)}catch{return A}}function LR2(A){return A.replaceAll("\\","/").replace(/^\.\//,"").slice(0,300)||"content file"}function Lb0(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();v0();import{basename as dF$}from"path";var nF$=W.object({workspaceUrl:W.string()}),rF$=W.object({type:W.literal("sync-now")}),_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()},oF$=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(),..._R2}).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),..._R2})),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 kDA{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 oF$.parse({health:X,directory:{displayPath:dF$(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(!rF$.safeParse(w).success)throw Error("Invalid directory sync workspace action");let Y={interfaceType:"cms",userId:B.userId,userPermissionLevel:B.userPermissionLevel},Z=await Fb0({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:h_,payload:A});if(!("success"in Q)||!Q.success)return;let $=nF$.safeParse(Q.data);return $.success?$.data.workspaceUrl:void 0}toSafeGitStatus(A){let Q=A.files.slice(0,20).map((w)=>({path:sF$(w.path),status:w.status.trim()||"changed"})),$=aF$(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 sF$(A){let Q=A.replaceAll("\\","/").replace(/^\.\//,"");if(Q.startsWith("../")||Q.startsWith("/"))return"content file";return Q.slice(0,300)||"content file"}function aF$(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$/,"")}`}}v8();class Ib0{resourceScope;scheduleScope;periodicScope;delayScope;scheduleFibers;periodicFibers;delayedFibers;clock;activeOperations=new Set;activeFailures=[];nextPeriodicId=0;closePromise=null;closed=!1;constructor(A={}){this.resourceScope=r0.runSync(j2.make()),this.scheduleScope=r0.runSync(j2.make()),this.periodicScope=r0.runSync(j2.make()),this.delayScope=r0.runSync(j2.make()),this.scheduleFibers=r0.runSync(j2.extend(CZ.make(),this.scheduleScope)),this.periodicFibers=r0.runSync(j2.extend(zw.make(),this.periodicScope)),this.delayedFibers=r0.runSync(j2.extend(zw.make(),this.delayScope)),this.clock=A.clock}async acquire(A,Q){if(this.closed)throw Error("Directory sync runtime is closed");let $=r0.acquireRelease(r0.promise(A),(B)=>r0.promise(()=>Q(B))),w=await r0.runPromiseExit(j2.extend($,this.resourceScope));if(R2.isFailure(w))throw j$.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||zw.unsafeHas(this.periodicFibers,$))return;let Y=r0.tryPromise({try:Q,catch:(Z)=>Z}).pipe(r0.catchAll((Z)=>r0.sync(()=>{this.activeFailures.push(Z)})));zw.unsafeSet(this.periodicFibers,$,r0.runFork(Y),{onlyIfMissing:!0})},B=r0.sleep(A).pipe(r0.andThen(r0.sync(w)),r0.forever),X=this.clock?r0.withClock(B,this.clock):B;CZ.unsafeAdd(this.scheduleFibers,r0.runFork(X))}scheduleTrailing(A,Q,$){if(this.closed)return;let w=r0.sleep(Q).pipe(r0.andThen(r0.sync(()=>{this.trackActive($)}))),B=this.clock?r0.withClock(w,this.clock):w,X=r0.runFork(B);zw.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 r0.runPromiseExit(j2.close(A,R2.void));if(R2.isFailure(Q))throw j$.squash(Q.cause)}}function PR2(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 bR2(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 jR2={name:"@brains/directory-sync",version:"0.2.0-alpha.206",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 ODA extends d6{directorySync;gitSync;operationStatus;workspaceProvider;cmsWorkspaceUrl;runtime=new Ib0;directorySyncFacade=PR2(()=>this.requireDirectorySync());gitSyncFacade=bR2(()=>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",jR2,A,_50)}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:P50,basePrompt:"",formatter:new Hb0,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 MDA(A.runtimeState,A.jobs,this.logger.child("OperationStatus"),Q),await this.operationStatus.initialize(),this.config.autoSync)bDA(A,this.directorySync,Q,this.operationStatus);if(await this.registerJobHandlers(A),AR2(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 Db0(this.logger.child("DirectorySyncRequestJobHandler"),A,()=>this.requireDirectorySync(),()=>this.requireGitSync()));if(this.config.initialSync)YR2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync?this.gitSyncFacade:void 0);this.workspaceProvider=new kDA({context:A,pluginId:this.id,config:this.config,getDirectorySync:()=>this.requireDirectorySync(),getGitSync:()=>this.gitSync,operationStatus:this.operationStatus}),GR2(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 qR2(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 Ib0,w=this.createDirectorySync(Q,A),B;try{if(await w.initializeDirectory(),this.config.autoSync)bDA(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 mP0({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 UR2({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 VDA({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)ZR2($.messaging,()=>this.requireGitSync(),this.config.commitDebounce,this.logger.child("GitAutoCommit"),this.runtimeScheduler,this.operationStatus),this.gitAutoCommitRegistered=!0;if(this.config.autoSync)WR2(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){ex2(A,this.directorySyncFacade,this.logger,()=>this.requireDirectorySync(),this.requireOperationStatus())}}function CT(A={}){return new ODA(A)}v0();var Nb0="email:send",MR2=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();v0();var kR2={name:"@brains/email-resend",version:"0.2.0-alpha.206",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 AL$=W.object({apiKey:W.string().min(1).optional(),from:W.string().min(1).optional()}),QL$=W.looseObject({id:W.string().optional()});class OR2 extends d6{fetchImpl;constructor(A={},Q={}){super("email-resend",kR2,A,AL$);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(Nb0,async($)=>{let w=MR2.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=QL$.parse(await w.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function _b0(A={}){return new OR2(A)}zA();import{render as qn2}from"preact-render-to-string";import{h as zy}from"preact";function fR2(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]&&($=fR2(A[Q]))&&(w&&(w+=" "),w+=$)}else for($ in A)A[$]&&(w&&(w+=" "),w+=$);return w}function kn(){for(var A,Q,$=0,w="",B=arguments.length;$<B;$++)(A=arguments[$])&&(Q=fR2(A))&&(w&&(w+=" "),w+=Q);return w}var $L$=(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 $},wL$=(A,Q)=>({classGroupId:A,validator:Q}),yR2=(A=new Map,Q=null,$)=>({nextPart:A,validators:Q,classGroupId:$});var xR2=[];var BL$=(A)=>{let Q=YL$(A),{conflictingClassGroups:$,conflictingClassGroupModifiers:w}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return XL$(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return gR2(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=w[Y],K=$[Y];if(H){if(K)return $L$(K,H);return H}return K||xR2}return $[Y]||xR2}}},gR2=(A,Q,$)=>{if(A.length-Q===0)return $.classGroupId;let B=A[Q],X=$.nextPart.get(B);if(X){let K=gR2(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},XL$=(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})(),YL$=(A)=>{let{theme:Q,classGroups:$}=A;return ZL$($,Q)},ZL$=(A,Q)=>{let $=yR2();for(let w in A){let B=A[w];RDA(B,$,w,Q)}return $},RDA=(A,Q,$,w)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];WL$(Y,Q,$,w)}},WL$=(A,Q,$,w)=>{if(typeof A==="string"){HL$(A,Q,$);return}if(typeof A==="function"){KL$(A,Q,$,w);return}UL$(A,Q,$,w)},HL$=(A,Q,$)=>{let w=A===""?Q:SR2(Q,A);w.classGroupId=$},KL$=(A,Q,$,w)=>{if(GL$(A)){RDA(A(w),Q,$,w);return}if(Q.validators===null)Q.validators=[];Q.validators.push(wL$($,A))},UL$=(A,Q,$,w)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];RDA(H,SR2(Q,Z),$,w)}},SR2=(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=yR2(),$.nextPart.set(Y,Z);$=Z}return $},GL$=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,DL$=(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 qL$=[],RR2=(A,Q,$,w,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:$,maybePostfixModifierPosition:w,isExternal:B}),zL$=(A)=>{let{prefix:Q,experimentalParseClassName:$}=A,w=(B)=>{let X=[],Y=0,Z=0,H=0,K,U=B.length;for(let L=0;L<U;L++){let F=B[L];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(H,L)),H=L+1;continue}if(F==="/"){K=L;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")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 V=K&&K>H?K-H:void 0;return RR2(X,q,D,V)};if(Q){let B=Q+":",X=w;w=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):RR2(qL$,!1,Y,void 0,!0)}if($){let B=w;w=(X)=>$({className:X,parseClassName:B})}return w},JL$=(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}},VL$=(A)=>({cache:DL$(A.cacheSize),parseClassName:zL$(A),sortModifiers:JL$(A),postfixLookupClassGroupIds:FL$(A),...BL$(A)}),FL$=(A)=>{let Q=Object.create(null),$=A.postfixLookupClassGroups;if($)for(let w=0;w<$.length;w++)Q[$[w]]=!0;return Q},LL$=/\s+/,IL$=(A,Q)=>{let{parseClassName:$,getClassGroupId:w,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(LL$),K="";for(let U=H.length-1;U>=0;U-=1){let G=H[U],{isExternal:D,modifiers:q,hasImportantModifier:V,baseClassName:L,maybePostfixModifierPosition:F}=$(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!F,j;if(_){let O=L.substring(0,F);j=w(O);let g=j&&Y[j]?w(L):void 0;if(g&&g!==j)j=g,_=!1}else j=w(L);if(!j){if(!_){K=G+(K.length>0?" "+K:K);continue}if(j=w(L),!j){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=q.length===0?"":q.length===1?q[0]:X(q).join(":"),k=V?b+"!":b,v=k+j;if(Z.indexOf(v)>-1)continue;Z.push(v);let R=B(j,_);for(let O=0;O<R.length;++O){let g=R[O];Z.push(k+g)}K=G+(K.length>0?" "+K:K)}return K},NL$=(...A)=>{let Q=0,$,w,B="";while(Q<A.length)if($=A[Q++]){if(w=mR2($))B&&(B+=" "),B+=w}return B},mR2=(A)=>{if(typeof A==="string")return A;let Q,$="";for(let w=0;w<A.length;w++)if(A[w]){if(Q=mR2(A[w]))$&&($+=" "),$+=Q}return $},vR2=(A,...Q)=>{let $,w,B,X,Y=(H)=>{let K=Q.reduce((U,G)=>G(U),A());return $=VL$(K),w=$.cache.get,B=$.cache.set,X=Z,Z(H)},Z=(H)=>{let K=w(H);if(K)return K;let U=IL$(H,$);return B(H,U),U};return X=Y,(...H)=>X(NL$(...H))},_L$=[],$X=(A)=>{let Q=($)=>$[A]||_L$;return Q.isThemeGetter=!0,Q},uR2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,cR2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,PL$=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,bL$=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,jL$=/\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$/,ML$=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,kL$=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,OL$=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,Mf=(A)=>PL$.test(A),S$=(A)=>!!A&&!Number.isNaN(Number(A)),RL=(A)=>!!A&&Number.isInteger(Number(A)),fDA=(A)=>A.endsWith("%")&&S$(A.slice(0,-1)),Qb=(A)=>bL$.test(A),pR2=()=>!0,fL$=(A)=>jL$.test(A)&&!ML$.test(A),vDA=()=>!1,xL$=(A)=>kL$.test(A),RL$=(A)=>OL$.test(A),vL$=(A)=>!a2(A)&&!$Q(A),CL$=(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)),hL$=(A)=>kf(A,dR2,vDA),a2=(A)=>uR2.test(A),hT=(A)=>kf(A,nR2,fL$),CR2=(A)=>kf(A,cL$,S$),EL$=(A)=>kf(A,oR2,pR2),TL$=(A)=>kf(A,rR2,vDA),hR2=(A)=>kf(A,lR2,vDA),yL$=(A)=>kf(A,iR2,RL$),Pb0=(A)=>kf(A,sR2,xL$),$Q=(A)=>cR2.test(A),b50=(A)=>ET(A,nR2),gL$=(A)=>ET(A,rR2),ER2=(A)=>ET(A,lR2),SL$=(A)=>ET(A,dR2),mL$=(A)=>ET(A,iR2),bb0=(A)=>ET(A,sR2,!0),uL$=(A)=>ET(A,oR2,!0),kf=(A,Q,$)=>{let w=uR2.exec(A);if(w){if(w[1])return Q(w[1]);return $(w[2])}return!1},ET=(A,Q,$=!1)=>{let w=cR2.exec(A);if(w){if(w[1])return Q(w[1]);return $}return!1},lR2=(A)=>A==="position"||A==="percentage",iR2=(A)=>A==="image"||A==="url",dR2=(A)=>A==="length"||A==="size"||A==="bg-size",nR2=(A)=>A==="length",cL$=(A)=>A==="number",rR2=(A)=>A==="family-name",oR2=(A)=>A==="number"||A==="weight",sR2=(A)=>A==="shadow";var TR2=()=>{let A=$X("color"),Q=$X("font"),$=$X("text"),w=$X("font-weight"),B=$X("tracking"),X=$X("leading"),Y=$X("breakpoint"),Z=$X("container"),H=$X("spacing"),K=$X("radius"),U=$X("shadow"),G=$X("inset-shadow"),D=$X("text-shadow"),q=$X("drop-shadow"),V=$X("blur"),L=$X("perspective"),F=$X("aspect"),_=$X("ease"),j=$X("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],k=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...k(),$Q,a2],R=()=>["auto","hidden","clip","visible","scroll"],O=()=>["auto","contain","none"],g=()=>[$Q,a2,H],m=()=>[Mf,"full","auto",...g()],l=()=>[RL,"none","subgrid",$Q,a2],a=()=>["auto",{span:["full",RL,$Q,a2]},RL,$Q,a2],B0=()=>[RL,"auto",$Q,a2],p=()=>["auto","min","max","fr",$Q,a2],f=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],T=()=>["start","end","center","stretch","center-safe","end-safe"],E=()=>["auto",...g()],o=()=>[Mf,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...g()],t=()=>[Mf,"screen","full","dvw","lvw","svw","min","max","fit",...g()],q0=()=>[Mf,"screen","full","lh","dvh","lvh","svh","min","max","fit",...g()],S=()=>[A,$Q,a2],Y0=()=>[...k(),ER2,hR2,{position:[$Q,a2]}],F0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],d=()=>["auto","cover","contain",SL$,hL$,{size:[$Q,a2]}],c0=()=>[fDA,b50,hT],i0=()=>["","none","full",K,$Q,a2],N0=()=>["",S$,b50,hT],b0=()=>["solid","dashed","dotted","double"],C0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[S$,fDA,ER2,hR2],k0=()=>["","none",V,$Q,a2],O0=()=>["none",S$,$Q,a2],f0=()=>["none",S$,$Q,a2],m0=()=>[S$,$Q,a2],s0=()=>[Mf,"full",...g()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Qb],breakpoint:[Qb],color:[pR2],container:[Qb],"drop-shadow":[Qb],ease:["in","out","in-out"],font:[vL$],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Qb],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Qb],shadow:[Qb],spacing:["px",S$],text:[Qb],"text-shadow":[Qb],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",Mf,a2,$Q,F]}],container:["container"],"container-type":[{"@container":["","normal","size",$Q,a2]}],"container-named":[CL$],columns:[{columns:[S$,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:m()}],"inset-x":[{"inset-x":m()}],"inset-y":[{"inset-y":m()}],start:[{"inset-s":m(),start:m()}],end:[{"inset-e":m(),end:m()}],"inset-bs":[{"inset-bs":m()}],"inset-be":[{"inset-be":m()}],top:[{top:m()}],right:[{right:m()}],bottom:[{bottom:m()}],left:[{left:m()}],visibility:["visible","invisible","collapse"],z:[{z:[RL,"auto",$Q,a2]}],basis:[{basis:[Mf,"full","auto",Z,...g()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[S$,Mf,"auto","initial","none",a2]}],grow:[{grow:["",S$,$Q,a2]}],shrink:[{shrink:["",S$,$Q,a2]}],order:[{order:[RL,"first","last","none",$Q,a2]}],"grid-cols":[{"grid-cols":l()}],"col-start-end":[{col:a()}],"col-start":[{"col-start":B0()}],"col-end":[{"col-end":B0()}],"grid-rows":[{"grid-rows":l()}],"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:g()}],"gap-x":[{"gap-x":g()}],"gap-y":[{"gap-y":g()}],"justify-content":[{justify:[...f(),"normal"]}],"justify-items":[{"justify-items":[...T(),"normal"]}],"justify-self":[{"justify-self":["auto",...T()]}],"align-content":[{content:["normal",...f()]}],"align-items":[{items:[...T(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...T(),{baseline:["","last"]}]}],"place-content":[{"place-content":f()}],"place-items":[{"place-items":[...T(),"baseline"]}],"place-self":[{"place-self":["auto",...T()]}],p:[{p:g()}],px:[{px:g()}],py:[{py:g()}],ps:[{ps:g()}],pe:[{pe:g()}],pbs:[{pbs:g()}],pbe:[{pbe:g()}],pt:[{pt:g()}],pr:[{pr:g()}],pb:[{pb:g()}],pl:[{pl:g()}],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":g()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":g()}],"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",$,b50,hT]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[w,uL$,EL$]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",fDA,a2]}],"font-family":[{font:[gL$,TL$,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":[S$,"none",$Q,CR2]}],leading:[{leading:[X,...g()]}],"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:S()}],"text-color":[{text:S()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...b0(),"wavy"]}],"text-decoration-thickness":[{decoration:[S$,"from-font","auto",$Q,hT]}],"text-decoration-color":[{decoration:S()}],"underline-offset":[{"underline-offset":[S$,"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:g()}],"tab-size":[{tab:[RL,$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"]},RL,$Q,a2],radial:["",$Q,a2],conic:[RL,$Q,a2]},mL$,yL$]}],"bg-color":[{bg:S()}],"gradient-from-pos":[{from:c0()}],"gradient-via-pos":[{via:c0()}],"gradient-to-pos":[{to:c0()}],"gradient-from":[{from:S()}],"gradient-via":[{via:S()}],"gradient-to":[{to:S()}],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:S()}],"border-color-x":[{"border-x":S()}],"border-color-y":[{"border-y":S()}],"border-color-s":[{"border-s":S()}],"border-color-e":[{"border-e":S()}],"border-color-bs":[{"border-bs":S()}],"border-color-be":[{"border-be":S()}],"border-color-t":[{"border-t":S()}],"border-color-r":[{"border-r":S()}],"border-color-b":[{"border-b":S()}],"border-color-l":[{"border-l":S()}],"divide-color":[{divide:S()}],"outline-style":[{outline:[...b0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[S$,$Q,a2]}],"outline-w":[{outline:["",S$,b50,hT]}],"outline-color":[{outline:S()}],shadow:[{shadow:["","none",U,bb0,Pb0]}],"shadow-color":[{shadow:S()}],"inset-shadow":[{"inset-shadow":["none",G,bb0,Pb0]}],"inset-shadow-color":[{"inset-shadow":S()}],"ring-w":[{ring:N0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:S()}],"ring-offset-w":[{"ring-offset":[S$,hT]}],"ring-offset-color":[{"ring-offset":S()}],"inset-ring-w":[{"inset-ring":N0()}],"inset-ring-color":[{"inset-ring":S()}],"text-shadow":[{"text-shadow":["none",D,bb0,Pb0]}],"text-shadow-color":[{"text-shadow":S()}],opacity:[{opacity:[S$,$Q,a2]}],"mix-blend":[{"mix-blend":[...C0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":C0()}],"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":[S$]}],"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":S()}],"mask-image-linear-to-color":[{"mask-linear-to":S()}],"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":S()}],"mask-image-t-to-color":[{"mask-t-to":S()}],"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":S()}],"mask-image-r-to-color":[{"mask-r-to":S()}],"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":S()}],"mask-image-b-to-color":[{"mask-b-to":S()}],"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":S()}],"mask-image-l-to-color":[{"mask-l-to":S()}],"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":S()}],"mask-image-x-to-color":[{"mask-x-to":S()}],"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":S()}],"mask-image-y-to-color":[{"mask-y-to":S()}],"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":S()}],"mask-image-radial-to-color":[{"mask-radial-to":S()}],"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":k()}],"mask-image-conic-pos":[{"mask-conic":[S$]}],"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":S()}],"mask-image-conic-to-color":[{"mask-conic-to":S()}],"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:[S$,$Q,a2]}],contrast:[{contrast:[S$,$Q,a2]}],"drop-shadow":[{"drop-shadow":["","none",q,bb0,Pb0]}],"drop-shadow-color":[{"drop-shadow":S()}],grayscale:[{grayscale:["",S$,$Q,a2]}],"hue-rotate":[{"hue-rotate":[S$,$Q,a2]}],invert:[{invert:["",S$,$Q,a2]}],saturate:[{saturate:[S$,$Q,a2]}],sepia:[{sepia:["",S$,$Q,a2]}],"backdrop-filter":[{"backdrop-filter":["","none",$Q,a2]}],"backdrop-blur":[{"backdrop-blur":k0()}],"backdrop-brightness":[{"backdrop-brightness":[S$,$Q,a2]}],"backdrop-contrast":[{"backdrop-contrast":[S$,$Q,a2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",S$,$Q,a2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[S$,$Q,a2]}],"backdrop-invert":[{"backdrop-invert":["",S$,$Q,a2]}],"backdrop-opacity":[{"backdrop-opacity":[S$,$Q,a2]}],"backdrop-saturate":[{"backdrop-saturate":[S$,$Q,a2]}],"backdrop-sepia":[{"backdrop-sepia":["",S$,$Q,a2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":g()}],"border-spacing-x":[{"border-spacing-x":g()}],"border-spacing-y":[{"border-spacing-y":g()}],"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:[S$,"initial",$Q,a2]}],ease:[{ease:["linear","initial",_,$Q,a2]}],delay:[{delay:[S$,$Q,a2]}],animate:[{animate:["none",j,$Q,a2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[L,$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:s0()}],"translate-x":[{"translate-x":s0()}],"translate-y":[{"translate-y":s0()}],"translate-z":[{"translate-z":s0()}],"translate-none":["translate-none"],zoom:[{zoom:[RL,$Q,a2]}],accent:[{accent:S()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:S()}],"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":S()}],"scrollbar-track-color":[{"scrollbar-track":S()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":g()}],"scroll-mx":[{"scroll-mx":g()}],"scroll-my":[{"scroll-my":g()}],"scroll-ms":[{"scroll-ms":g()}],"scroll-me":[{"scroll-me":g()}],"scroll-mbs":[{"scroll-mbs":g()}],"scroll-mbe":[{"scroll-mbe":g()}],"scroll-mt":[{"scroll-mt":g()}],"scroll-mr":[{"scroll-mr":g()}],"scroll-mb":[{"scroll-mb":g()}],"scroll-ml":[{"scroll-ml":g()}],"scroll-p":[{"scroll-p":g()}],"scroll-px":[{"scroll-px":g()}],"scroll-py":[{"scroll-py":g()}],"scroll-ps":[{"scroll-ps":g()}],"scroll-pe":[{"scroll-pe":g()}],"scroll-pbs":[{"scroll-pbs":g()}],"scroll-pbe":[{"scroll-pbe":g()}],"scroll-pt":[{"scroll-pt":g()}],"scroll-pr":[{"scroll-pr":g()}],"scroll-pb":[{"scroll-pb":g()}],"scroll-pl":[{"scroll-pl":g()}],"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",...S()]}],"stroke-w":[{stroke:[S$,b50,hT,CR2]}],stroke:[{stroke:["none",...S()]}],"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"]}},pL$=(A,{cacheSize:Q,prefix:$,experimentalParseClassName:w,extend:B={},override:X={}})=>{return On(A,"cacheSize",Q),On(A,"prefix",$),On(A,"experimentalParseClassName",w),jb0(A.theme,X.theme),jb0(A.classGroups,X.classGroups),jb0(A.conflictingClassGroups,X.conflictingClassGroups),jb0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),On(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),On(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),Mb0(A.theme,B.theme),Mb0(A.classGroups,B.classGroups),Mb0(A.conflictingClassGroups,B.conflictingClassGroups),Mb0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),xDA(A,B,"postfixLookupClassGroups"),xDA(A,B,"orderSensitiveModifiers"),A},On=(A,Q,$)=>{if($!==void 0)A[Q]=$},jb0=(A,Q)=>{if(Q)for(let $ in Q)On(A,$,Q[$])},Mb0=(A,Q)=>{if(Q)for(let $ in Q)xDA(A,Q,$)},xDA=(A,Q,$)=>{let w=Q[$];if(w!==void 0)A[$]=A[$]?A[$].concat(w):w},kb0=(A,...Q)=>typeof A==="function"?vR2(TR2,A,...Q):vR2(()=>pL$(TR2(),A),...Q);var lL$=kb0({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 lL$(kn(A))}var aR2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,tR2=kn,B5=(A,Q)=>($)=>{var w;if((Q===null||Q===void 0?void 0:Q.variants)==null)return tR2(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=aR2(U)||aR2(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((V)=>{let[L,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[L]):{...X,...Z}[L]===F})?[...K,G,D]:K},[]);return tR2(A,Y,H,$===null||$===void 0?void 0:$.class,$===null||$===void 0?void 0:$.className)};import{jsxDEV as CDA}from"preact/jsx-dev-runtime";var eR2=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 hDA({variant:A,title:Q,children:$,className:w}){return CDA("div",{className:wQ(eR2({variant:A}),w),role:"alert",children:[Q&&CDA("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),CDA("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 iL$}from"preact/jsx-dev-runtime";var Av2=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 TT({variant:A,size:Q,className:$,children:w,ssrOnClick:B,type:X="button",...Y}){return iL$("button",{type:X,className:wQ(Av2({variant:A,size:Q}),$),...Y,...B&&{onclick:B},children:w},void 0,!1,void 0,this)}import{jsxDEV as dL$}from"preact/jsx-dev-runtime";var Qv2=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 wX({href:A,children:Q,variant:$,size:w,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return dL$("a",{href:A,className:wQ(Qv2({variant:$,size:w}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as Ob0}from"preact/jsx-dev-runtime";var $v2=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"}}),nL$={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function fn({variant:A,size:Q,className:$}){let w=nL$[Q??"md"];return Ob0("button",{onclick:"toggleTheme()",type:"button",className:wQ($v2({variant:A,size:Q}),$),"aria-label":"Toggle dark mode",children:Ob0("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:[Ob0("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),Ob0("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 EDA}from"preact/jsx-dev-runtime";var wv2=B5("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function fb0({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 EDA("ul",{className:wQ(wv2({orientation:w}),Q),children:[X.map((Y)=>EDA("li",{children:EDA("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 Th5}from"preact/jsx-dev-runtime";import{jsxDEV as Sh5}from"preact/jsx-dev-runtime";import{createContext as rL$,h as oL$}from"preact";import{useContext as sL$}from"preact/hooks";var TDA=rL$(null);function xn({headCollector:A,children:Q}){return oL$(TDA.Provider,{value:A},Q)}function Bv2(){return sL$(TDA)}function E6(A){let Q=Bv2();if(Q)Q.setHeadProps(A);return null}import{createContext as kM$,h as OM$}from"preact";import{useContext as fM$}from"preact/hooks";$QA();var qT2=k1(DT2(),1),jM$=new xJ0({gfm:!0,breaks:!0}),MM$={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 ZzA(A,Q){let{imageRenderer:$}=Q??{},B=($?new xJ0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return $(X,Y,Z)??!1}}}):jM$).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>`),qT2.default(B,MM$)}var zT2=kM$(null);function rn({imageRenderer:A,children:Q}){return OM$(zT2.Provider,{value:A??null},Q)}function JT2(){return fM$(zT2)}function Hb(){let A=JT2();return(Q)=>ZzA(Q,A?{imageRenderer:A}:void 0)}var xM$=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,RM$={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"},vM$=/&(?:amp|lt|gt|quot|#39);/g;function CM$(A){return A.replace(vM$,(Q)=>RM$[Q]??Q)}function WzA(A){return A.replace(xM$,(Q,$)=>{return`<div class="mermaid">${CM$($)}</div>`})}var VT2=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function FT2(A){let Q={};for(let w of A.matchAll(VT2)){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(VT2,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
5864
5864
 
5865
5865
  `).trim();return{attributes:Q,markdown:$}}var hM$=/<!--\s*\.break\s*-->/;function LT2(A){let Q=A.split(hM$);return Q.length>1?Q:null}import{jsxDEV as gL}from"preact/jsx-dev-runtime";var HzA=({markdown:A,deck:Q})=>{let $=Hb(),B=A.split(/^---$/gm).map((U)=>U.trim()).map((U)=>{let{attributes:G,markdown:D}=FT2(U),q=LT2(D),V;if(q)V=`<div class="slide-columns">${q.map((F)=>`<div class="slide-column">${WzA($(F.trim()))}</div>`).join("")}</div>`;else V=WzA($(D));return{attributes:G,htmlContent:V}}),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)=>gL("section",{...U,dangerouslySetInnerHTML:{__html:G}},D,!1,void 0,this));return gL("section",{className:"presentation-section",children:[Y&&gL(E6,{title:Y,...Z?{description:Z}:{},...H?{ogImage:H}:{},ogType:"article"},void 0,!1,void 0,this),gL("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),gL("div",{className:"reveal",children:gL("div",{className:"slides",children:K},void 0,!1,void 0,this)},void 0,!1,void 0,this),gL("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&&gL("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),gL("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 gl$=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()}),ln2=W.object({site:W.object({title:W.string(),previewUrl:W.string().optional(),liveUrl:W.string().optional()}),environments:W.array(gl$),managementUrl:W.string().optional()});function JVA(A){if(A.active)return A.active.state;if(A.lastFailure)return"failed";if(A.lastSuccess)return"current";return"not built"}function Sl$(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 pn2(A){let Q=A.environment?JVA(A.environment):"unavailable";return HX("div",{class:`pipeline-metric site-health-metric site-health-metric--${Q}`},[HX("dt",{},[HX("span",{class:"site-health-dot","aria-hidden":"true"}),A.label]),HX("dd",{},Q),A.environment?HX("small",{class:"muted"},Sl$(A.environment)):null])}function zVA(A,Q,$="external"){return HX("a",{class:`widget-action widget-action--${$==="manage"?"primary":"secondary"}`,href:A,...$==="external"?{target:"_blank",rel:"noreferrer"}:{}},[HX("span",{},Q),HX("span",{class:"widget-action-arrow","aria-hidden":"true"},$==="external"?"\u2197":"\u2192")])}function ml$(A){let Q=ln2.safeParse(A.data);if(!Q.success)return HX("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(zVA($.site.previewUrl,"Open preview"));if($.site.liveUrl)Y.push(zVA($.site.liveUrl,"Open live"));if($.managementUrl)Y.push(zVA($.managementUrl,"Open in CMS","manage"));return HX("div",{class:"pipeline-digest site-health-widget"},[HX("dl",{class:"pipeline-metrics"},[HX(pn2,{label:"Preview",environment:w}),HX(pn2,{label:"Live",environment:B})]),X.length>0?HX("section",{class:"pipeline-failures"},[HX("h4",{},"Needs attention"),...X.map((Z)=>HX("div",{class:"pipeline-failure",key:Z.environment},[HX("strong",{},Z.environment),HX("span",{},Z.lastFailure?.message)]))]):null,Y.length>0?HX("nav",{class:"widget-actions","aria-label":"Site actions"},Y):null])}function ul$(A){let Q=ln2.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:$?JVA($):"unavailable",...$?.lastFailure?{tone:"warn"}:{tone:"good"}},{label:"Live",value:w?JVA(w):"unavailable",...w?.lastFailure?{tone:"warn"}:{tone:"good"}}],needsOperator:B}}async function in2(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:ml$,clientStyles:cn2,dataProvider:async()=>({...await Q.getSnapshot(),...$?{managementUrl:$}:{}}),digestProvider:ul$}})}v0();jX();var cl$=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()}),pl$=W.object({show:W.boolean().default(!1),label:W.string().optional(),slot:W.enum(Sj).default("primary"),priority:W.number().min(0).max(100).default(50)}).optional(),ll$=W.object({id:W.string(),path:W.string(),title:W.string().default(""),pageLabel:W.string().optional(),description:W.string().default(""),sections:W.array(cl$).default([]),layout:W.string().default("default"),fullscreen:W.boolean().optional(),pluginId:W.string().optional(),sourceEntityType:W.string().optional(),external:W.boolean().optional(),navigation:pl$}),dn2=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:Or.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(ll$).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(Sj).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 nn2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.204",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 VVA 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",nn2,{...A,layouts:Q},dn2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new Bk0(A.logger),this._slotRegistry=new vM0,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 GVA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},this.buildStatusService=new DVA(A.runtimeState,A.jobs),await this.buildStatusService.initialize(),vn2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Yk0(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=_z.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new UVA(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 KVA(this.config,A,this.id,this.logger,this.buildStatusService),this.siteWorkspaceProvider=new qVA({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(oa,async()=>{let $=await this.getInstructions();if($)A.registerInstructions($);return{success:!0}}),En2({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}async onReady(A){if(!this.siteWorkspaceProvider)return;let Q=await this.siteWorkspaceProvider.registerCmsWorkspace();await in2(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 gn2(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 Jy(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 Jy(A.messaging.send,this.config.siteInfo);return`## Your Site
6921
+ `;var gl$=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()}),ln2=W.object({site:W.object({title:W.string(),previewUrl:W.string().optional(),liveUrl:W.string().optional()}),environments:W.array(gl$),managementUrl:W.string().optional()});function JVA(A){if(A.active)return A.active.state;if(A.lastFailure)return"failed";if(A.lastSuccess)return"current";return"not built"}function Sl$(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 pn2(A){let Q=A.environment?JVA(A.environment):"unavailable";return HX("div",{class:`pipeline-metric site-health-metric site-health-metric--${Q}`},[HX("dt",{},[HX("span",{class:"site-health-dot","aria-hidden":"true"}),A.label]),HX("dd",{},Q),A.environment?HX("small",{class:"muted"},Sl$(A.environment)):null])}function zVA(A,Q,$="external"){return HX("a",{class:`widget-action widget-action--${$==="manage"?"primary":"secondary"}`,href:A,...$==="external"?{target:"_blank",rel:"noreferrer"}:{}},[HX("span",{},Q),HX("span",{class:"widget-action-arrow","aria-hidden":"true"},$==="external"?"\u2197":"\u2192")])}function ml$(A){let Q=ln2.safeParse(A.data);if(!Q.success)return HX("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(zVA($.site.previewUrl,"Open preview"));if($.site.liveUrl)Y.push(zVA($.site.liveUrl,"Open live"));if($.managementUrl)Y.push(zVA($.managementUrl,"Open in CMS","manage"));return HX("div",{class:"pipeline-digest site-health-widget"},[HX("dl",{class:"pipeline-metrics"},[HX(pn2,{label:"Preview",environment:w}),HX(pn2,{label:"Live",environment:B})]),X.length>0?HX("section",{class:"pipeline-failures"},[HX("h4",{},"Needs attention"),...X.map((Z)=>HX("div",{class:"pipeline-failure",key:Z.environment},[HX("strong",{},Z.environment),HX("span",{},Z.lastFailure?.message)]))]):null,Y.length>0?HX("nav",{class:"widget-actions","aria-label":"Site actions"},Y):null])}function ul$(A){let Q=ln2.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:$?JVA($):"unavailable",...$?.lastFailure?{tone:"warn"}:{tone:"good"}},{label:"Live",value:w?JVA(w):"unavailable",...w?.lastFailure?{tone:"warn"}:{tone:"good"}}],needsOperator:B}}async function in2(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:ml$,clientStyles:cn2,dataProvider:async()=>({...await Q.getSnapshot(),...$?{managementUrl:$}:{}}),digestProvider:ul$}})}v0();jX();var cl$=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()}),pl$=W.object({show:W.boolean().default(!1),label:W.string().optional(),slot:W.enum(Sj).default("primary"),priority:W.number().min(0).max(100).default(50)}).optional(),ll$=W.object({id:W.string(),path:W.string(),title:W.string().default(""),pageLabel:W.string().optional(),description:W.string().default(""),sections:W.array(cl$).default([]),layout:W.string().default("default"),fullscreen:W.boolean().optional(),pluginId:W.string().optional(),sourceEntityType:W.string().optional(),external:W.boolean().optional(),navigation:pl$}),dn2=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:Or.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(ll$).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(Sj).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 nn2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.206",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 VVA 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",nn2,{...A,layouts:Q},dn2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new Bk0(A.logger),this._slotRegistry=new vM0,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 GVA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},this.buildStatusService=new DVA(A.runtimeState,A.jobs),await this.buildStatusService.initialize(),vn2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Yk0(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=_z.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new UVA(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 KVA(this.config,A,this.id,this.logger,this.buildStatusService),this.siteWorkspaceProvider=new qVA({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(oa,async()=>{let $=await this.getInstructions();if($)A.registerInstructions($);return{success:!0}}),En2({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}async onReady(A){if(!this.siteWorkspaceProvider)return;let Q=await this.siteWorkspaceProvider.registerCmsWorkspace();await in2(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 gn2(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 Jy(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 Jy(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 Vy(A={}){return new VVA(A)}zA();zA();v0();var FVA=W.object({routeId:W.string(),sectionId:W.string()}),dl$=W.object({routeId:W.string(),sectionId:W.string()}),sB0=U6.extend({entityType:W.literal("site-content"),template:W.string().optional(),content:W.string(),metadata:dl$});zA();class rn2 extends zQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:sB0,frontmatterSchema:FVA})}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 LVA=new rn2;v0();var Zk0=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")}),fo5=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()});v0();var nl$=W.looseObject({id:W.string(),template:W.string().optional(),content:W.unknown().optional()}),rl$=W.looseObject({id:W.string(),title:W.string().optional(),description:W.string().optional(),sections:W.array(nl$)}),ol$=W.array(rl$);class IVA{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=ol$.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,V={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:V})}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 NVA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new IVA(A)}async generateContent(A,Q){let $=Zk0.parse(A);return this.operations.generate($,this.siteConfig,Q)}}jX();v0();var sl$=W.object({namespace:W.string(),sections:W.record(W.string(),W.any())}),on2=W.custom((A)=>sl$.safeParse(A).success),_VA=W.object({definitions:W.union([on2,W.array(on2)]).optional()});zA();function sn2(A,Q){return[e8(Q,"generate","Generate content for all routes, a specific route, or a specific section",Zk0,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 an2={name:"@brains/site-content",version:"0.2.0-alpha.204",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 PVA extends d6{siteContentService;constructor(A={}){super("site-content",an2,A,_VA)}async onRegister(A){A.entities.register("site-content",sB0,LVA);for(let Q of uk(this.config.definitions))A.templates.register(aj(Q),Q.namespace);this.siteContentService=new NVA(A)}async getTools(){return sn2(()=>this.siteContentService,this.id)}}function Fy(A={}){return new PVA(A)}zA();jX();zA();v0();jX();var tl$=W.object({}),el$=W.object({}),aB0=U6.extend({id:W.literal("site-info"),entityType:W.literal("site-info"),metadata:el$});var fr=oS0.omit({url:!0,analyticsScript:!0});zA();v0();var Ai$=W.record(W.string(),W.unknown());class aL extends zQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:aB0,frontmatterSchema:fr,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=fr.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("",Ai$.parse(Q))}}class tL{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,$){return tL.instance??=new tL(A,Q,$),tL.instance}static resetInstance(){tL.instance=null}static createFresh(A,Q,$){return new tL(A,Q,$)}constructor(A,Q,$){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new aL;let w=tL.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}}v0();var Qi$=new aL,$i$=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}:{}})),wi$=W.looseObject({socialLinks:W.array($i$).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?Qi$.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=wi$.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 tn2={name:"@brains/site-info",version:"0.2.0-alpha.204",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 Xi$=new aL,Yi$="site-info";class bVA extends c6{entityType=Yi$;schema=aB0;adapter=Xi$;defaultSiteInfo;constructor(A){super("site-info",tn2,{},MY);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new Wk0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=tL.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(ra,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:oa,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Ly(A){return new bVA(A)}var Zi$=new aL;async function tB0(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 Zi$.parseSiteInfoBody($.content)}function en2(A,Q){let $=A.metadata.publishedAt??A.created,w=Q.metadata.publishedAt??Q.created;return new Date(w).getTime()-new Date($).getTime()}async function Hk0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(en2).slice(0,Q.count).map(Q.parse)}function jVA(A){if(!A)throw Error("CTA not configured in site-info");return A}v0();var Ar2=W.object({label:W.string(),href:W.string(),priority:W.number()}),Wi$=W.object({primary:W.array(Ar2),secondary:W.array(Ar2)}),Hi$=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")}),Ki$=fr.extend({navigation:Wi$,copyright:W.string(),socialLinks:W.array(Hi$).optional().describe("Social media links from profile entity")});zA();wD();vr();v0();var MVA=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();Kw();p2();v0();var qi$=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()}),Xa5=CU.extend({title:W.string().optional(),slug:W.string().optional()});class kVA extends SZ{constructor(A,Q){super(A,Q,{schema:qi$,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 Vy(A={}){return new VVA(A)}zA();zA();v0();var FVA=W.object({routeId:W.string(),sectionId:W.string()}),dl$=W.object({routeId:W.string(),sectionId:W.string()}),sB0=U6.extend({entityType:W.literal("site-content"),template:W.string().optional(),content:W.string(),metadata:dl$});zA();class rn2 extends zQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:sB0,frontmatterSchema:FVA})}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 LVA=new rn2;v0();var Zk0=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")}),fo5=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()});v0();var nl$=W.looseObject({id:W.string(),template:W.string().optional(),content:W.unknown().optional()}),rl$=W.looseObject({id:W.string(),title:W.string().optional(),description:W.string().optional(),sections:W.array(nl$)}),ol$=W.array(rl$);class IVA{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=ol$.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,V={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:V})}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 NVA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new IVA(A)}async generateContent(A,Q){let $=Zk0.parse(A);return this.operations.generate($,this.siteConfig,Q)}}jX();v0();var sl$=W.object({namespace:W.string(),sections:W.record(W.string(),W.any())}),on2=W.custom((A)=>sl$.safeParse(A).success),_VA=W.object({definitions:W.union([on2,W.array(on2)]).optional()});zA();function sn2(A,Q){return[e8(Q,"generate","Generate content for all routes, a specific route, or a specific section",Zk0,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 an2={name:"@brains/site-content",version:"0.2.0-alpha.206",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 PVA extends d6{siteContentService;constructor(A={}){super("site-content",an2,A,_VA)}async onRegister(A){A.entities.register("site-content",sB0,LVA);for(let Q of uk(this.config.definitions))A.templates.register(aj(Q),Q.namespace);this.siteContentService=new NVA(A)}async getTools(){return sn2(()=>this.siteContentService,this.id)}}function Fy(A={}){return new PVA(A)}zA();jX();zA();v0();jX();var tl$=W.object({}),el$=W.object({}),aB0=U6.extend({id:W.literal("site-info"),entityType:W.literal("site-info"),metadata:el$});var fr=oS0.omit({url:!0,analyticsScript:!0});zA();v0();var Ai$=W.record(W.string(),W.unknown());class aL extends zQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:aB0,frontmatterSchema:fr,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=fr.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("",Ai$.parse(Q))}}class tL{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,$){return tL.instance??=new tL(A,Q,$),tL.instance}static resetInstance(){tL.instance=null}static createFresh(A,Q,$){return new tL(A,Q,$)}constructor(A,Q,$){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new aL;let w=tL.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}}v0();var Qi$=new aL,$i$=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}:{}})),wi$=W.looseObject({socialLinks:W.array($i$).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?Qi$.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=wi$.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 tn2={name:"@brains/site-info",version:"0.2.0-alpha.206",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 Xi$=new aL,Yi$="site-info";class bVA extends c6{entityType=Yi$;schema=aB0;adapter=Xi$;defaultSiteInfo;constructor(A){super("site-info",tn2,{},MY);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new Wk0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=tL.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(ra,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:oa,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Ly(A){return new bVA(A)}var Zi$=new aL;async function tB0(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 Zi$.parseSiteInfoBody($.content)}function en2(A,Q){let $=A.metadata.publishedAt??A.created,w=Q.metadata.publishedAt??Q.created;return new Date(w).getTime()-new Date($).getTime()}async function Hk0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(en2).slice(0,Q.count).map(Q.parse)}function jVA(A){if(!A)throw Error("CTA not configured in site-info");return A}v0();var Ar2=W.object({label:W.string(),href:W.string(),priority:W.number()}),Wi$=W.object({primary:W.array(Ar2),secondary:W.array(Ar2)}),Hi$=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")}),Ki$=fr.extend({navigation:Wi$,copyright:W.string(),socialLinks:W.array(Hi$).optional().describe("Social media links from profile entity")});zA();wD();vr();v0();var MVA=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();Kw();p2();v0();var qi$=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()}),Xa5=CU.extend({title:W.string().optional(),slug:W.string().optional()});class kVA extends SZ{constructor(A,Q){super(A,Q,{schema:qi$,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();vr();wD();function gi$(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),oY("header",{className:"printable-hero",children:[oY("div",{className:"printable-masthead",children:Q.brandLabel&&oY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),oY("div",{children:[oY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&oY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),oY("div",{className:"printable-meta",children:[Q.author&&oY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),$&&oY("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&&oY("figure",{className:"printable-cover-wrap",children:oY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),oY(BX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&oY("footer",{className:"printable-footer",children:[oY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&oY("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 Pd$=26214400,bd$=60000;class SVA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Dk0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=jd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Ld$(_d$(Nd$(),"brain-blog-printable-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/printable/post/${Q.id}`,template:Nr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:Pd$,timeoutMs:bd$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Md$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await Id$(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),$=KB.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 jd$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=KB.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 Md$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}import{mkdtemp as Rd$,rm as vd$}from"fs/promises";import{tmpdir as Cd$}from"os";import{join as hd$}from"path";u4();p2();wD();v0();import{jsxDEV as xd$}from"preact/jsx-dev-runtime";var B90="og-image",kd$="blog:og-image",_r2=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()}),Pr2={name:kd$,pluginId:"blog",schema:_r2,renderers:{image:fd$}};function Od$(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 fd$(A){let Q=_r2.parse(A);return xd$(Kb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Od$(Q.publishedAt)},void 0,!1,void 0,this)}var Ed$={width:1200,height:630},Td$=60000;class mVA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??w90}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==B90)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=yd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Rd$(hd$(Cd$(),"brain-blog-og-image-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/og/post/${Q.id}`,template:Pr2,format:"image",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),Ed$,{timeoutMs:Td$,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${gd$(Q)}-og.png`}}finally{await X.close()}}finally{await vd$(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),$=KB.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 yd$(A,Q={}){let{frontmatter:$}=t8(A.content),w=KB.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 gd$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var br2={name:"@brains/blog",version:"0.2.0-alpha.204",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 uVA extends c6{entityType=Mb.entityType;schema=xr;adapter=Mb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",br2,A,MVA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new kVA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Yr2()}getDataSources(){return[new fVA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (kr2(),Mr2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),Zr2(A,this.logger),Wr2(A,this.logger),Kr2(A,this.logger),Ur2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Dk0,new SVA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",B90,new mVA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=D9.getInstance().register(vVA()),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:B90,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 cVA(A={}){return new uVA(A)}wD();vr();zA();v0();b9();zA();v0();var nJ=W.object({title:W.string(),slug:W.string(),coverImageId:W.string().optional()}),ud$=W.object({title:W.string(),slug:W.string()}),cd$=W.object({title:W.string(),slug:W.string()}),Ax=U6.extend({entityType:W.literal("series"),metadata:cd$}),qk0=Ax.extend({frontmatter:nJ}),pd$=qk0.extend({description:W.string().optional(),postCount:W.number(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Or2=W.object({description:W.string().optional()});function _y(A){return new P$(Or2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}zA();class pVA extends zQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:Ax,frontmatterSchema:nJ,supportsCoverImage:!0,bodyFormatter:_y("")})}toMarkdown(A){let Q,$={};try{Q=this.parseFrontMatter(A.content,nJ).coverImageId,$=_y(A.metadata.title).parse(this.extractBody(A.content))}catch{}let w={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=_y(A.metadata.title).format($);return this.buildMarkdown(X,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,nJ);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,nJ);return _y(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var Qx=new pVA;zA();p2();yZ();v0();var ld$=W.object({seriesName:W.string().optional(),seriesIndex:W.number().optional()});function zk0(A){let Q=ld$.safeParse(A);return Q.success?Q.data:{}}function Py(A){return zk0(A.metadata).seriesName}function fr2(A){return zk0(A.metadata).seriesIndex}function xr2(A,Q){let $=fr2(A)??Number.MAX_SAFE_INTEGER,w=fr2(Q)??Number.MAX_SAFE_INTEGER;return $-w}class lVA{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 $=Py(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=Py(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:O1(A)};return i7("",Q)}}zA();v0();var id$=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()})}),dd$=W.object({type:W.enum(["list","detail"]),seriesName:W.string().optional()});function nd$(A){let Q=dd$.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let $=id$.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 Rr2(A){let Q=MQ(A.content,nJ);return qk0.parse({...A,frontmatter:Q.metadata})}class iVA{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=nd$(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=Rr2(X),Z=Qx.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=Rr2(w),X=Qx.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=Py(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(xr2),$}}zA();v0();yZ();var rd$=W.object({prompt:W.string().optional(),title:W.string().optional(),seriesId:W.string().optional()}),od$=W.object({title:W.string().optional(),excerpt:W.string().optional()});class Jk0{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),oY("header",{className:"printable-hero",children:[oY("div",{className:"printable-masthead",children:Q.brandLabel&&oY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),oY("div",{children:[oY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&oY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),oY("div",{className:"printable-meta",children:[Q.author&&oY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),$&&oY("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&&oY("figure",{className:"printable-cover-wrap",children:oY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),oY(BX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&oY("footer",{className:"printable-footer",children:[oY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&oY("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 Pd$=26214400,bd$=60000;class SVA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Dk0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=jd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Ld$(_d$(Nd$(),"brain-blog-printable-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/printable/post/${Q.id}`,template:Nr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:Pd$,timeoutMs:bd$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Md$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await Id$(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),$=KB.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 jd$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=KB.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 Md$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}import{mkdtemp as Rd$,rm as vd$}from"fs/promises";import{tmpdir as Cd$}from"os";import{join as hd$}from"path";u4();p2();wD();v0();import{jsxDEV as xd$}from"preact/jsx-dev-runtime";var B90="og-image",kd$="blog:og-image",_r2=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()}),Pr2={name:kd$,pluginId:"blog",schema:_r2,renderers:{image:fd$}};function Od$(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 fd$(A){let Q=_r2.parse(A);return xd$(Kb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:Od$(Q.publishedAt)},void 0,!1,void 0,this)}var Ed$={width:1200,height:630},Td$=60000;class mVA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??w90}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==B90)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let $=yd$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await Rd$(hd$(Cd$(),"brain-blog-og-image-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/og/post/${Q.id}`,template:Pr2,format:"image",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),Ed$,{timeoutMs:Td$,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${gd$(Q)}-og.png`}}finally{await X.close()}}finally{await vd$(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),$=KB.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 yd$(A,Q={}){let{frontmatter:$}=t8(A.content),w=KB.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 gd$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var br2={name:"@brains/blog",version:"0.2.0-alpha.206",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 uVA extends c6{entityType=Mb.entityType;schema=xr;adapter=Mb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",br2,A,MVA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new kVA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Yr2()}getDataSources(){return[new fVA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (kr2(),Mr2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),Zr2(A,this.logger),Wr2(A,this.logger),Kr2(A,this.logger),Ur2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",Dk0,new SVA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",B90,new mVA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=D9.getInstance().register(vVA()),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:B90,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 cVA(A={}){return new uVA(A)}wD();vr();zA();v0();b9();zA();v0();var nJ=W.object({title:W.string(),slug:W.string(),coverImageId:W.string().optional()}),ud$=W.object({title:W.string(),slug:W.string()}),cd$=W.object({title:W.string(),slug:W.string()}),Ax=U6.extend({entityType:W.literal("series"),metadata:cd$}),qk0=Ax.extend({frontmatter:nJ}),pd$=qk0.extend({description:W.string().optional(),postCount:W.number(),coverImageUrl:W.string().optional(),coverImageWidth:W.number().optional(),coverImageHeight:W.number().optional()}),Or2=W.object({description:W.string().optional()});function _y(A){return new P$(Or2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}zA();class pVA extends zQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:Ax,frontmatterSchema:nJ,supportsCoverImage:!0,bodyFormatter:_y("")})}toMarkdown(A){let Q,$={};try{Q=this.parseFrontMatter(A.content,nJ).coverImageId,$=_y(A.metadata.title).parse(this.extractBody(A.content))}catch{}let w={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=_y(A.metadata.title).format($);return this.buildMarkdown(X,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,nJ);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,nJ);return _y(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var Qx=new pVA;zA();p2();yZ();v0();var ld$=W.object({seriesName:W.string().optional(),seriesIndex:W.number().optional()});function zk0(A){let Q=ld$.safeParse(A);return Q.success?Q.data:{}}function Py(A){return zk0(A.metadata).seriesName}function fr2(A){return zk0(A.metadata).seriesIndex}function xr2(A,Q){let $=fr2(A)??Number.MAX_SAFE_INTEGER,w=fr2(Q)??Number.MAX_SAFE_INTEGER;return $-w}class lVA{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 $=Py(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=Py(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:O1(A)};return i7("",Q)}}zA();v0();var id$=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()})}),dd$=W.object({type:W.enum(["list","detail"]),seriesName:W.string().optional()});function nd$(A){let Q=dd$.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let $=id$.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 Rr2(A){let Q=MQ(A.content,nJ);return qk0.parse({...A,frontmatter:Q.metadata})}class iVA{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=nd$(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=Rr2(X),Z=Qx.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=Rr2(w),X=Qx.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=Py(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(xr2),$}}zA();v0();yZ();var rd$=W.object({prompt:W.string().optional(),title:W.string().optional(),seriesId:W.string().optional()}),od$=W.object({title:W.string().optional(),excerpt:W.string().optional()});class Jk0{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 Sr2({entity:A,config:Q}){let $=Ax.parse(A),w=Qx.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 dVA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:i8["ai.rizom.brain.series"],validate:!1,buildRecord:Sr2}}var mr2={name:"@brains/series",version:"0.2.0-alpha.204",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 ur2=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 nVA extends c6{entityType="series";schema=Ax;adapter=Qx;manager;unregisterAtprotoProjection;constructor(){super("series",mr2,{},MY)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Jk0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...yr2(),description:gr2}}getDataSources(){return[new iVA(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 $=Py(Q.entity),w=zk0(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 lVA(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=D9.getInstance().register(dVA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let $=ur2.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 $=ur2.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 Jk0(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 rVA(){return new nVA}zA();v0();zA();p2();v0();zA();var cr2=W.enum(["generating","draft","queued","published","failed"]),pr2=W.enum(["generating","draft","queued","published","failed"]),oVA="publishedAt is required when deck status is published",sVA=(A)=>A.status==="published"&&!A.publishedAt,aVA=(A)=>{if(sVA(A))throw Error(oVA)},eL=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:cr2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),QAB=W.object({title:W.string(),description:W.string().optional(),status:cr2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!sVA(A))return;Q.addIssue({code:W.ZodIssueCode.custom,path:["publishedAt"],message:oVA})}),Bn$=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(!sVA(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:oVA})}),Xn$=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()}),Er=U6.extend({entityType:W.literal("deck"),metadata:Bn$}),Vk0=Er.extend({frontmatter:Xn$,body:W.string(),ogImageUrl:W.string().optional()}),X90=Vk0.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 tVA extends zQ{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:Er,frontmatterSchema:eL,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,eL);aVA($);let w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontmatter(A),$=this.extractBody(A);aVA(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 Sr2({entity:A,config:Q}){let $=Ax.parse(A),w=Qx.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 dVA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:i8["ai.rizom.brain.series"],validate:!1,buildRecord:Sr2}}var mr2={name:"@brains/series",version:"0.2.0-alpha.206",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 ur2=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 nVA extends c6{entityType="series";schema=Ax;adapter=Qx;manager;unregisterAtprotoProjection;constructor(){super("series",mr2,{},MY)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Jk0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...yr2(),description:gr2}}getDataSources(){return[new iVA(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 $=Py(Q.entity),w=zk0(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 lVA(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=D9.getInstance().register(dVA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let $=ur2.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 $=ur2.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 Jk0(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 rVA(){return new nVA}zA();v0();zA();p2();v0();zA();var cr2=W.enum(["generating","draft","queued","published","failed"]),pr2=W.enum(["generating","draft","queued","published","failed"]),oVA="publishedAt is required when deck status is published",sVA=(A)=>A.status==="published"&&!A.publishedAt,aVA=(A)=>{if(sVA(A))throw Error(oVA)},eL=W.object({title:W.string(),slug:W.string().optional(),description:W.string().optional(),author:W.string().optional(),status:cr2,publishedAt:W.string().datetime().optional(),event:W.string().optional(),coverImageId:W.string().optional(),ogImageId:W.string().optional()}),QAB=W.object({title:W.string(),description:W.string().optional(),status:cr2,publishedAt:W.string().datetime().optional(),coverImageId:W.string().optional(),slug:W.string(),error:W.string().optional()}).superRefine((A,Q)=>{if(!sVA(A))return;Q.addIssue({code:W.ZodIssueCode.custom,path:["publishedAt"],message:oVA})}),Bn$=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(!sVA(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:oVA})}),Xn$=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()}),Er=U6.extend({entityType:W.literal("deck"),metadata:Bn$}),Vk0=Er.extend({frontmatter:Xn$,body:W.string(),ogImageUrl:W.string().optional()}),X90=Vk0.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 tVA extends zQ{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:Er,frontmatterSchema:eL,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,eL);aVA($);let w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontmatter(A),$=this.extractBody(A);aVA(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 Y90=new tVA;v0();aw();var Yn$=W.object({markdown:W.string().describe("Markdown content with slide separators (---)"),deck:X90.optional()}),eVA=W2({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:Yn$,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:HzA,fullscreen:!0}});aw();v0();var AFA=W.object({decks:W.array(Vk0)}),QFA=W.object({decks:W.array(X90),pageTitle:W.string().optional(),pageLabel:W.string().optional()});import{jsxDEV as $FA}from"preact/jsx-dev-runtime";var Zn$="Presentations",wFA=({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 $FA("div",{className:"deck-list bg-theme",children:$FA("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:$FA(a50,{label:Q&&Q!=="Decks"?Q:Zn$,items:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};b9();class Fk0 extends P${constructor(){super(AFA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var BFA=W2({name:"deck-list",description:"List view of all presentation decks",schema:QFA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new Fk0,layout:{component:wFA}});v0();zA();var Wn$=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")}),lr2=W2({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:Wn$,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)=>VW("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[VW("header",{className:"deck-carousel-header",children:VW("span",{className:"deck-carousel-wordmark","aria-label":$??Q,children:[VW("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VW(qn$,{children:[VW("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VW("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),VW("div",{className:"deck-carousel-body",children:VW("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VW("footer",{className:"deck-carousel-footer",children:[VW("span",{className:"deck-carousel-footer-meta",children:w??Q},void 0,!1,void 0,this),VW("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[VW("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VW("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 zn$,rm as Jn$}from"fs/promises";import{tmpdir as Vn$}from"os";import{join as Fn$}from"path";u4();p2();var Ln$=26214400,In$=60000,or2=20;class ZFA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ,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 $=Nn$(Q,{brandLabel:this.resolveBrandLabel()});if($.slides.length>or2)throw Error(`Refusing to render carousel with ${$.slides.length} slides; maxSlides=${or2}`);let w=await this.getThemeMode(),B=await zn$(Fn$(Vn$(),"brain-deck-carousel-"));try{let X=await XD({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:rr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:w},themeCSS:this.context.themeCSS}),Y=await YD({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:Ln$,timeoutMs:In$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${_n$(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await Jn$(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 Nn$(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 _n$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}v0();import{jsxDEV as jn$}from"preact/jsx-dev-runtime";var Lk0="og-image",Pn$="decks:og-image",sr2=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()}),ar2={name:Pn$,pluginId:"decks",schema:sr2,renderers:{image:bn$}};function bn$(A){let Q=sr2.parse(A),$=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return jn$(Kb,{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 WFA{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!==Lk0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=eL.parse($),X=Mn$(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 Ny({mediaPath:`/_media/og/deck/${Q.id}`,template:ar2,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:`${kn$(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 Mn$(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function kn$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}zA();async function tr2({entity:A,config:Q}){let $=Er.parse(A),w=MQ($.content,eL),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 HFA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:i8["ai.rizom.brain.deck"],validate:!1,buildRecord:tr2}}var er2={name:"@brains/decks",version:"0.2.0-alpha.204",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 fn$=W.object({prompt:W.string(),event:W.string().optional()}),xn$=W.object({title:W.string(),content:W.string()});class KFA extends c6{deps;entityType=Y90.entityType;schema=Y90.schema;adapter=Y90;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",er2,{},MY);this.deps=A}createGenerationHandler(A){return new YFA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":eVA,"deck-list":BFA,generation:lr2,description:ir2}}getDataSources(){return[new XFA(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(HFA()),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:sA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await tB0(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",dr2,new ZFA(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",Lk0,new WFA(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let $=fn$.parse(Q);return A.ai.generate({prompt:`${$.prompt}${$.event?`
7467
+ `}},void 0,!1,void 0,this),B.map((K,U)=>VW("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[VW("header",{className:"deck-carousel-header",children:VW("span",{className:"deck-carousel-wordmark","aria-label":$??Q,children:[VW("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VW(qn$,{children:[VW("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VW("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),VW("div",{className:"deck-carousel-body",children:VW("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VW("footer",{className:"deck-carousel-footer",children:[VW("span",{className:"deck-carousel-footer-meta",children:w??Q},void 0,!1,void 0,this),VW("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[VW("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VW("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 zn$,rm as Jn$}from"fs/promises";import{tmpdir as Vn$}from"os";import{join as Fn$}from"path";u4();p2();var Ln$=26214400,In$=60000,or2=20;class ZFA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ,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 $=Nn$(Q,{brandLabel:this.resolveBrandLabel()});if($.slides.length>or2)throw Error(`Refusing to render carousel with ${$.slides.length} slides; maxSlides=${or2}`);let w=await this.getThemeMode(),B=await zn$(Fn$(Vn$(),"brain-deck-carousel-"));try{let X=await XD({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:rr2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:w},themeCSS:this.context.themeCSS}),Y=await YD({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:Ln$,timeoutMs:In$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${_n$(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await Jn$(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 Nn$(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 _n$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}v0();import{jsxDEV as jn$}from"preact/jsx-dev-runtime";var Lk0="og-image",Pn$="decks:og-image",sr2=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()}),ar2={name:Pn$,pluginId:"decks",schema:sr2,renderers:{image:bn$}};function bn$(A){let Q=sr2.parse(A),$=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return jn$(Kb,{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 WFA{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!==Lk0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=eL.parse($),X=Mn$(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 Ny({mediaPath:`/_media/og/deck/${Q.id}`,template:ar2,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:`${kn$(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 Mn$(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function kn$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}zA();async function tr2({entity:A,config:Q}){let $=Er.parse(A),w=MQ($.content,eL),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 HFA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:i8["ai.rizom.brain.deck"],validate:!1,buildRecord:tr2}}var er2={name:"@brains/decks",version:"0.2.0-alpha.206",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 fn$=W.object({prompt:W.string(),event:W.string().optional()}),xn$=W.object({title:W.string(),content:W.string()});class KFA extends c6{deps;entityType=Y90.entityType;schema=Y90.schema;adapter=Y90;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",er2,{},MY);this.deps=A}createGenerationHandler(A){return new YFA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":eVA,"deck-list":BFA,generation:lr2,description:ir2}}getDataSources(){return[new XFA(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(HFA()),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:sA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await tB0(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",dr2,new ZFA(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",Lk0,new WFA(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let $=fn$.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 $=xn$.parse(Q);return A.ai.generate({prompt:`Title: ${$.title}
7470
7470
 
@@ -7621,9 +7621,9 @@ ${$.content}`,templateName:"decks:description"})})}}function W90(){return new KF
7621
7621
  background: transparent;
7622
7622
  }
7623
7623
 
7624
- `,Ho2=()=>V4("style",{children:Tn$},void 0,!1,void 0,this);import{jsxDEV as GQ,Fragment as yn$}from"preact/jsx-dev-runtime";var bk0=({title:A,description:Q,children:$,detail:w=!1,footer:B=!1,contentClassName:X=""})=>GQ(yn$,{children:[GQ(E6,{title:A,description:Q},void 0,!1,void 0,this),GQ(Ho2,{},void 0,!1,void 0,this),GQ("div",{className:`docs-handbook${w?" docs-handbook--detail":""}`,children:[GQ(Zo2,{},void 0,!1,void 0,this),GQ("div",{className:`${AI.wrap} ${X}`.trim(),children:[$,B&&GQ(Wo2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Ko2=({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:`${AI.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),GQ("h1",{className:`${AI.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:AI.primaryButton,href:yr($),children:"Start reading"},void 0,!1,void 0,this),GQ("a",{className:AI.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Uo2=({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:[gr($),"."]},void 0,!0,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Pk0($)}`,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),Go2=({group:A,index:Q})=>GQ("article",{className:"mb-16 last:mb-0",id:Pk0(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:[gr(Q),"."]},void 0,!0,void 0,this),GQ("h2",{className:`${AI.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:yr($),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),Do2=({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),qo2=({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#${Pk0(B)}`,children:[GQ("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[gr(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:yr(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),zo2=({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:yr(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:yr(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 Sr}from"preact/jsx-dev-runtime";var qFA=({docs:A})=>{let Q=H90(A),$=_k0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return Sr(bk0,{title:"Documentation",description:"Brains documentation",children:[Sr(Ko2,{docsCount:A.length,sectionsCount:$.length,startDoc:B},void 0,!1,void 0,this),Sr("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:[Sr(Uo2,{groups:$},void 0,!1,void 0,this),Sr("div",{children:$.map((X,Y)=>Sr(Go2,{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 ZD}from"preact/jsx-dev-runtime";var zFA=({doc:A,docs:Q,prevDoc:$,nextDoc:w})=>{let B=_k0(Q.length>0?Q:[A]),X=H90(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 ZD(bk0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[ZD(Do2,{title:A.metadata.title},void 0,!1,void 0,this),ZD("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[ZD(qo2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),ZD("article",{className:"min-w-0",children:[ZD("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[ZD("p",{className:`${AI.label} m-0 mb-6 flex items-baseline gap-3`,children:[ZD("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[gr(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),ZD("h1",{className:`${AI.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&&ZD("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),ZD("div",{className:"docs-article__body",children:ZD(BX,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),ZD(zo2,{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 gn$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Sn$=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}),mn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),sourcePath:W.string(),description:W.string().optional(),slug:W.string().optional()}),un$=W.object({title:W.string(),section:W.string(),order:W.number().int(),description:W.string().optional(),slug:W.string()}),K90=W.object({id:W.string(),entityType:W.literal("doc"),content:W.string(),created:W.string(),updated:W.string(),visibility:Sn$,metadata:un$,contentHash:W.string(),frontmatter:mn$,body:W.string()}),cn$=W.object({docs:W.array(K90),pagination:gn$.nullable(),baseUrl:W.string().optional()}),pn$=W.object({doc:K90,docs:W.array(K90),prevDoc:K90.nullable(),nextDoc:K90.nullable()});function Jo2(){return{"doc-list":W2({name:"doc-list",description:"Documentation index template",schema:cn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:qFA}}),"doc-detail":W2({name:"doc-detail",description:"Documentation page template",schema:pn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:zFA}})}}var Vo2={name:"@brains/doc",version:"0.2.0-alpha.204",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 JFA extends c6{entityType=Ik0.entityType;schema=Tr;adapter=Ik0;constructor(){super("docs",Vo2,{},MY)}getTemplates(){return Jo2()}getDataSources(){return[new Nk0(this.logger.child("DocDataSource"))]}}function U90(){return new JFA}zA();p2();v0();AB();v0();var VFA=W.literal("application/pdf"),Fo2=W.enum(["pending","draft","failed"]),FFA=W.object({title:W.string().optional(),mimeType:VFA,filename:W.string().min(1),pageCount:W.number().int().min(0).optional(),status:Fo2.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()}),mr=U6.extend({entityType:W.literal("document"),content:W.string().regex(/^data:application\/pdf;base64,.+$/),metadata:FFA});function G90(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 jk0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function LFA(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 Mk0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=mr;toMarkdown(A){return A.content}fromMarkdown(A){return G90(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}=G90(Q);return{entityType:"document",content:Q,metadata:{mimeType:w,...$}}}}var kb=new Mk0;async function XLA(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(() => (ka2(),Ma2))).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
+ `,Ho2=()=>V4("style",{children:Tn$},void 0,!1,void 0,this);import{jsxDEV as GQ,Fragment as yn$}from"preact/jsx-dev-runtime";var bk0=({title:A,description:Q,children:$,detail:w=!1,footer:B=!1,contentClassName:X=""})=>GQ(yn$,{children:[GQ(E6,{title:A,description:Q},void 0,!1,void 0,this),GQ(Ho2,{},void 0,!1,void 0,this),GQ("div",{className:`docs-handbook${w?" docs-handbook--detail":""}`,children:[GQ(Zo2,{},void 0,!1,void 0,this),GQ("div",{className:`${AI.wrap} ${X}`.trim(),children:[$,B&&GQ(Wo2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Ko2=({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:`${AI.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),GQ("h1",{className:`${AI.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:AI.primaryButton,href:yr($),children:"Start reading"},void 0,!1,void 0,this),GQ("a",{className:AI.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Uo2=({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:[gr($),"."]},void 0,!0,void 0,this),GQ("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Pk0($)}`,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),Go2=({group:A,index:Q})=>GQ("article",{className:"mb-16 last:mb-0",id:Pk0(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:[gr(Q),"."]},void 0,!0,void 0,this),GQ("h2",{className:`${AI.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:yr($),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),Do2=({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),qo2=({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#${Pk0(B)}`,children:[GQ("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[gr(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:yr(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),zo2=({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:yr(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:yr(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 Sr}from"preact/jsx-dev-runtime";var qFA=({docs:A})=>{let Q=H90(A),$=_k0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return Sr(bk0,{title:"Documentation",description:"Brains documentation",children:[Sr(Ko2,{docsCount:A.length,sectionsCount:$.length,startDoc:B},void 0,!1,void 0,this),Sr("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:[Sr(Uo2,{groups:$},void 0,!1,void 0,this),Sr("div",{children:$.map((X,Y)=>Sr(Go2,{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 ZD}from"preact/jsx-dev-runtime";var zFA=({doc:A,docs:Q,prevDoc:$,nextDoc:w})=>{let B=_k0(Q.length>0?Q:[A]),X=H90(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 ZD(bk0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[ZD(Do2,{title:A.metadata.title},void 0,!1,void 0,this),ZD("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[ZD(qo2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),ZD("article",{className:"min-w-0",children:[ZD("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[ZD("p",{className:`${AI.label} m-0 mb-6 flex items-baseline gap-3`,children:[ZD("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[gr(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),ZD("h1",{className:`${AI.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&&ZD("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),ZD("div",{className:"docs-article__body",children:ZD(BX,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),ZD(zo2,{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 gn$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Sn$=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}),mn$=W.object({title:W.string(),section:W.string(),order:W.number().int(),sourcePath:W.string(),description:W.string().optional(),slug:W.string().optional()}),un$=W.object({title:W.string(),section:W.string(),order:W.number().int(),description:W.string().optional(),slug:W.string()}),K90=W.object({id:W.string(),entityType:W.literal("doc"),content:W.string(),created:W.string(),updated:W.string(),visibility:Sn$,metadata:un$,contentHash:W.string(),frontmatter:mn$,body:W.string()}),cn$=W.object({docs:W.array(K90),pagination:gn$.nullable(),baseUrl:W.string().optional()}),pn$=W.object({doc:K90,docs:W.array(K90),prevDoc:K90.nullable(),nextDoc:K90.nullable()});function Jo2(){return{"doc-list":W2({name:"doc-list",description:"Documentation index template",schema:cn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:qFA}}),"doc-detail":W2({name:"doc-detail",description:"Documentation page template",schema:pn$,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:zFA}})}}var Vo2={name:"@brains/doc",version:"0.2.0-alpha.206",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 JFA extends c6{entityType=Ik0.entityType;schema=Tr;adapter=Ik0;constructor(){super("docs",Vo2,{},MY)}getTemplates(){return Jo2()}getDataSources(){return[new Nk0(this.logger.child("DocDataSource"))]}}function U90(){return new JFA}zA();p2();v0();AB();v0();var VFA=W.literal("application/pdf"),Fo2=W.enum(["pending","draft","failed"]),FFA=W.object({title:W.string().optional(),mimeType:VFA,filename:W.string().min(1),pageCount:W.number().int().min(0).optional(),status:Fo2.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()}),mr=U6.extend({entityType:W.literal("document"),content:W.string().regex(/^data:application\/pdf;base64,.+$/),metadata:FFA});function G90(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 jk0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function LFA(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 Mk0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=mr;toMarkdown(A){return A.content}fromMarkdown(A){return G90(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}=G90(Q);return{entityType:"document",content:Q,metadata:{mimeType:w,...$}}}}var kb=new Mk0;async function XLA(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(() => (ka2(),Ma2))).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();v0();import{createHash as xr$}from"crypto";var Rr$=26214400,vr$=20,Cr$=60000,Oa2=80,hr$=10,Er$={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()},xa2=W.object(Er$),GO0=xa2.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 DO0 extends H8{context;renderPdf;constructor(A,Q,$={}){super(A,{schema:GO0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=$.renderPdf??dJ}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??vr$,B=A.maxBytes??Rr$,X=A.timeoutMs??Cr$;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=YLA(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=LFA(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`),V=kb.createDocumentEntity({dataUrl:jk0(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 YH({entityService:this.context.entityService,entity:{...V,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=sA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await PF({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(yr$):[],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:EX(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||!gr$(X,$))w.push(B)}return w}}function YLA(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 Tr$(B)}function Tr$(A){let Q=O1(A.replace(/[/:]+/g," "))||`document-${fa2(A)}`;if(Q.length<=Oa2)return Q;let $=`-${fa2(A)}`;return`${Q.slice(0,Oa2-$.length).replace(/-+$/g,"")}${$}`}function fa2(A){return xr$("sha256").update(A).digest("hex").slice(0,hr$)}function yr$(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function gr$(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ra2={name:"@brains/document-plugin",version:"0.2.0-alpha.204",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 mr$=`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();v0();import{createHash as xr$}from"crypto";var Rr$=26214400,vr$=20,Cr$=60000,Oa2=80,hr$=10,Er$={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()},xa2=W.object(Er$),GO0=xa2.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 DO0 extends H8{context;renderPdf;constructor(A,Q,$={}){super(A,{schema:GO0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=$.renderPdf??dJ}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??vr$,B=A.maxBytes??Rr$,X=A.timeoutMs??Cr$;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=YLA(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=LFA(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`),V=kb.createDocumentEntity({dataUrl:jk0(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 YH({entityService:this.context.entityService,entity:{...V,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=sA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await PF({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(yr$):[],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:EX(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||!gr$(X,$))w.push(B)}return w}}function YLA(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 Tr$(B)}function Tr$(A){let Q=O1(A.replace(/[/:]+/g," "))||`document-${fa2(A)}`;if(Q.length<=Oa2)return Q;let $=`-${fa2(A)}`;return`${Q.slice(0,Oa2-$.length).replace(/-+$/g,"")}${$}`}function fa2(A){return xr$("sha256").update(A).digest("hex").slice(0,hr$)}function yr$(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function gr$(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var Ra2={name:"@brains/document-plugin",version:"0.2.0-alpha.206",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 mr$=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
7627
7627
  % Pending document placeholder
7628
7628
  %%EOF
7629
7629
  `).toString("base64")}`,ur$=W.object({}).catchall(W.unknown()).transform(()=>({})),ZLA={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function cr$(A,Q){let $=A.title?.trim();if($)return $;return Q.replace(/\.[^.]+$/,"").trim()||Q}function pr$(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function lr$(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 WLA extends d6{entityType=kb.entityType;schema=mr;adapter=kb;pluginContext;constructor(){super("document",Ra2,{},ur$)}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 DO0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===ZLA.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 $=GO0.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??YLA($,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!==ZLA.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let w;try{w=await Q.uploads.scoped(ZLA).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=cr$(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=kb.createDocumentEntity({dataUrl:pr$(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:lr$({entityId:H.entityId,filename:w.record.filename})}}}}async createPendingDocument(A,Q){let $=new Date().toISOString(),w=kb.createDocumentEntity({dataUrl:mr$,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await RC({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 HLA(){return new WLA}zA();v0();zA();v0();var va2=W.enum(["generating","failed"]),ir$=W.enum(["generating","failed"]),Wx=W.object({title:W.string().optional(),status:va2.optional(),error:W.string().optional()}),dr$=W.object({title:W.string(),status:va2.optional(),error:W.string().optional()}),nr$=W.object({title:W.string(),status:ir$.optional(),error:W.string().optional()}),Hx=U6.extend({entityType:W.literal("note"),metadata:nr$}),rr$=Hx.extend({frontmatter:Wx,body:W.string()});zA();v0();var or$=W.record(W.string(),W.unknown());class KLA extends zQ{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:Hx,frontmatterSchema:Wx})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Wx);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,Wx)}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,or$);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 Rb=new KLA;v0();var ULA=W.object({defaultPrompt:W.string().default("Create a note summarizing key concepts from my knowledge base")});v0();zA();var Ca2=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")}),GLA=W2({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:Ca2,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 Ao$={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Qo$=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:Qo$,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(Ao$).read(A.uploadId);await this.reportProgress($,{progress:35,message:"Extracting markdown from upload"});let B=await ya2({upload:w,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress($,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=Rb.fromMarkdown(B.content),Z=await YH({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,sA(w),A.stubContentHash),r5.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:EX(EX(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 ga2({entity:A,config:Q}){let $=Hx.parse(A),w=MQ($.content,Wx);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 zLA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:i8["ai.rizom.brain.note"],validate:!1,buildRecord:ga2}}var Sa2={name:"@brains/note",version:"0.2.0-alpha.204",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 ma2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},wo$=W.object({prompt:W.string()});class JLA extends c6{entityType=Rb.entityType;schema=Hx;adapter=Rb;unregisterAtprotoProjection;constructor(A={}){super("note",Sa2,A,ULA)}async interceptCreate(A,Q,$){if(A.from?.kind!==ma2.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(ma2).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ta2(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=DLA({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=Rb.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 qO0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:GLA}}async onRegister(A){A.jobs.registerHandler("upload-import",new qLA(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let $=wo$.parse(Q);return A.ai.generate({prompt:$.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=D9.getInstance().register(zLA())}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 Ry(A={}){return new JLA(A)}zA();v0();zA();var ua2=W.object({ref:W.string(),label:W.string()}),ca2=W.enum(["pending","draft","published"]),Bo$=W.enum(["pending","draft","published"]),g90=W.object({status:ca2,title:W.string(),url:W.string().url(),description:W.string().optional(),domain:W.string(),capturedAt:W.string().datetime(),source:ua2}),Xo$=g90.pick({title:!0,status:!0}),Yo$=W.object({title:W.string(),status:Bo$}),vy=U6.extend({entityType:W.literal("link"),metadata:Yo$});p2();v0();v0();var VLA=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 Kx extends zQ{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:vy,frontmatterSchema:g90})}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,g90),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 Ao=new Kx;zA();v0();var Zo$=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.")}),pa2=W2({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:Zo$,basePrompt:`You are an expert at extracting key information from webpage content.
7644
+ `}var Ao$={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Qo$=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:Qo$,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(Ao$).read(A.uploadId);await this.reportProgress($,{progress:35,message:"Extracting markdown from upload"});let B=await ya2({upload:w,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress($,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=Rb.fromMarkdown(B.content),Z=await YH({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,sA(w),A.stubContentHash),r5.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:EX(EX(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 ga2({entity:A,config:Q}){let $=Hx.parse(A),w=MQ($.content,Wx);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 zLA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:i8["ai.rizom.brain.note"],validate:!1,buildRecord:ga2}}var Sa2={name:"@brains/note",version:"0.2.0-alpha.206",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 ma2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},wo$=W.object({prompt:W.string()});class JLA extends c6{entityType=Rb.entityType;schema=Hx;adapter=Rb;unregisterAtprotoProjection;constructor(A={}){super("note",Sa2,A,ULA)}async interceptCreate(A,Q,$){if(A.from?.kind!==ma2.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(ma2).readRecord(w)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!Ta2(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=DLA({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=Rb.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 qO0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:GLA}}async onRegister(A){A.jobs.registerHandler("upload-import",new qLA(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let $=wo$.parse(Q);return A.ai.generate({prompt:$.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=D9.getInstance().register(zLA())}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 Ry(A={}){return new JLA(A)}zA();v0();zA();var ua2=W.object({ref:W.string(),label:W.string()}),ca2=W.enum(["pending","draft","published"]),Bo$=W.enum(["pending","draft","published"]),g90=W.object({status:ca2,title:W.string(),url:W.string().url(),description:W.string().optional(),domain:W.string(),capturedAt:W.string().datetime(),source:ua2}),Xo$=g90.pick({title:!0,status:!0}),Yo$=W.object({title:W.string(),status:Bo$}),vy=U6.extend({entityType:W.literal("link"),metadata:Yo$});p2();v0();v0();var VLA=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 Kx extends zQ{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:vy,frontmatterSchema:g90})}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,g90),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 Ao=new Kx;zA();v0();var Zo$=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.")}),pa2=W2({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:Zo$,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 Do$}from"crypto";class Ux{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(Ux.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),$=Do$("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();v0();Kw();var qo$=W.object({interfaceId:W.string().optional(),userId:W.string().optional(),channelId:W.string().optional(),channelName:W.string().optional(),timestamp:W.string().optional()}),zo$=W.object({url:W.url(),metadata:qo$.optional()}),w8B=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 JO0 extends H8{context;linkAdapter;urlFetcher;constructor(A,Q,$){super(A,{schema:zo$,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new Kx,this.urlFetcher=new Qo($?.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=Ux.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),V=Y.metadata.status;if(V!=="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:V};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,V=`Could not capture link: ${K.error}`,L=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:V,summary:V,domain:q,capturedAt:H,source:Z});return await YH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:L,metadata:{status:"pending",title:q}}}),{success:!1,entityId:X,title:q,url:w,status:"pending",error:V}}}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 V=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),L=await YH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:q}}});return await $.report({progress:g6.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:L.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 YH({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}),r5.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 da2({entity:A,config:Q}){let $=vy.parse(A),{frontmatter:w,summary:B}=Ao.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 PLA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:i8["ai.rizom.brain.link"],validate:!1,buildRecord:da2}}var na2={name:"@brains/link",version:"0.2.0-alpha.204",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 Vo$=W.object({url:W.url()});class bLA extends c6{entityType=Ao.entityType;schema=vy;adapter=Ao;shell;unregisterAtprotoProjection;constructor(A={}){super("link",na2,A,VLA)}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 JO0(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 JO0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:pa2,"link-list":la2,"link-detail":ia2}}getDataSources(){return[new _LA(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=D9.getInstance().register(PLA()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:$}=Vo$.parse(Q),B=await new Qo(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 V=this.linkAdapter.createLinkContent({status:"pending",title:q,url:w,description:U.description,summary:U.summary,domain:new URL(w).hostname,capturedAt:H,source:Z}),L=await YH({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:q}}});return await $.report({progress:g6.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:L.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 YH({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}),r5.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 da2({entity:A,config:Q}){let $=vy.parse(A),{frontmatter:w,summary:B}=Ao.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 PLA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:i8["ai.rizom.brain.link"],validate:!1,buildRecord:da2}}var na2={name:"@brains/link",version:"0.2.0-alpha.206",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 Vo$=W.object({url:W.url()});class bLA extends c6{entityType=Ao.entityType;schema=vy;adapter=Ao;shell;unregisterAtprotoProjection;constructor(A={}){super("link",na2,A,VLA)}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 JO0(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 JO0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:pa2,"link-list":la2,"link-detail":ia2}}getDataSources(){return[new _LA(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=D9.getInstance().register(PLA()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:$}=Vo$.parse(Q),B=await new Qo(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=Ux.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 RC({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[$]=Ux.extractUrls(Q);if($)return $}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function ra2(A={}){return new bLA(A)}var Cy=ra2;v0();var Fo$=W.object({conversationId:W.string().optional(),interfaceId:W.string().optional(),userId:W.string().optional(),messageId:W.string().optional(),timestamp:W.string().optional()}),R8B=W.object({id:W.string().optional(),metadata:Fo$.optional()});zA();v0();aw();v0();zA();var oa2=W.enum(["generating","draft","published","failed"]),sa2=W.enum(["generating","draft","published","failed"]),ZY=W.object({title:W.string(),slug:W.string().optional(),status:oa2,publishedAt:W.string().datetime().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.string().url().optional()}),Lo$=ZY.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:W.string(),error:W.string().optional()}),Io$=W.object({title:W.string(),status:sa2,publishedAt:W.string().datetime().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),No$=W.object({title:W.string(),slug:W.string().optional(),status:sa2,publishedAt:W.string().datetime().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.string().url().optional()}),Gx=U6.extend({entityType:W.literal("project"),metadata:Io$}),VO0=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),m90=Gx.extend({frontmatter:No$,body:W.string(),structuredContent:VO0.optional(),coverImageUrl:W.string().optional(),ogImageUrl:W.string().optional()}),_o$=m90.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()}),Po$=m90.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();b9();class jLA extends P${constructor(){super(VO0,{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 MLA=new jLA;class kLA extends zQ{constructor(){super({entityType:"project",purpose:"A portfolio project or case study.",schema:Gx,frontmatterSchema:ZY,supportsCoverImage:!0,bodyFormatter:MLA})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,ZY),w={...$,slug:$.slug??A.metadata.slug};return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,ZY),$=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,ZY)}parseStructuredContent(A){return MLA.parse(this.extractBody(A.content))}createProjectContent(A,Q){let $=MLA.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 hy=new kLA;v0();var OLA=W.looseObject({});import{jsxDEV as zD,Fragment as jo$}from"preact/jsx-dev-runtime";var bo$=({project:A})=>{let{frontmatter:Q,url:$,coverImageUrl:w}=A;return zD(C8,{href:$,children:[w&&zD("img",{src:w,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),zD($Y,{children:Q.title},void 0,!1,void 0,this),zD("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},fLA=({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 zD(jo$,{children:[zD(E6,{title:B,description:Y},void 0,!1,void 0,this),zD("div",{className:"project-list bg-theme",children:zD("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[zD("h1",{className:"text-4xl font-bold text-heading mb-12",children:B},void 0,!1,void 0,this),zD("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((Z)=>zD(bo$,{project:Z},Z.id,!1,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&zD("div",{className:"mt-12",children:zD(Db,{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 _w,Fragment as aa2}from"preact/jsx-dev-runtime";var Mo$=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return _w("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:_w("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?_w(C8,{href:A.url,variant:"compact",children:[_w("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),_w("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):_w("div",{},void 0,!1,void 0,this),Q&&_w(C8,{href:Q.url,variant:"compact",className:"md:text-right",children:[_w("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),_w("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)},FO0=({title:A,content:Q})=>{if(!Q)return null;return _w("section",{className:"mb-12",children:[_w("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),_w(BX,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},xLA=({project:A,prevProject:Q,nextProject:$})=>{let{frontmatter:w,structuredContent:B,metadata:X,coverImageUrl:Y}=A,Z=A.ogImageUrl??Y;return _w(aa2,{children:[_w(E6,{title:w.title,description:w.description,...Z?{ogImage:Z}:{},ogType:"article"},void 0,!1,void 0,this),_w("article",{className:"project-detail",children:_w("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:_w("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&_w(Ub,{src:Y,alt:w.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),_w("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),_w("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[_w("span",{className:"text-sm",children:X.year},void 0,!1,void 0,this),w.url&&_w(aa2,{children:[_w("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),_w("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),_w("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:w.description},void 0,!1,void 0,this),B&&_w("div",{className:"case-study",children:[_w(FO0,{title:"Context",content:B.context},void 0,!1,void 0,this),_w(FO0,{title:"Problem",content:B.problem},void 0,!1,void 0,this),_w(FO0,{title:"Solution",content:B.solution},void 0,!1,void 0,this),_w(FO0,{title:"Outcome",content:B.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_w(Mo$,{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)};v0();zA();var ko$=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)")}),RLA=W2({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:ko$,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),UX("section",{className:"project-shell",children:[UX("header",{className:"project-hero",children:[UX("div",{className:"project-index",children:[Q.brandLabel&&UX("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&UX("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),UX("div",{className:"project-title-panel",children:[UX("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),UX("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&UX("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),UX("div",{className:"printable-meta",children:[Q.year&&UX("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&UX("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&&UX("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),UX(BX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&UX("footer",{className:"printable-footer",children:[UX("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?UX("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 To$=26214400,yo$=60000;class hLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==NO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let $=go$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await vo$(Eo$(ho$(),"brain-project-printable-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/printable/project/${Q.id}`,template:At2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:To$,timeoutMs:yo$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${So$(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}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=ZY.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 go$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=ZY.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 So$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}u4();p2();v0();import{jsxDEV as co$}from"preact/jsx-dev-runtime";var _O0="og-image",mo$="portfolio:og-image",Qt2=W.object({title:W.string().min(1),description:W.string().optional(),year:W.number().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),$t2={name:mo$,pluginId:"portfolio",schema:Qt2,renderers:{image:uo$}};function uo$(A){let Q=Qt2.parse(A);return co$(Kb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class ELA{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!==_O0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$}=t8(Q.content),w=ZY.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 Ny({mediaPath:`/_media/og/project/${Q.id}`,template:$t2,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:`${po$(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 po$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var wt2={name:"@brains/portfolio",version:"0.2.0-alpha.204",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 io$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),do$=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}),Bt2=W.enum(["generating","draft","published","failed"]),no$=W.object({title:W.string(),slug:W.string().optional(),status:Bt2,publishedAt:W.string().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.url().optional()}),ro$=W.object({title:W.string(),status:Bt2,publishedAt:W.string().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),oo$=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),PO0=W.object({id:W.string(),entityType:W.literal("project"),content:W.string(),created:W.string(),updated:W.string(),visibility:do$,metadata:ro$,contentHash:W.string(),frontmatter:no$,body:W.string(),structuredContent:oo$.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()}),so$=W.object({projects:W.array(PO0),pageTitle:W.string().optional(),pagination:io$.nullable(),baseUrl:W.string().optional()}),ao$=W.object({prompt:W.string(),year:W.number()});function to$(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 TLA extends c6{entityType="project";schema=Gx;adapter=hy;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",wt2,A,OLA)}async interceptCreate(A,Q,$){if(!A.prompt||A.content)return{kind:"continue",input:A};let w=to$(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 LO0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":W2({name:"project-list",description:"Portfolio project list page template",schema:so$,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:fLA}}),"project-detail":W2({name:"project-detail",description:"Individual project case study template",schema:W.object({project:PO0,prevProject:PO0.nullable(),nextProject:PO0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:xLA}}),generation:RLA}}getDataSources(){return[new IO0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",NO0,new hLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",_O0,new ELA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=D9.getInstance().register(CLA())}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 $=ao$.parse(Q);return A.ai.generate({prompt:vLA($),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,ZY),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:sA(B)}})}return{success:!0}})}}function yLA(A={}){return new TLA(A)}zA();v0();aw();v0();zA();var Xt2=W.enum(["available","early access","coming soon","planned"]),Yt2=W.enum(["available","early access","coming soon","planned"]),Zt2=W.object({title:W.string(),description:W.string()}),Mz=W.object({name:W.string(),availability:Xt2,order:W.number(),ogImageId:W.string().optional()}),bO0=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(Zt2).min(1).max(6),story:W.string()}),f5B=Mz.pick({name:!0,availability:!0,order:!0}).extend({slug:W.string()}),eo$=W.object({name:W.string(),availability:Yt2,order:W.number(),slug:W.string()}),As$=W.object({name:W.string(),availability:Yt2,order:W.number(),ogImageId:W.string().optional()}),$o=U6.extend({entityType:W.literal("product"),metadata:eo$}),jO0=$o.extend({frontmatter:As$,body:bO0,labels:W.record(W.string(),W.string()),ogImageUrl:W.string().optional()}),Qs$=jO0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()});zA();p2();b9();class wo extends P${constructor(){super(bO0,{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 gLA extends zQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:$o,frontmatterSchema:Mz,bodyFormatter:new wo})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Mz);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Mz),$=O1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:$,availability:Q.availability,order:Q.order}}}}var MO0=new gLA;v0();zA();var Wt2=W.object({title:W.string(),description:W.string()}),Ht2=W.object({title:W.string(),description:W.string()}),$s$=W.object({title:W.string(),description:W.string()}),Kt2=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Dx=W.object({headline:W.string(),tagline:W.string()}),ws$=W.object({title:W.string(),description:W.string()}),kO0=W.object({vision:W.string(),pillars:W.array(Wt2).min(1).max(6),approach:W.array(ws$).min(1).max(6),productsIntro:W.string(),technologies:W.array($s$).min(1).max(6),benefits:W.array(Ht2).min(1).max(6),cta:Kt2}),Bs$=Dx.pick({headline:!0}).extend({slug:W.string()}),Xs$=W.object({headline:W.string(),slug:W.string()}),Ys$=W.object({headline:W.string(),tagline:W.string()}),Bo=U6.extend({entityType:W.literal("products-overview"),metadata:Xs$}),SLA=Bo.extend({frontmatter:Ys$,body:kO0,labels:W.record(W.string(),W.string())});zA();p2();b9();class Xo extends P${constructor(){super(kO0,{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 mLA extends zQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Bo,frontmatterSchema:Dx,bodyFormatter:new Xo})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Dx);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Dx),$=O1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:$}}}}var uLA=new mLA;zA();v0();var Zs$=W.object({entityType:W.string(),query:W.object({id:W.string().optional()}).optional()});function Ut2(A,Q){let $=MQ(A.content,Mz),w=Q.parse($.content),B=Q.getLabels();return jO0.parse({...A,frontmatter:$.metadata,body:w,labels:B})}function Gt2(A,Q){let $=MQ(A.content,Dx),w=Q.parse($.content),B=Q.getLabels();return SLA.parse({...A,frontmatter:$.metadata,body:w,labels:B})}class OO0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new Xo;productFormatter=new wo;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,$){let w=Zs$.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=Gt2(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:Ut2(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:Gt2(Z,this.overviewFormatter),products:Y.map((H)=>Ut2(H,this.productFormatter))})}}import{jsxDEV as v1,Fragment as Ks$}from"preact/jsx-dev-runtime";var Dt2=({overview:A,products:Q})=>{let{frontmatter:$,body:w,labels:B}=A;return v1(Ks$,{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),UX("section",{className:"project-shell",children:[UX("header",{className:"project-hero",children:[UX("div",{className:"project-index",children:[Q.brandLabel&&UX("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&UX("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),UX("div",{className:"project-title-panel",children:[UX("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),UX("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&UX("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),UX("div",{className:"printable-meta",children:[Q.year&&UX("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&UX("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&&UX("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),UX(BX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&UX("footer",{className:"printable-footer",children:[UX("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?UX("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 To$=26214400,yo$=60000;class hLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==NO0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let $=go$(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),w=await vo$(Eo$(ho$(),"brain-project-printable-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/printable/project/${Q.id}`,template:At2,format:"pdf",content:$,siteConfig:{title:$.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:To$,timeoutMs:yo$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${So$(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}async resolveCoverImageUrl(A){let{frontmatter:Q}=t8(A.content),$=ZY.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 go$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=ZY.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 So$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}u4();p2();v0();import{jsxDEV as co$}from"preact/jsx-dev-runtime";var _O0="og-image",mo$="portfolio:og-image",Qt2=W.object({title:W.string().min(1),description:W.string().optional(),year:W.number().optional(),brandLabel:W.string().optional(),coverImageUrl:W.string().optional()}),$t2={name:mo$,pluginId:"portfolio",schema:Qt2,renderers:{image:uo$}};function uo$(A){let Q=Qt2.parse(A);return co$(Kb,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class ELA{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!==_O0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$}=t8(Q.content),w=ZY.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 Ny({mediaPath:`/_media/og/project/${Q.id}`,template:$t2,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:`${po$(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 po$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.title)}var wt2={name:"@brains/portfolio",version:"0.2.0-alpha.206",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 io$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),do$=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}),Bt2=W.enum(["generating","draft","published","failed"]),no$=W.object({title:W.string(),slug:W.string().optional(),status:Bt2,publishedAt:W.string().optional(),description:W.string(),year:W.number(),coverImageId:W.string().optional(),ogImageId:W.string().optional(),url:W.url().optional()}),ro$=W.object({title:W.string(),status:Bt2,publishedAt:W.string().optional(),year:W.number(),slug:W.string(),error:W.string().optional()}),oo$=W.object({context:W.string(),problem:W.string(),solution:W.string(),outcome:W.string()}),PO0=W.object({id:W.string(),entityType:W.literal("project"),content:W.string(),created:W.string(),updated:W.string(),visibility:do$,metadata:ro$,contentHash:W.string(),frontmatter:no$,body:W.string(),structuredContent:oo$.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()}),so$=W.object({projects:W.array(PO0),pageTitle:W.string().optional(),pagination:io$.nullable(),baseUrl:W.string().optional()}),ao$=W.object({prompt:W.string(),year:W.number()});function to$(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 TLA extends c6{entityType="project";schema=Gx;adapter=hy;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",wt2,A,OLA)}async interceptCreate(A,Q,$){if(!A.prompt||A.content)return{kind:"continue",input:A};let w=to$(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 LO0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":W2({name:"project-list",description:"Portfolio project list page template",schema:so$,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:fLA}}),"project-detail":W2({name:"project-detail",description:"Individual project case study template",schema:W.object({project:PO0,prevProject:PO0.nullable(),nextProject:PO0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:xLA}}),generation:RLA}}getDataSources(){return[new IO0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",NO0,new hLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",_O0,new ELA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=D9.getInstance().register(CLA())}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 $=ao$.parse(Q);return A.ai.generate({prompt:vLA($),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,ZY),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:sA(B)}})}return{success:!0}})}}function yLA(A={}){return new TLA(A)}zA();v0();aw();v0();zA();var Xt2=W.enum(["available","early access","coming soon","planned"]),Yt2=W.enum(["available","early access","coming soon","planned"]),Zt2=W.object({title:W.string(),description:W.string()}),Mz=W.object({name:W.string(),availability:Xt2,order:W.number(),ogImageId:W.string().optional()}),bO0=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(Zt2).min(1).max(6),story:W.string()}),f5B=Mz.pick({name:!0,availability:!0,order:!0}).extend({slug:W.string()}),eo$=W.object({name:W.string(),availability:Yt2,order:W.number(),slug:W.string()}),As$=W.object({name:W.string(),availability:Yt2,order:W.number(),ogImageId:W.string().optional()}),$o=U6.extend({entityType:W.literal("product"),metadata:eo$}),jO0=$o.extend({frontmatter:As$,body:bO0,labels:W.record(W.string(),W.string()),ogImageUrl:W.string().optional()}),Qs$=jO0.extend({url:W.string().optional(),typeLabel:W.string().optional(),listUrl:W.string().optional(),listLabel:W.string().optional(),ogImageUrl:W.string().optional()});zA();p2();b9();class wo extends P${constructor(){super(bO0,{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 gLA extends zQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:$o,frontmatterSchema:Mz,bodyFormatter:new wo})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Mz);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Mz),$=O1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:$,availability:Q.availability,order:Q.order}}}}var MO0=new gLA;v0();zA();var Wt2=W.object({title:W.string(),description:W.string()}),Ht2=W.object({title:W.string(),description:W.string()}),$s$=W.object({title:W.string(),description:W.string()}),Kt2=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),Dx=W.object({headline:W.string(),tagline:W.string()}),ws$=W.object({title:W.string(),description:W.string()}),kO0=W.object({vision:W.string(),pillars:W.array(Wt2).min(1).max(6),approach:W.array(ws$).min(1).max(6),productsIntro:W.string(),technologies:W.array($s$).min(1).max(6),benefits:W.array(Ht2).min(1).max(6),cta:Kt2}),Bs$=Dx.pick({headline:!0}).extend({slug:W.string()}),Xs$=W.object({headline:W.string(),slug:W.string()}),Ys$=W.object({headline:W.string(),tagline:W.string()}),Bo=U6.extend({entityType:W.literal("products-overview"),metadata:Xs$}),SLA=Bo.extend({frontmatter:Ys$,body:kO0,labels:W.record(W.string(),W.string())});zA();p2();b9();class Xo extends P${constructor(){super(kO0,{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 mLA extends zQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Bo,frontmatterSchema:Dx,bodyFormatter:new Xo})}toMarkdown(A){let Q=this.extractBody(A.content);try{let $=this.parseFrontMatter(A.content,Dx);return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,Dx),$=O1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:$}}}}var uLA=new mLA;zA();v0();var Zs$=W.object({entityType:W.string(),query:W.object({id:W.string().optional()}).optional()});function Ut2(A,Q){let $=MQ(A.content,Mz),w=Q.parse($.content),B=Q.getLabels();return jO0.parse({...A,frontmatter:$.metadata,body:w,labels:B})}function Gt2(A,Q){let $=MQ(A.content,Dx),w=Q.parse($.content),B=Q.getLabels();return SLA.parse({...A,frontmatter:$.metadata,body:w,labels:B})}class OO0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new Xo;productFormatter=new wo;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,$){let w=Zs$.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=Gt2(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:Ut2(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:Gt2(Z,this.overviewFormatter),products:Y.map((H)=>Ut2(H,this.productFormatter))})}}import{jsxDEV as v1,Fragment as Ks$}from"preact/jsx-dev-runtime";var Dt2=({overview:A,products:Q})=>{let{frontmatter:$,body:w,labels:B}=A;return v1(Ks$,{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),JD("section",{className:"product-shell",children:[JD("header",{className:"product-hero",children:[Q.brandLabel&&JD("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),JD("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&JD("div",{className:"printable-meta",children:JD("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),JD("div",{className:"product-body-wrap",children:[JD("aside",{className:"product-rail","aria-hidden":"true",children:JD("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),JD(BX,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&JD("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 Fs$=26214400,Ls$=60000;class pLA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??dJ}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==fO0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let $=Is$(Q,{brandLabel:this.resolveBrandLabel()}),w=await qs$(Vs$(Js$(),"brain-product-printable-"));try{let B=await XD({outputDir:w,mediaPath:`/_media/printable/product/${Q.id}`,template:Jt2,format:"pdf",content:$,siteConfig:{title:$.name,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await YD({rootDir:w});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:Fs$,timeoutMs:Ls$,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Ns$(Q)}-printable.pdf`}}finally{await X.close()}}finally{await zs$(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 Is$(A,Q={}){let{frontmatter:$,content:w}=t8(A.content),B=Mz.parse($);return{name:B.name,body:w,availability:B.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function Ns$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}u4();p2();v0();import{jsxDEV as bs$}from"preact/jsx-dev-runtime";var xO0="og-image",_s$="products:og-image",Vt2=W.object({name:W.string().min(1),tagline:W.string().optional(),availability:W.string().optional(),brandLabel:W.string().optional()}),Ft2={name:_s$,pluginId:"products",schema:Vt2,renderers:{image:Ps$}};function Ps$(A){let Q=Vt2.parse(A);return bs$(Kb,{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 lLA{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!==xO0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:$,content:w}=t8(Q.content),B=Mz.parse($),X=js$(w,"Tagline"),Y=this.resolveBrandLabel(),Z={name:B.name,availability:B.availability,...X?{tagline:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Ny({mediaPath:`/_media/og/product/${Q.id}`,template:Ft2,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:`${Ms$(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 js$(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 Ms$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}var Lt2={name:"@brains/products",version:"0.2.0-alpha.204",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 Os$=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}),It2=W.object({id:W.string(),entityType:W.string(),content:W.string(),created:W.string(),updated:W.string(),visibility:Os$,metadata:W.record(W.string(),W.unknown()),contentHash:W.string()}),Nt2=W.enum(["available","early access","coming soon","planned"]),fs$=W.object({title:W.string(),description:W.string()}),xs$=W.object({name:W.string(),availability:Nt2,order:W.number(),ogImageId:W.string().optional()}),Rs$=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(fs$).min(1).max(6),story:W.string()}),vs$=W.object({name:W.string(),availability:Nt2,order:W.number(),slug:W.string()}),_t2=It2.extend({entityType:W.literal("product"),metadata:vs$,frontmatter:xs$,body:Rs$,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()}),RO0=W.object({title:W.string(),description:W.string()}),Cs$=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),hs$=W.object({headline:W.string(),tagline:W.string()}),Es$=W.object({vision:W.string(),pillars:W.array(RO0).min(1).max(6),approach:W.array(RO0).min(1).max(6),productsIntro:W.string(),technologies:W.array(RO0).min(1).max(6),benefits:W.array(RO0).min(1).max(6),cta:Cs$}),Ts$=W.object({headline:W.string(),slug:W.string()}),ys$=It2.extend({entityType:W.literal("products-overview"),metadata:Ts$,frontmatter:hs$,body:Es$,labels:W.record(W.string(),W.string())}),gs$=W.object({overview:ys$,products:W.array(_t2)}),Ss$=W.object({product:_t2});class iLA extends c6{entityType=MO0.entityType;schema=$o;adapter=MO0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",Lt2,A,cLA)}getTemplates(){return{"product-list":W2({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:gs$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Dt2}}),"product-detail":W2({name:"product-detail",description:"Individual product detail page",schema:Ss$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:qt2}})}}getDataSources(){return[new OO0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",fO0,new pLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",xO0,new lLA(A)),A.entities.register("products-overview",Bo,uLA)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function u90(A={}){return new iLA(A)}zA();v0();v0();var ms$=W.enum(["public","shared","restricted"]),Pt2=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:ms$.default("public"),sourceChangeBatchDelayMs:W.number().int().min(0).default(1000)});zA();v0();zA();var D9B=W.object({}),us$=W.record(W.string(),W.unknown()).transform(()=>({})),Yo=U6.extend({entityType:W.literal("topic"),metadata:us$}),q9B=W.object({content:W.string()}),bt2=W.object({title:W.string().describe("Topic title")});var Ey="topics",Pw="topic",dLA="topics-projection",jt2="topic:project",vO0="topics-plugin",Mt2="topics:batch-completed",kt2="topics-source-batch",CO0="topics:knowledge-map";class sJ extends zQ{constructor(){super({entityType:Pw,purpose:"A recurring theme or subject derived from the user's content.",schema:Yo,frontmatterSchema:bt2})}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:Pw}}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();v0();v0();var cs$=W.object({title:W.string().max(100),content:W.string(),relevanceScore:W.number().min(0).max(1)}),Ot2=W.array(cs$);var ps$=W.object({topics:Ot2}),ft2=W2({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:ps$,basePrompt:`You are an expert at analyzing content and extracting key topics.
8037
+ `).trim();return X.length>0?X:void 0}function Ms$(A){let Q=A.metadata.slug;return Q.length>0?Q:O1(A.metadata.name)}var Lt2={name:"@brains/products",version:"0.2.0-alpha.206",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 Os$=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}),It2=W.object({id:W.string(),entityType:W.string(),content:W.string(),created:W.string(),updated:W.string(),visibility:Os$,metadata:W.record(W.string(),W.unknown()),contentHash:W.string()}),Nt2=W.enum(["available","early access","coming soon","planned"]),fs$=W.object({title:W.string(),description:W.string()}),xs$=W.object({name:W.string(),availability:Nt2,order:W.number(),ogImageId:W.string().optional()}),Rs$=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(fs$).min(1).max(6),story:W.string()}),vs$=W.object({name:W.string(),availability:Nt2,order:W.number(),slug:W.string()}),_t2=It2.extend({entityType:W.literal("product"),metadata:vs$,frontmatter:xs$,body:Rs$,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()}),RO0=W.object({title:W.string(),description:W.string()}),Cs$=W.object({heading:W.string(),buttonText:W.string(),link:W.string()}),hs$=W.object({headline:W.string(),tagline:W.string()}),Es$=W.object({vision:W.string(),pillars:W.array(RO0).min(1).max(6),approach:W.array(RO0).min(1).max(6),productsIntro:W.string(),technologies:W.array(RO0).min(1).max(6),benefits:W.array(RO0).min(1).max(6),cta:Cs$}),Ts$=W.object({headline:W.string(),slug:W.string()}),ys$=It2.extend({entityType:W.literal("products-overview"),metadata:Ts$,frontmatter:hs$,body:Es$,labels:W.record(W.string(),W.string())}),gs$=W.object({overview:ys$,products:W.array(_t2)}),Ss$=W.object({product:_t2});class iLA extends c6{entityType=MO0.entityType;schema=$o;adapter=MO0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",Lt2,A,cLA)}getTemplates(){return{"product-list":W2({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:gs$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:Dt2}}),"product-detail":W2({name:"product-detail",description:"Individual product detail page",schema:Ss$,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:qt2}})}}getDataSources(){return[new OO0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",fO0,new pLA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",xO0,new lLA(A)),A.entities.register("products-overview",Bo,uLA)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function u90(A={}){return new iLA(A)}zA();v0();v0();var ms$=W.enum(["public","shared","restricted"]),Pt2=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:ms$.default("public"),sourceChangeBatchDelayMs:W.number().int().min(0).default(1000)});zA();v0();zA();var D9B=W.object({}),us$=W.record(W.string(),W.unknown()).transform(()=>({})),Yo=U6.extend({entityType:W.literal("topic"),metadata:us$}),q9B=W.object({content:W.string()}),bt2=W.object({title:W.string().describe("Topic title")});var Ey="topics",Pw="topic",dLA="topics-projection",jt2="topic:project",vO0="topics-plugin",Mt2="topics:batch-completed",kt2="topics-source-batch",CO0="topics:knowledge-map";class sJ extends zQ{constructor(){super({entityType:Pw,purpose:"A recurring theme or subject derived from the user's content.",schema:Yo,frontmatterSchema:bt2})}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:Pw}}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();v0();v0();var cs$=W.object({title:W.string().max(100),content:W.string(),relevanceScore:W.number().min(0).max(1)}),Ot2=W.array(cs$);var ps$=W.object({topics:Ot2}),ft2=W2({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:ps$,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
 
@@ -8349,13 +8349,13 @@ ${A.incomingTopic.content}`})}}function Pa$(A){if(A.length===0)return"";return A
8349
8349
 
8350
8350
  ${Q.content}`}).join(`
8351
8351
 
8352
- `)}async function yy(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 aJ(Q.entityService,$),U=w.topicMergeSynthesizer??new wIA(Q,$),G=await cO0(Q.entityService,void 0,Z),D=new Map,q=0,V=0,L=0;for(let _ of H){$.info(`Processing batch of ${_.length} entities`);let j=Pa$(_),b=pO0({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 m=await K.findMergeCandidate({incoming:R,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(m){let l=await U.synthesize({existingTopic:m.topic,incomingTopic:R}),a=await K.applySynthesizedMerge({existingId:m.topic.id,synthesized:{...l,title:m.title},visibility:Z});if(!a)throw Error(`Failed to merge topic: ${R.title}`);D.set(a.id,a),V++;continue}}let O=K.getTopicIdForTitle(R.title,Z);if(D.has(O)){L++;continue}let g=await K.createTopicOptimistic({title:R.title,content:R.content,visibility:Z});if(g.topic)D.set(g.topic.id,g.topic);if(g.created)q++;else L++}catch(O){$.error("Topic batch item failed",{title:R.title,error:sA(O)})}}catch(k){$.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:sA(k)})}}let F={created:q,merged:V,skipped:L,batches:H.length};if(q>0||V>0)await Q.messaging.send({type:Mt2,payload:F,broadcast:!0});return F}zA();v0();var ba$=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 BIA{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 et2(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 ja$({context:Q,logger:$,config:w,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??w.minRelevanceScore})},validateAndParse:(B)=>{let X=ba$.safeParse(B??{});return X.success?X.data:null}}}async function ja$(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(!wk(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 yy(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 Ae2(){return{priority:5,source:vO0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Ey}}}async function Qe2(A){let Q=await we2(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 yy(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 $e2(A){let Q=await we2(A),$=await XIA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",$)}async function XIA(A,Q,$,w){let B=new aJ(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 yy(A,Q,$,{minRelevanceScore:w.minRelevanceScore,autoMerge:w.autoMerge,mergeSimilarityThreshold:w.mergeSimilarityThreshold,targetVisibility:w.extractionVisibility});return{deleted:X.length,...Y}}async function we2(A){let Q=Ma$(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 Ma$(A){return A.context.entityService.getEntityTypes().filter(($)=>A.shouldProcessEntityType($))}var Ko=W.object({entityType:W.string(),content:W.string(),metadata:W.record(W.string(),W.unknown()).optional()}),ka$=Ko.extend({minRelevanceScore:W.number().optional()}),Oa$=W.object({contentA:Ko,contentB:Ko,minRelevanceScore:W.number().optional(),threshold:W.number().min(0).max(1).optional()}),d90=W.object({title:W.string(),content:W.string()}),fa$=W.object({existingTopics:W.array(d90),incomingTopic:d90,threshold:W.number().optional()}),xa$=W.object({existingTopics:W.array(d90).default([]),incomingTopic:d90.extend({relevanceScore:W.number().min(0).max(1).optional()}),threshold:W.number().optional()}),Ra$=W.object({entities:W.array(Ko).min(1),minRelevanceScore:W.number().optional()}),va$=W.object({existingTopics:W.array(d90).optional(),entities:W.array(Ko)}),Ca$=W.object({entities:W.array(Ko)});function Ho(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 Be2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function ha$(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function Ea$(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:ha$(Q)}]}}async function gy(A){let Q=await A.entityService.listEntities({entityType:Pw});await Promise.all(Q.map(($)=>A.entityService.deleteEntity({entityType:Pw,id:$.id})))}async function Ta$(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise(($)=>setTimeout($,100))}}function Xe2(A){let{context:Q,logger:$,config:w}=A,B=new $IA(Q,$),X=async(Y,Z,H="")=>{let K=Ho(Y,H);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await gy(Q);let Z=ka$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Ho(Z);return(await B.extractFromEntity(K,H)).map((G)=>Ea$(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await gy(Q);let Z=Oa$.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 aJ(Q.entityService,$),q=[];for(let F of U){let _=await D.createTopic(F);if(_)q.push(_)}let V=(await Promise.all(G.map(async(F)=>{let _=await D.findMergeCandidate({incoming:F,threshold:K,additionalCandidates:q});if(!_)return null;return{incomingTitle:F.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((F)=>F!==null),L=V.map((F)=>F.candidateTitle);return{topicsA:U.map(Be2),topicsB:G.map(Be2),matchingTitles:L,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await gy(Q);let Z=fa$.parse(Y),H=Z.threshold??w.mergeSimilarityThreshold,K=new aJ(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 gy(Q);let Z=xa$.parse(Y),H=new aJ(Q.entityService,$);for(let D of Z.existingTopics)await H.createTopic({title:D.title,content:D.content});await Ta$(Q);let K=Ho({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await yy([K],Q,$,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??w.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:Pw});return{...U,topicCount:G.length,topics:G.map(oLA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await gy(Q);let Z=va$.parse(Y),H=new aJ(Q.entityService,$);for(let D of Z.existingTopics??[])await H.createTopic(D);let K=Z.entities.map((D,q)=>Ho(D,`-rebuild-${q}`)),U=await XIA(K,Q,$,w),G=await Q.entityService.listEntities({entityType:Pw});return{...U,topicCount:G.length,topics:G.map(oLA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await gy(Q);let Z=Ra$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=new aJ(Q.entityService,$),U=[];for(let[D,q]of Z.entities.entries()){let V=Ho(q,`-sequential-${D}`),L=await B.extractFromEntity(V,H);for(let F of L)await K.createTopic({title:F.title,content:F.content});U.push({extractedTitles:L.map((F)=>F.title)})}let G=await Q.entityService.listEntities({entityType:Pw});return{totalTopics:G.length,perEntity:U,topics:G.map(Zo)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await gy(Q);let H=Ca$.parse(Y).entities.map((G,D)=>Ho(G,`-batch-${D}`)),K=await yy(H,Q,$,{minRelevanceScore:w.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:Pw});return{...K,topics:U.map(Zo)}})}var ya$=new sJ;async function Ye2({entity:A,config:Q}){let $=Yo.parse(A),w=ya$.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 YIA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:i8["ai.rizom.brain.topic"],validate:!1,buildRecord:Ye2}}var Ze2={name:"@brains/topics",version:"0.2.0-alpha.204",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 Sa$=new sJ,ma$=W.looseObject({status:W.unknown().optional()});class We2 extends c6{entityType=Pw;schema=Yo;adapter=Sa$;unregisterAtprotoProjection;sourceBatch=new BIA;constructor(A={}){super(Ey,Ze2,A,Pt2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:ft2,"merge-synthesis":xt2,"topic-list":Rt2,"topic-detail":vt2,"knowledge-map":mt2()}}getDataSources(){return[new sLA(this.logger.child("TopicsDataSource")),new eLA]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:dLA,targetType:Pw,job:{type:jt2,handler:et2({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 xC(A,Pw,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Ae2()},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(!wk($.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:$.id,entityType:$.entityType,contentHash:$.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:vO0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:kt2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Ey}})}}]}async onRegister(A){A.insights.register("topic-distribution",ut2()),ct2({context:A,pluginId:this.id}),pt2({context:A,pluginId:this.id}),Xe2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=D9.getInstance().register(YIA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(dLA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===Pw)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=ma$.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 Qe2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await $e2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function lO0(A={}){return new We2(A)}zA();v0();zA();var ZIA=W.enum(["linkedin"]),He2=W.enum(["linkedin"]),WIA=W.enum(["generating","draft","queued","published","failed"]),Ke2=W.enum(["generating","draft","queued","published","failed"]),Ue2=W.enum(["post","deck"]),ua$=W.enum(["post","deck"]),Ge2=W.object({id:W.string().min(1).describe("Document entity ID")}),ca$=W.object({id:W.string().min(1)}),tJ=W.object({title:W.string().describe("Short descriptive title (3-6 words) for file naming"),platform:ZIA.describe("Target platform"),status:WIA,coverImageId:W.string().optional().describe("Image entity ID for post image"),documents:W.array(Ge2).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:Ue2.optional().describe("Source entity type (post, deck)")}),De2=tJ.extend({platform:ZIA.optional(),status:WIA.optional()}),pa$=tJ.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()}),la$=W.object({title:W.string(),platform:He2,status:Ke2,publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),ia$=W.object({title:W.string(),platform:He2,status:Ke2,coverImageId:W.string().optional(),documents:W.array(ca$).optional(),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:ua$.optional()}),qx=U6.extend({entityType:W.literal("social-post"),metadata:la$}),iO0=qx.extend({frontmatter:ia$,body:W.string()}),da$=iO0.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 HIA extends zQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:qx,frontmatterSchema:tJ,supportsCoverImage:!0})}toMarkdown(A){let Q,$={};try{$=this.parseFrontMatter(A.content,tJ),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,De2),$=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,tJ)}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 aY=new HIA;zA();zA();v0();var na$=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()}),ra$=W.looseObject({entityType:W.string().optional(),query:na$.optional()});function qe2(A){let Q=MQ(A.content,tJ);return iO0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class dO0 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=ra$.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return qe2(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?qe2(w):null;return A.parse({post:B})}}v0();var ze2=W.object({accessToken:W.string().optional(),refreshToken:W.string().optional(),organizationId:W.string().optional(),apiVersion:W.string().regex(/^\d{6}$/).optional()}),KIA=W.object({linkedin:ze2.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();v0();Kw();GIA();import{jsxDEV as L7,Fragment as aa$}from"preact/jsx-dev-runtime";function oa$(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function sa$(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var rO0=({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(aa$,{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(C8,{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:sa$(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(eK,{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:oa$(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(Db,{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 ta$}from"preact/jsx-dev-runtime";function Je2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var oO0=({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(ta$,{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(SL,{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(eK,{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(Ub,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),I7(C8,{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)," ",Je2(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)," ",Je2(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 n90(A){return`social-media:${A}`}var ea$=W.union([W.boolean(),W.object({generate:W.boolean().optional(),prompt:W.string().optional()})]),DIA=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:ea$.optional().describe("Generic cover image generation request")}),At$=CU.extend({slug:W.string().optional()});class Sy extends SZ{constructor(A,Q){super(A,Q,{schema:DIA,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 F=await this.context.ai.generate({prompt:Z,templateName:n90($)});H=F.title,Z=F.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 F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)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(F.metadata),b=j.success?j.data.slug:Y,k=await this.context.ai.generate({prompt:`Create an engaging ${$} post to promote this ${X}:
8352
+ `)}async function yy(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 aJ(Q.entityService,$),U=w.topicMergeSynthesizer??new wIA(Q,$),G=await cO0(Q.entityService,void 0,Z),D=new Map,q=0,V=0,L=0;for(let _ of H){$.info(`Processing batch of ${_.length} entities`);let j=Pa$(_),b=pO0({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 m=await K.findMergeCandidate({incoming:R,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(m){let l=await U.synthesize({existingTopic:m.topic,incomingTopic:R}),a=await K.applySynthesizedMerge({existingId:m.topic.id,synthesized:{...l,title:m.title},visibility:Z});if(!a)throw Error(`Failed to merge topic: ${R.title}`);D.set(a.id,a),V++;continue}}let O=K.getTopicIdForTitle(R.title,Z);if(D.has(O)){L++;continue}let g=await K.createTopicOptimistic({title:R.title,content:R.content,visibility:Z});if(g.topic)D.set(g.topic.id,g.topic);if(g.created)q++;else L++}catch(O){$.error("Topic batch item failed",{title:R.title,error:sA(O)})}}catch(k){$.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:sA(k)})}}let F={created:q,merged:V,skipped:L,batches:H.length};if(q>0||V>0)await Q.messaging.send({type:Mt2,payload:F,broadcast:!0});return F}zA();v0();var ba$=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 BIA{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 et2(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 ja$({context:Q,logger:$,config:w,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??w.minRelevanceScore})},validateAndParse:(B)=>{let X=ba$.safeParse(B??{});return X.success?X.data:null}}}async function ja$(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(!wk(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 yy(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 Ae2(){return{priority:5,source:vO0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Ey}}}async function Qe2(A){let Q=await we2(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 yy(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 $e2(A){let Q=await we2(A),$=await XIA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",$)}async function XIA(A,Q,$,w){let B=new aJ(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 yy(A,Q,$,{minRelevanceScore:w.minRelevanceScore,autoMerge:w.autoMerge,mergeSimilarityThreshold:w.mergeSimilarityThreshold,targetVisibility:w.extractionVisibility});return{deleted:X.length,...Y}}async function we2(A){let Q=Ma$(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 Ma$(A){return A.context.entityService.getEntityTypes().filter(($)=>A.shouldProcessEntityType($))}var Ko=W.object({entityType:W.string(),content:W.string(),metadata:W.record(W.string(),W.unknown()).optional()}),ka$=Ko.extend({minRelevanceScore:W.number().optional()}),Oa$=W.object({contentA:Ko,contentB:Ko,minRelevanceScore:W.number().optional(),threshold:W.number().min(0).max(1).optional()}),d90=W.object({title:W.string(),content:W.string()}),fa$=W.object({existingTopics:W.array(d90),incomingTopic:d90,threshold:W.number().optional()}),xa$=W.object({existingTopics:W.array(d90).default([]),incomingTopic:d90.extend({relevanceScore:W.number().min(0).max(1).optional()}),threshold:W.number().optional()}),Ra$=W.object({entities:W.array(Ko).min(1),minRelevanceScore:W.number().optional()}),va$=W.object({existingTopics:W.array(d90).optional(),entities:W.array(Ko)}),Ca$=W.object({entities:W.array(Ko)});function Ho(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 Be2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function ha$(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function Ea$(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:ha$(Q)}]}}async function gy(A){let Q=await A.entityService.listEntities({entityType:Pw});await Promise.all(Q.map(($)=>A.entityService.deleteEntity({entityType:Pw,id:$.id})))}async function Ta$(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise(($)=>setTimeout($,100))}}function Xe2(A){let{context:Q,logger:$,config:w}=A,B=new $IA(Q,$),X=async(Y,Z,H="")=>{let K=Ho(Y,H);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await gy(Q);let Z=ka$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=Ho(Z);return(await B.extractFromEntity(K,H)).map((G)=>Ea$(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await gy(Q);let Z=Oa$.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 aJ(Q.entityService,$),q=[];for(let F of U){let _=await D.createTopic(F);if(_)q.push(_)}let V=(await Promise.all(G.map(async(F)=>{let _=await D.findMergeCandidate({incoming:F,threshold:K,additionalCandidates:q});if(!_)return null;return{incomingTitle:F.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((F)=>F!==null),L=V.map((F)=>F.candidateTitle);return{topicsA:U.map(Be2),topicsB:G.map(Be2),matchingTitles:L,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await gy(Q);let Z=fa$.parse(Y),H=Z.threshold??w.mergeSimilarityThreshold,K=new aJ(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 gy(Q);let Z=xa$.parse(Y),H=new aJ(Q.entityService,$);for(let D of Z.existingTopics)await H.createTopic({title:D.title,content:D.content});await Ta$(Q);let K=Ho({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await yy([K],Q,$,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??w.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:Pw});return{...U,topicCount:G.length,topics:G.map(oLA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await gy(Q);let Z=va$.parse(Y),H=new aJ(Q.entityService,$);for(let D of Z.existingTopics??[])await H.createTopic(D);let K=Z.entities.map((D,q)=>Ho(D,`-rebuild-${q}`)),U=await XIA(K,Q,$,w),G=await Q.entityService.listEntities({entityType:Pw});return{...U,topicCount:G.length,topics:G.map(oLA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await gy(Q);let Z=Ra$.parse(Y),H=Z.minRelevanceScore??w.minRelevanceScore,K=new aJ(Q.entityService,$),U=[];for(let[D,q]of Z.entities.entries()){let V=Ho(q,`-sequential-${D}`),L=await B.extractFromEntity(V,H);for(let F of L)await K.createTopic({title:F.title,content:F.content});U.push({extractedTitles:L.map((F)=>F.title)})}let G=await Q.entityService.listEntities({entityType:Pw});return{totalTopics:G.length,perEntity:U,topics:G.map(Zo)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await gy(Q);let H=Ca$.parse(Y).entities.map((G,D)=>Ho(G,`-batch-${D}`)),K=await yy(H,Q,$,{minRelevanceScore:w.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:Pw});return{...K,topics:U.map(Zo)}})}var ya$=new sJ;async function Ye2({entity:A,config:Q}){let $=Yo.parse(A),w=ya$.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 YIA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:i8["ai.rizom.brain.topic"],validate:!1,buildRecord:Ye2}}var Ze2={name:"@brains/topics",version:"0.2.0-alpha.206",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 Sa$=new sJ,ma$=W.looseObject({status:W.unknown().optional()});class We2 extends c6{entityType=Pw;schema=Yo;adapter=Sa$;unregisterAtprotoProjection;sourceBatch=new BIA;constructor(A={}){super(Ey,Ze2,A,Pt2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:ft2,"merge-synthesis":xt2,"topic-list":Rt2,"topic-detail":vt2,"knowledge-map":mt2()}}getDataSources(){return[new sLA(this.logger.child("TopicsDataSource")),new eLA]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:dLA,targetType:Pw,job:{type:jt2,handler:et2({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 xC(A,Pw,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Ae2()},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(!wk($.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:$.id,entityType:$.entityType,contentHash:$.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:vO0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:kt2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Ey}})}}]}async onRegister(A){A.insights.register("topic-distribution",ut2()),ct2({context:A,pluginId:this.id}),pt2({context:A,pluginId:this.id}),Xe2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=D9.getInstance().register(YIA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(dLA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===Pw)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=ma$.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 Qe2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await $e2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function lO0(A={}){return new We2(A)}zA();v0();zA();var ZIA=W.enum(["linkedin"]),He2=W.enum(["linkedin"]),WIA=W.enum(["generating","draft","queued","published","failed"]),Ke2=W.enum(["generating","draft","queued","published","failed"]),Ue2=W.enum(["post","deck"]),ua$=W.enum(["post","deck"]),Ge2=W.object({id:W.string().min(1).describe("Document entity ID")}),ca$=W.object({id:W.string().min(1)}),tJ=W.object({title:W.string().describe("Short descriptive title (3-6 words) for file naming"),platform:ZIA.describe("Target platform"),status:WIA,coverImageId:W.string().optional().describe("Image entity ID for post image"),documents:W.array(Ge2).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:Ue2.optional().describe("Source entity type (post, deck)")}),De2=tJ.extend({platform:ZIA.optional(),status:WIA.optional()}),pa$=tJ.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()}),la$=W.object({title:W.string(),platform:He2,status:Ke2,publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),ia$=W.object({title:W.string(),platform:He2,status:Ke2,coverImageId:W.string().optional(),documents:W.array(ca$).optional(),publishedAt:W.string().datetime().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:ua$.optional()}),qx=U6.extend({entityType:W.literal("social-post"),metadata:la$}),iO0=qx.extend({frontmatter:ia$,body:W.string()}),da$=iO0.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 HIA extends zQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:qx,frontmatterSchema:tJ,supportsCoverImage:!0})}toMarkdown(A){let Q,$={};try{$=this.parseFrontMatter(A.content,tJ),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,De2),$=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,tJ)}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 aY=new HIA;zA();zA();v0();var na$=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()}),ra$=W.looseObject({entityType:W.string().optional(),query:na$.optional()});function qe2(A){let Q=MQ(A.content,tJ);return iO0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class dO0 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=ra$.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return qe2(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?qe2(w):null;return A.parse({post:B})}}v0();var ze2=W.object({accessToken:W.string().optional(),refreshToken:W.string().optional(),organizationId:W.string().optional(),apiVersion:W.string().regex(/^\d{6}$/).optional()}),KIA=W.object({linkedin:ze2.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();v0();Kw();GIA();import{jsxDEV as L7,Fragment as aa$}from"preact/jsx-dev-runtime";function oa$(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function sa$(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var rO0=({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(aa$,{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(C8,{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:sa$(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(eK,{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:oa$(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(Db,{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 ta$}from"preact/jsx-dev-runtime";function Je2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var oO0=({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(ta$,{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(SL,{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(eK,{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(Ub,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),I7(C8,{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)," ",Je2(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)," ",Je2(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 n90(A){return`social-media:${A}`}var ea$=W.union([W.boolean(),W.object({generate:W.boolean().optional(),prompt:W.string().optional()})]),DIA=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:ea$.optional().describe("Generic cover image generation request")}),At$=CU.extend({slug:W.string().optional()});class Sy extends SZ{constructor(A,Q){super(A,Q,{schema:DIA,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 F=await this.context.ai.generate({prompt:Z,templateName:n90($)});H=F.title,Z=F.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 F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)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(F.metadata),b=j.success?j.data.slug:Y,k=await this.context.ai.generate({prompt:`Create an engaging ${$} post to promote this ${X}:
8353
8353
 
8354
8354
  Source: ${X}/${b}
8355
8355
 
8356
8356
  ${F.content}`,templateName:n90($)});H=k.title,Z=k.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 F=await this.context.ai.generate({prompt:B,templateName:n90($)});H=F.title,Z=F.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=aY.createPostContent(U,Z),q=aY.fromMarkdown(G).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let V=await v3({entityType:"social-post",title:H,deriveId:(F)=>`${$}-${O1(F)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),L=G;if(V!==H){q.title=V,q.slug=`${$}-${O1(V)}`;let F={...U,title:V};L=aY.createPostContent(F,Z)}return{id:q.slug,content:L,metadata:q,title:V,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}}}v0();var Ve2=200,Fe2="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function r90(A){if(A.length<=Ve2)return A;return`${A.slice(0,Ve2)}\u2026 (truncated, ${A.length} bytes)`}var Qt$=W.looseObject({sub:W.string()}),$t$=W.looseObject({id:W.string()}),wt$=W.looseObject({value:W.looseObject({asset:W.string(),uploadMechanism:W.looseObject({[Fe2]:W.looseObject({uploadUrl:W.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[Fe2].uploadUrl,assetUrn:A.value.asset})),Bt$=W.looseObject({value:W.looseObject({uploadUrl:W.url(),document:W.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function Xt$(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function Yt$(A){let Q=wt$.safeParse(A);return Q.success?Q.data:null}function Zt$(A){let Q=Bt$.safeParse(A);return Q.success?Q.data:null}var Wt$="202604";class qIA{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:[Xt$(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=r90(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??Wt$,"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=r90(await $.text());return this.logger.warn("LinkedIn image upload registration failed",{status:$.status,error:Z}),null}let w=Yt$(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=r90(await $.text());throw Error(`LinkedIn document upload initialization failed: ${$.status} - ${X}`)}let w=Zt$(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=r90(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=Qt$.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 $=r90(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${$}`)}let Q=$t$.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function zIA(A,Q,$={}){return new qIA(A,Q,$)}v0();aw();GIA();var Ht$=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),Kt$=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}),Le2=W.enum(["linkedin"]),Ie2=W.enum(["generating","draft","queued","published","failed"]),Ut$=W.enum(["post","deck"]),Gt$=W.object({id:W.string().min(1)}),Dt$=W.object({title:W.string(),platform:Le2,status:Ie2,coverImageId:W.string().optional(),documents:W.array(Gt$).optional(),publishedAt:W.string().optional(),platformPostId:W.string().optional(),sourceEntityId:W.string().optional(),sourceEntityType:Ut$.optional()}),qt$=W.object({title:W.string(),platform:Le2,status:Ie2,publishedAt:W.string().optional(),platformPostId:W.string().optional(),slug:W.string(),error:W.string().optional()}),Ne2=W.object({id:W.string(),entityType:W.literal("social-post"),content:W.string(),created:W.string(),updated:W.string(),visibility:Kt$,metadata:qt$,contentHash:W.string(),frontmatter:Dt$,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()}),zt$=W.object({posts:W.array(Ne2),totalCount:W.number().optional(),pagination:Ht$.nullable(),baseUrl:W.string().optional()}),Jt$=W.object({post:Ne2});function _e2(){return{linkedin:nO0,"social-post-list":W2({name:"social-post-list",description:"Social post list page template",schema:zt$,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:rO0}}),"social-post-detail":W2({name:"social-post-detail",description:"Individual social post template",schema:Jt$,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:oO0}})}}v0();var Vt$=W.object({prompt:W.string().optional(),content:W.string().optional(),platform:W.enum(["linkedin"]).default("linkedin")}),Ft$=W.object({prompt:W.string().optional(),content:W.string().optional(),title:W.string().optional(),platform:W.enum(["linkedin"]).optional()});function Pe2(A){A.eval.registerHandler("generation",async(Q)=>{let $=Vt$.parse(Q),w=$.content?`Create an engaging LinkedIn post to share this content:
8357
8357
 
8358
- ${$.content}`:$.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${$.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let $=Ft$.parse(Q),w=[],B=yW.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 Sy(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 o90{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,tJ),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),V=new Date().toISOString(),L=q.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...L&&{platformPostId:L}},_=aY.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:L}}}),await this.reportSuccess(Q,$,q.id),this.logger.info(`Post published successfully: ${$}`,{platform:X,platformPostId:L})}catch(G){let D=G instanceof Error?G.message:String(G),q={...Z.metadata,status:"failed"},V=aY.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,$,D),this.logger.error(`Post publish failed: ${$}`,{platform:X,error:D})}}catch(w){let B=sA(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 be2(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 je2(A,Q,$){let w=new o90({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 Me2(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=sA(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 ke2(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:`${aY.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=sA(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 Oe2(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:`${aY.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=sA(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 fe2({entity:A,config:Q}){let $=qx.parse(A),w=aY.parsePostFrontmatter($),B=aY.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 JIA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:i8["ai.rizom.brain.socialPost"],validate:!1,buildRecord:fe2}}var xe2={name:"@brains/social-media",version:"0.2.0-alpha.204",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 VIA extends c6{entityType=aY.entityType;schema=qx;adapter=aY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",xe2,A,KIA)}createGenerationHandler(A){return new Sy(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return _e2()}getDataSources(){return[new dO0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),be2(A,this.providers,this.logger),je2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Me2(A,this.logger),ke2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Oe2(A,this.logger),Pe2(A),this.unregisterAtprotoProjection=D9.getInstance().register(JIA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=zIA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function s90(A={}){return new VIA(A)}v0();var It$=W.enum(["draft","queued","published","failed"]),Re2=W.object({status:It$.default("draft"),queueOrder:W.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:W.string().datetime().optional()});class FIA{name="internal";async publish(A,Q){return{id:"internal"}}}var vb={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},tY={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"},zx={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"},ve2={REGISTER:"publish-assets:register"};v0();var Nt$=W.enum(["provider"]),Ce2=W.object({executionMode:Nt$.optional(),publishResultIdField:W.string().min(1).optional(),publishTimestampField:W.string().min(1).optional(),enabled:W.boolean().optional()}).strict();var _t$=W.object({skipIfDraftExists:W.boolean().optional(),minSourceEntities:W.number().optional(),maxUnpublishedDrafts:W.number().optional(),sourceEntityType:W.string().optional()}),he2=W.object({entitySchedules:W.record(W.string(),W.string()).optional(),generationSchedules:W.record(W.string(),W.string()).optional(),generationConditions:W.record(W.string(),_t$).optional()});class WI{static instance=null;queues=new Map;static getInstance(){return WI.instance??=new WI,WI.instance}static resetInstance(){WI.instance=null}static createFresh(){return new WI}constructor(){}async add(A,Q,$=vb){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 HI{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new FIA;static getInstance(){return HI.instance??=new HI,HI.instance}static resetInstance(){HI.instance=null}static createFresh(){return new HI}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 Ee2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await Pt$(A,Q)}async function Pt$(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:tY.FAILED,payload:w,sender:"publish-service",broadcast:!0});Q.onFailed?.(w);return}LIA(A.entityType,A.entityId,$.result,Q)}catch($){let w=sA($);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 LIA(A,Q,$,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send({type:tY.COMPLETED,payload:{entityType:A,entityId:Q,result:$},sender:"publish-service",broadcast:!0});w.onPublish?.({entityType:A,entityId:Q,result:$})}function Te2(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:tY.FAILED,payload:X,sender:"publish-service",broadcast:!0});w.onFailed?.(X)}async function ye2(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:zx.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:zx.EXECUTE,payload:w,sender:"content-pipeline"});Q.onGenerate?.(w)}function ge2(A,Q,$){if($)$.send({type:zx.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function Se2(A,Q,$){if($)$.send({type:zx.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var bt$=1000;class IIA{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(bt$,()=>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 Ee2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class NIA{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 ye2(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 KI{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return KI.instance??=new KI(A),KI.instance}static async resetInstance(){let A=KI.instance;if(KI.instance=null,A)await A.stop()}static createFresh(A){return new KI(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new IIA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new NIA({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,$){LIA(A,Q,$,this.publishDeps)}failPublish(A,Q,$){Te2(A,Q,$,this.publishDeps)}completeGeneration(A,Q){ge2(A,Q,this.config.messageBus)}failGeneration(A,Q){Se2(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}" - ${sA(w)}`,{cause:w})}}}class UI{static instance=null;retries=new Map;static getInstance(){return UI.instance??=new UI,UI.instance}static resetInstance(){UI.instance=null}static createFresh(){return new UI}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}}}fAA();v0();var me2=W.union([W.string().min(1),W.object({location:W.enum(["metadata","frontmatter"]),field:W.string().min(1)})]),sO0=W.object({entityType:W.string().min(1),attachmentType:W.string().min(1),mediaEntityType:W.enum(["image","document"]),targetEntityField:me2.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 _IA(A){return`${A.entityType}:${A.attachmentType}`}class GI{static instance=null;definitions=new Map;static getInstance(){return GI.instance??=new GI,GI.instance}static resetInstance(){GI.instance=null}static createFresh(){return new GI}constructor(){}register(A){let Q=sO0.parse(A),$=_IA(Q);return this.definitions.set($,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(_IA({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(_IA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}u4();p2();class aO0{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 PIA(A.metadata[Q]);if(Q.location==="metadata")return PIA(A.metadata[Q.field]);let{frontmatter:$}=t8(A.content);return PIA($[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 PIA(A){return typeof A==="string"?A.length>0:A!==void 0}zA();v0();var Mt$=W.object({id:W.string().min(1)});async function ce2(A,Q){let{bodyContent:$,coverImageId:w,documents:B,sourceEntityType:X,sourceEntityId:Y}=kt$(Q.content),Z=w?await xt$(A,w):void 0,H;if(B&&B.length>0){let U=await Rt$(A,B);if(U.length>0)H=U}H??=await ft$(A,X,Y);let K={bodyContent:$};if(Z)K.imageData=Z;if(H&&H.length>0)K.documentData=H;return K}function kt$(A){try{let Q=MQ(A,W.record(W.string(),W.unknown())),$=Q.metadata.coverImageId,w=typeof $==="string"?$:void 0,B=Ot$(Q.metadata.documents),X=ue2(Q.metadata.sourceEntityType),Y=ue2(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 Ot$(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let $=Mt$.safeParse(Q);return $.success?[$.data]:[]})}function ue2(A){return typeof A==="string"&&A.length>0?A:void 0}async function ft$(A,Q,$){if(!Q||!$)return;let w=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:$,attachmentType:"carousel"});return w?[w]:void 0}async function xt$(A,Q){let $=await A.entityService.getEntity({entityType:"image",id:Q});if(!$?.content)return;let w=pe2($.content);if(!w?.mimeType.startsWith("image/"))return;return{data:w.data,mimeType:w.mimeType}}async function Rt$(A,Q){return(await Promise.all(Q.map((w)=>vt$(A,w)))).filter((w)=>w!==void 0)}async function vt$(A,Q){let $=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!$?.content)return;let w=pe2($.content);if(w?.mimeType!=="application/pdf")return;return{type:"document",data:w.data,mimeType:"application/pdf",filename:Ct$($,Q.id)}}function pe2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function Ct$(A,Q){let $=A.metadata.filename;return typeof $==="string"&&$.length>0?$:`${Q}.pdf`}u4();var ht$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function bIA(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,...Et$($.id,w.publishResultIdField)},H={...Q,content:le2(Q.content,Y,$.id,w.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function le2(A,Q,$,w,B="publishedAt"){if(!ht$.test(A))return A;let X=EX(EX(A,"status","published"),B,Q);if(!$||!w)return X;return EX(X,w,$)}function Et$(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Uo{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 ce2(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 bIA(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();v0();var jIA=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)")}),MIA=W.object({position:W.number(),entityType:W.string(),entityId:W.string(),queuedAt:W.string()}),Tt$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({queue:W.array(MIA).optional(),entityType:W.string().optional(),entityId:W.string().optional(),position:W.number().optional()}).optional()}),yt$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),kIA=W.union([Tt$,yt$]);function tO0(A,Q,$,w){let B=w??$;return{...e8(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",jIA,async(Y,Z)=>{let{action:H,entityType:K,entityId:U,position:G}=Y;switch(H){case"list":return gt$($,K);case"add":return St$(A,B,K,U,Z);case"remove":return mt$(A,B,K,U,Z);case"reorder":return ut$(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${H}`}}},{sideEffects:"writes"}),outputSchema:kIA}}async function gt$(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 St$(A,Q,$,w,B){let X=OIA("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 mt$(A,Q,$,w,B){let X=OIA("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 ut$(A,Q,$,w,B,X){let Y=OIA("reorder",$,w);if(!Y.success)return Y.error;let Z=ct$(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 OIA(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 ct$(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}}v0();import{createHash as pt$}from"crypto";var fIA=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()}),lt$=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()}),it$=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()}),dt$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),nt$=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()}),xIA=W.union([it$,dt$,nt$]),rt$=900000;function Go(A,Q,$,w){let B=w??new Uo({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:fIA.shape,outputSchema:xIA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=lt$.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((L)=>`${L.path.join(".")}: ${L.message}`).join(", ")}`};let K=H.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(L){return{success:!1,error:L instanceof Error?L.message:String(L)}}let q=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:V}=q;if(K.confirmed){let L=st$(X,K,V);if(L!==null)return L;let F;try{F=await B.publish({entityType:U,id:V.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in F)return{success:!1,error:F.error};let{entity:_,result:j}=F;return{success:!0,data:{entityType:U,entityId:_.id,platformId:j.id,url:j.url},message:`Published ${U}:${_.id}`}}return ot$(X,K,V)}}}function ot$(A,Q,$){let w=new Date(Date.now()+rt$).toISOString(),B=ie2(A,$,w),X=at$($);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 st$(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!==ie2(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 ie2(A,Q,$){return pt$("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update($).digest("hex")}function at$(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();v0();var RIA=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")}),vIA=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 eO0(A,Q,$,w){return{...e8(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",RIA,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:vIA}}zA();u4();v0();var tt$="content-pipeline.queue.v1",CIA=1024,et$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,Ae$=W.object({interfaceType:W.string().optional(),userId:W.string().optional(),userPermissionLevel:W.enum(["public","trusted","anchor"]).optional(),authorization:W.enum(["user","system"]).optional()}),Qe$=W.object({entityType:W.string(),entityId:W.string(),rank:W.number().int().positive(),queuedAt:W.string().datetime(),contentHashAtEnqueue:W.string(),authContext:Ae$,revision:W.number().int().positive()});class hIA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:tt$,schema:Qe$})}async add(A,Q,$=vb){return this.enqueue(A,Q,$)}async enqueue(A,Q,$=vb){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(kz(A,Q))){let Y=(await this.queueManager.list(A)).find((H)=>H.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set(kz(A,Q),{entityType:A,entityId:Q,rank:B.position*CIA,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(kz(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(kz(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(kz(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(kz(H,U.id),U)}let $=await this.listStored();for(let H of $)if(!Q.has(kz(H.entityType,H.entityId)))await this.store.delete(kz(H.entityType,H.entityId));let w=(await this.listStored()).filter((H)=>Q.has(kz(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)=>kz(G.entityType,G.entityId)===H))continue;let U=(B.get(K.entityType)??0)+CIA;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:{...vb},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(kz(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*CIA;if(w.rank===B)continue;await this.store.set(kz(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=et$.test(A.content)?EX(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 kz(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function de2(A,Q){$e$(A,Q),we$(A,Q),Be$(A,Q),Xe$(A,Q)}function $e$(A,Q){A.messaging.subscribe(tY.REGISTER,async($)=>Ye$(Q,$.payload)),A.messaging.subscribe(tY.QUEUE,async($)=>Ke$(A,Q,$.payload)),A.messaging.subscribe(tY.DIRECT,async($)=>Ue$(A,Q,$.payload)),A.messaging.subscribe(tY.REMOVE,async($)=>Ge$(Q,$.payload)),A.messaging.subscribe(tY.REORDER,async($)=>De$(Q,$.payload)),A.messaging.subscribe(tY.LIST,async($)=>qe$(A,Q,$.payload)),A.messaging.subscribe(tY.REPORT_SUCCESS,async($)=>ze$(Q,$.payload)),A.messaging.subscribe(tY.REPORT_FAILURE,async($)=>Je$(Q,$.payload)),A.messaging.subscribe(tY.COMPLETED,async($)=>{return await Q.publicationQueueService.complete($.payload.entityType,$.payload.entityId),{success:!0}}),A.messaging.subscribe(tY.FAILED,async($)=>{return await Q.publicationQueueService.fail($.payload.entityType,$.payload.entityId,$.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function we$(A,Q){A.messaging.subscribe(zx.REPORT_SUCCESS,async($)=>Ve$(Q,$.payload)),A.messaging.subscribe(zx.REPORT_FAILURE,async($)=>Fe$(Q,$.payload)),Q.logger.debug("Subscribed to generation messages")}function Be$(A,Q){A.messaging.subscribe(ve2.REGISTER,async($)=>Ze$(Q,$.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Xe$(A,Q){let $=async(w)=>We$(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 Ye$(A,Q){let{entityType:$,provider:w,config:B}=Q;try{let X=B?Ce2.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=sA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Ze$(A,Q){let $=sO0.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 We$(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(!He$(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:sA(w)}),{success:!1}}}function He$(A){if(!A)return!1;let Q=Re2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Ke$(A,Q,$){let{entityType:w,entityId:B}=$;try{let X=$.authContext??vb;A.permissions.assertEntityActionAllowed(w,"publish",X);let Y=await Q.publicationQueueService.enqueue(w,B,X);return await A.messaging.send({type:tY.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=sA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Ue$(A,Q,$){let{entityType:w,entityId:B}=$,X=$.authContext??vb;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=sA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function Ge$(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=sA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function De$(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=sA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function qe$(A,Q,$){let{entityType:w}=$;try{let B=await Q.queueManager.list(w);return await A.messaging.send({type:tY.LIST_RESPONSE,payload:{entityType:w,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=sA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function ze$(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 Je$(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 Ve$(A,Q){let{entityType:$,entityId:w}=Q;return A.scheduler.completeGeneration($,w),A.logger.info("Generation completed",{entityType:$,entityId:w}),{success:!0}}async function Fe$(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:sA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${sA(B)}`}}}function re2(A){let{context:Q,config:$,queueManager:w,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=Le$(Q);return KI.createFresh({queueManager:w,providerRegistry:B,retryTracker:X,logger:Z,backend:new Xh({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 Le$(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:()=>{}}}v0();v0();var Ie$=W.enum(["draft","queued","published","failed"]),Ne$=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()}),_e$=W.object({id:W.string(),label:W.string(),target:W.string(),status:W.enum(["pending","processing"])}),Pe$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),error:W.string(),retryCount:W.number().int().nonnegative()}),be$=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(Ne$),generating:W.array(_e$),failures:W.array(Pe$),publishableEntityTypes:W.array(W.string())}),je$=W.object({sourceEntityType:W.string(),sourceEntityId:W.string(),attachmentType:W.string().optional()});async function Af0(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=Ie$.safeParse(D.metadata.status);if(!q.success)continue;Y[q.data]+=1;let V=D.metadata.scheduledFor,L=D.metadata.error;X.set(oe2(U,D.id),{entityId:D.id,entityType:U,title:ke$(D.id,D.metadata),status:q.data,...typeof V==="string"?{scheduledFor:V}:{},...typeof L==="string"?{error:L}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await $.list(U)){let q=X.get(oe2(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 Me$(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,be$.parse({summary:Y,queue:Z,generating:H,failures:K,publishableEntityTypes:B})}async function Me$(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=je$.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 oe2(A,Q){return`${A}\x00${Q}`}function ke$(A,Q){for(let $ of["title","subject","slug"]){let w=Q[$];if(typeof w==="string"&&w.length>0)return w}return A}async function se2(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 Af0(A,$.providerRegistry,$.queueManager,$.retryTracker),...$.managementUrl?{managementUrl:$.managementUrl}:{}}),digestProvider:fe$}})}var Oe$=W.object({summary:W.object({draft:W.number(),queued:W.number(),generating:W.number(),published:W.number(),failed:W.number(),needsOperator:W.number()})});function fe$(A){let{summary:Q}=Oe$.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();v0();var xe$=W.object({workspaceUrl:W.string()}),Re$=W.object({confirmed:W.literal(!0),confirmationToken:W.string().min(1),contentHash:W.string().min(1),expiresAt:W.string().datetime()}),ve$=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:Re$.optional()})]);async function ae2(A,Q,$){let w=Go(A,Q,$.providerRegistry,$.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",priority:40,entityTypes:$.providerRegistry.getRegisteredTypes(),dataProvider:()=>Af0(A,$.providerRegistry,$.queueManager,$.retryTracker),actionHandler:async(Z,H)=>{let K=ve$.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return Ce$(A,$,w,K.data,H)}},X=await A.messaging.send({type:h_,payload:B});if(!("success"in X)||!X.success)return;let Y=xe$.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function Ce$(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 te2={name:"@brains/content-pipeline",version:"0.2.0-alpha.204",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 EIA extends d6{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",te2,A,he2)}async onRegister(A){this.pluginContext=A,this.queueManager=WI.createFresh(),this.publicationQueueService=new hIA(A,this.queueManager),this.providerRegistry=HI.createFresh(),this.retryTracker=UI.createFresh(),this.publishAssetRegistry=GI.createFresh(),this.publishAssetPreflight=new aO0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Uo({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=re2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),de2(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 ae2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await se2(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[tO0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),Go(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),eO0(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(),WI.resetInstance(),HI.resetInstance(),UI.resetInstance(),GI.resetInstance()}}function TIA(A={}){return new EIA(A)}zA();v0();var ee2=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")}),yIA=W.object({cloudflare:ee2.optional()});zA();v0();var Ee$=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 Te$(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 A0Q(A,Q,$){let w=[];if(!$)return w;return w.push(e8(A,"query",`Query website analytics from Cloudflare.
8358
+ ${$.content}`:$.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:w,templateName:`social-media:${$.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let $=Ft$.parse(Q),w=[],B=yW.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 Sy(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 o90{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,tJ),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),V=new Date().toISOString(),L=q.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...L&&{platformPostId:L}},_=aY.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:L}}}),await this.reportSuccess(Q,$,q.id),this.logger.info(`Post published successfully: ${$}`,{platform:X,platformPostId:L})}catch(G){let D=G instanceof Error?G.message:String(G),q={...Z.metadata,status:"failed"},V=aY.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,$,D),this.logger.error(`Post publish failed: ${$}`,{platform:X,error:D})}}catch(w){let B=sA(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 be2(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 je2(A,Q,$){let w=new o90({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 Me2(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=sA(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 ke2(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:`${aY.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=sA(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 Oe2(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:`${aY.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=sA(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 fe2({entity:A,config:Q}){let $=qx.parse(A),w=aY.parsePostFrontmatter($),B=aY.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 JIA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:i8["ai.rizom.brain.socialPost"],validate:!1,buildRecord:fe2}}var xe2={name:"@brains/social-media",version:"0.2.0-alpha.206",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 VIA extends c6{entityType=aY.entityType;schema=qx;adapter=aY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",xe2,A,KIA)}createGenerationHandler(A){return new Sy(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return _e2()}getDataSources(){return[new dO0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),be2(A,this.providers,this.logger),je2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)Me2(A,this.logger),ke2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Oe2(A,this.logger),Pe2(A),this.unregisterAtprotoProjection=D9.getInstance().register(JIA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=zIA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function s90(A={}){return new VIA(A)}v0();var It$=W.enum(["draft","queued","published","failed"]),Re2=W.object({status:It$.default("draft"),queueOrder:W.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:W.string().datetime().optional()});class FIA{name="internal";async publish(A,Q){return{id:"internal"}}}var vb={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},tY={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"},zx={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"},ve2={REGISTER:"publish-assets:register"};v0();var Nt$=W.enum(["provider"]),Ce2=W.object({executionMode:Nt$.optional(),publishResultIdField:W.string().min(1).optional(),publishTimestampField:W.string().min(1).optional(),enabled:W.boolean().optional()}).strict();var _t$=W.object({skipIfDraftExists:W.boolean().optional(),minSourceEntities:W.number().optional(),maxUnpublishedDrafts:W.number().optional(),sourceEntityType:W.string().optional()}),he2=W.object({entitySchedules:W.record(W.string(),W.string()).optional(),generationSchedules:W.record(W.string(),W.string()).optional(),generationConditions:W.record(W.string(),_t$).optional()});class WI{static instance=null;queues=new Map;static getInstance(){return WI.instance??=new WI,WI.instance}static resetInstance(){WI.instance=null}static createFresh(){return new WI}constructor(){}async add(A,Q,$=vb){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 HI{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new FIA;static getInstance(){return HI.instance??=new HI,HI.instance}static resetInstance(){HI.instance=null}static createFresh(){return new HI}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 Ee2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await Pt$(A,Q)}async function Pt$(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:tY.FAILED,payload:w,sender:"publish-service",broadcast:!0});Q.onFailed?.(w);return}LIA(A.entityType,A.entityId,$.result,Q)}catch($){let w=sA($);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 LIA(A,Q,$,w){if(w.retryTracker.clearRetries(Q),w.messageBus)w.messageBus.send({type:tY.COMPLETED,payload:{entityType:A,entityId:Q,result:$},sender:"publish-service",broadcast:!0});w.onPublish?.({entityType:A,entityId:Q,result:$})}function Te2(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:tY.FAILED,payload:X,sender:"publish-service",broadcast:!0});w.onFailed?.(X)}async function ye2(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:zx.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:zx.EXECUTE,payload:w,sender:"content-pipeline"});Q.onGenerate?.(w)}function ge2(A,Q,$){if($)$.send({type:zx.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function Se2(A,Q,$){if($)$.send({type:zx.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var bt$=1000;class IIA{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(bt$,()=>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 Ee2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class NIA{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 ye2(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 KI{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return KI.instance??=new KI(A),KI.instance}static async resetInstance(){let A=KI.instance;if(KI.instance=null,A)await A.stop()}static createFresh(A){return new KI(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new IIA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new NIA({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,$){LIA(A,Q,$,this.publishDeps)}failPublish(A,Q,$){Te2(A,Q,$,this.publishDeps)}completeGeneration(A,Q){ge2(A,Q,this.config.messageBus)}failGeneration(A,Q){Se2(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}" - ${sA(w)}`,{cause:w})}}}class UI{static instance=null;retries=new Map;static getInstance(){return UI.instance??=new UI,UI.instance}static resetInstance(){UI.instance=null}static createFresh(){return new UI}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}}}fAA();v0();var me2=W.union([W.string().min(1),W.object({location:W.enum(["metadata","frontmatter"]),field:W.string().min(1)})]),sO0=W.object({entityType:W.string().min(1),attachmentType:W.string().min(1),mediaEntityType:W.enum(["image","document"]),targetEntityField:me2.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 _IA(A){return`${A.entityType}:${A.attachmentType}`}class GI{static instance=null;definitions=new Map;static getInstance(){return GI.instance??=new GI,GI.instance}static resetInstance(){GI.instance=null}static createFresh(){return new GI}constructor(){}register(A){let Q=sO0.parse(A),$=_IA(Q);return this.definitions.set($,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(_IA({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(_IA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}u4();p2();class aO0{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 PIA(A.metadata[Q]);if(Q.location==="metadata")return PIA(A.metadata[Q.field]);let{frontmatter:$}=t8(A.content);return PIA($[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 PIA(A){return typeof A==="string"?A.length>0:A!==void 0}zA();v0();var Mt$=W.object({id:W.string().min(1)});async function ce2(A,Q){let{bodyContent:$,coverImageId:w,documents:B,sourceEntityType:X,sourceEntityId:Y}=kt$(Q.content),Z=w?await xt$(A,w):void 0,H;if(B&&B.length>0){let U=await Rt$(A,B);if(U.length>0)H=U}H??=await ft$(A,X,Y);let K={bodyContent:$};if(Z)K.imageData=Z;if(H&&H.length>0)K.documentData=H;return K}function kt$(A){try{let Q=MQ(A,W.record(W.string(),W.unknown())),$=Q.metadata.coverImageId,w=typeof $==="string"?$:void 0,B=Ot$(Q.metadata.documents),X=ue2(Q.metadata.sourceEntityType),Y=ue2(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 Ot$(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let $=Mt$.safeParse(Q);return $.success?[$.data]:[]})}function ue2(A){return typeof A==="string"&&A.length>0?A:void 0}async function ft$(A,Q,$){if(!Q||!$)return;let w=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:$,attachmentType:"carousel"});return w?[w]:void 0}async function xt$(A,Q){let $=await A.entityService.getEntity({entityType:"image",id:Q});if(!$?.content)return;let w=pe2($.content);if(!w?.mimeType.startsWith("image/"))return;return{data:w.data,mimeType:w.mimeType}}async function Rt$(A,Q){return(await Promise.all(Q.map((w)=>vt$(A,w)))).filter((w)=>w!==void 0)}async function vt$(A,Q){let $=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!$?.content)return;let w=pe2($.content);if(w?.mimeType!=="application/pdf")return;return{type:"document",data:w.data,mimeType:"application/pdf",filename:Ct$($,Q.id)}}function pe2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function Ct$(A,Q){let $=A.metadata.filename;return typeof $==="string"&&$.length>0?$:`${Q}.pdf`}u4();var ht$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function bIA(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,...Et$($.id,w.publishResultIdField)},H={...Q,content:le2(Q.content,Y,$.id,w.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function le2(A,Q,$,w,B="publishedAt"){if(!ht$.test(A))return A;let X=EX(EX(A,"status","published"),B,Q);if(!$||!w)return X;return EX(X,w,$)}function Et$(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class Uo{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 ce2(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 bIA(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();v0();var jIA=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)")}),MIA=W.object({position:W.number(),entityType:W.string(),entityId:W.string(),queuedAt:W.string()}),Tt$=W.object({success:W.literal(!0),message:W.string().optional(),data:W.object({queue:W.array(MIA).optional(),entityType:W.string().optional(),entityId:W.string().optional(),position:W.number().optional()}).optional()}),yt$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),kIA=W.union([Tt$,yt$]);function tO0(A,Q,$,w){let B=w??$;return{...e8(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",jIA,async(Y,Z)=>{let{action:H,entityType:K,entityId:U,position:G}=Y;switch(H){case"list":return gt$($,K);case"add":return St$(A,B,K,U,Z);case"remove":return mt$(A,B,K,U,Z);case"reorder":return ut$(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${H}`}}},{sideEffects:"writes"}),outputSchema:kIA}}async function gt$(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 St$(A,Q,$,w,B){let X=OIA("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 mt$(A,Q,$,w,B){let X=OIA("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 ut$(A,Q,$,w,B,X){let Y=OIA("reorder",$,w);if(!Y.success)return Y.error;let Z=ct$(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 OIA(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 ct$(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}}v0();import{createHash as pt$}from"crypto";var fIA=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()}),lt$=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()}),it$=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()}),dt$=W.object({success:W.literal(!1),error:W.string(),code:W.string().optional()}),nt$=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()}),xIA=W.union([it$,dt$,nt$]),rt$=900000;function Go(A,Q,$,w){let B=w??new Uo({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:fIA.shape,outputSchema:xIA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=lt$.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((L)=>`${L.path.join(".")}: ${L.message}`).join(", ")}`};let K=H.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(L){return{success:!1,error:L instanceof Error?L.message:String(L)}}let q=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in q)return{success:!1,error:q.error};let{entity:V}=q;if(K.confirmed){let L=st$(X,K,V);if(L!==null)return L;let F;try{F=await B.publish({entityType:U,id:V.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in F)return{success:!1,error:F.error};let{entity:_,result:j}=F;return{success:!0,data:{entityType:U,entityId:_.id,platformId:j.id,url:j.url},message:`Published ${U}:${_.id}`}}return ot$(X,K,V)}}}function ot$(A,Q,$){let w=new Date(Date.now()+rt$).toISOString(),B=ie2(A,$,w),X=at$($);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 st$(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!==ie2(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 ie2(A,Q,$){return pt$("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update($).digest("hex")}function at$(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();v0();var RIA=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")}),vIA=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 eO0(A,Q,$,w){return{...e8(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",RIA,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:vIA}}zA();u4();v0();var tt$="content-pipeline.queue.v1",CIA=1024,et$=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,Ae$=W.object({interfaceType:W.string().optional(),userId:W.string().optional(),userPermissionLevel:W.enum(["public","trusted","anchor"]).optional(),authorization:W.enum(["user","system"]).optional()}),Qe$=W.object({entityType:W.string(),entityId:W.string(),rank:W.number().int().positive(),queuedAt:W.string().datetime(),contentHashAtEnqueue:W.string(),authContext:Ae$,revision:W.number().int().positive()});class hIA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:tt$,schema:Qe$})}async add(A,Q,$=vb){return this.enqueue(A,Q,$)}async enqueue(A,Q,$=vb){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(kz(A,Q))){let Y=(await this.queueManager.list(A)).find((H)=>H.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set(kz(A,Q),{entityType:A,entityId:Q,rank:B.position*CIA,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(kz(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(kz(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(kz(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(kz(H,U.id),U)}let $=await this.listStored();for(let H of $)if(!Q.has(kz(H.entityType,H.entityId)))await this.store.delete(kz(H.entityType,H.entityId));let w=(await this.listStored()).filter((H)=>Q.has(kz(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)=>kz(G.entityType,G.entityId)===H))continue;let U=(B.get(K.entityType)??0)+CIA;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:{...vb},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(kz(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*CIA;if(w.rank===B)continue;await this.store.set(kz(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=et$.test(A.content)?EX(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 kz(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function de2(A,Q){$e$(A,Q),we$(A,Q),Be$(A,Q),Xe$(A,Q)}function $e$(A,Q){A.messaging.subscribe(tY.REGISTER,async($)=>Ye$(Q,$.payload)),A.messaging.subscribe(tY.QUEUE,async($)=>Ke$(A,Q,$.payload)),A.messaging.subscribe(tY.DIRECT,async($)=>Ue$(A,Q,$.payload)),A.messaging.subscribe(tY.REMOVE,async($)=>Ge$(Q,$.payload)),A.messaging.subscribe(tY.REORDER,async($)=>De$(Q,$.payload)),A.messaging.subscribe(tY.LIST,async($)=>qe$(A,Q,$.payload)),A.messaging.subscribe(tY.REPORT_SUCCESS,async($)=>ze$(Q,$.payload)),A.messaging.subscribe(tY.REPORT_FAILURE,async($)=>Je$(Q,$.payload)),A.messaging.subscribe(tY.COMPLETED,async($)=>{return await Q.publicationQueueService.complete($.payload.entityType,$.payload.entityId),{success:!0}}),A.messaging.subscribe(tY.FAILED,async($)=>{return await Q.publicationQueueService.fail($.payload.entityType,$.payload.entityId,$.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function we$(A,Q){A.messaging.subscribe(zx.REPORT_SUCCESS,async($)=>Ve$(Q,$.payload)),A.messaging.subscribe(zx.REPORT_FAILURE,async($)=>Fe$(Q,$.payload)),Q.logger.debug("Subscribed to generation messages")}function Be$(A,Q){A.messaging.subscribe(ve2.REGISTER,async($)=>Ze$(Q,$.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Xe$(A,Q){let $=async(w)=>We$(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 Ye$(A,Q){let{entityType:$,provider:w,config:B}=Q;try{let X=B?Ce2.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=sA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Ze$(A,Q){let $=sO0.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 We$(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(!He$(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:sA(w)}),{success:!1}}}function He$(A){if(!A)return!1;let Q=Re2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Ke$(A,Q,$){let{entityType:w,entityId:B}=$;try{let X=$.authContext??vb;A.permissions.assertEntityActionAllowed(w,"publish",X);let Y=await Q.publicationQueueService.enqueue(w,B,X);return await A.messaging.send({type:tY.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=sA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function Ue$(A,Q,$){let{entityType:w,entityId:B}=$,X=$.authContext??vb;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=sA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function Ge$(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=sA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function De$(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=sA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function qe$(A,Q,$){let{entityType:w}=$;try{let B=await Q.queueManager.list(w);return await A.messaging.send({type:tY.LIST_RESPONSE,payload:{entityType:w,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=sA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function ze$(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 Je$(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 Ve$(A,Q){let{entityType:$,entityId:w}=Q;return A.scheduler.completeGeneration($,w),A.logger.info("Generation completed",{entityType:$,entityId:w}),{success:!0}}async function Fe$(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:sA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${sA(B)}`}}}function re2(A){let{context:Q,config:$,queueManager:w,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=Le$(Q);return KI.createFresh({queueManager:w,providerRegistry:B,retryTracker:X,logger:Z,backend:new Xh({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 Le$(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:()=>{}}}v0();v0();var Ie$=W.enum(["draft","queued","published","failed"]),Ne$=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()}),_e$=W.object({id:W.string(),label:W.string(),target:W.string(),status:W.enum(["pending","processing"])}),Pe$=W.object({entityId:W.string(),entityType:W.string(),title:W.string(),error:W.string(),retryCount:W.number().int().nonnegative()}),be$=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(Ne$),generating:W.array(_e$),failures:W.array(Pe$),publishableEntityTypes:W.array(W.string())}),je$=W.object({sourceEntityType:W.string(),sourceEntityId:W.string(),attachmentType:W.string().optional()});async function Af0(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=Ie$.safeParse(D.metadata.status);if(!q.success)continue;Y[q.data]+=1;let V=D.metadata.scheduledFor,L=D.metadata.error;X.set(oe2(U,D.id),{entityId:D.id,entityType:U,title:ke$(D.id,D.metadata),status:q.data,...typeof V==="string"?{scheduledFor:V}:{},...typeof L==="string"?{error:L}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await $.list(U)){let q=X.get(oe2(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 Me$(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,be$.parse({summary:Y,queue:Z,generating:H,failures:K,publishableEntityTypes:B})}async function Me$(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=je$.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 oe2(A,Q){return`${A}\x00${Q}`}function ke$(A,Q){for(let $ of["title","subject","slug"]){let w=Q[$];if(typeof w==="string"&&w.length>0)return w}return A}async function se2(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 Af0(A,$.providerRegistry,$.queueManager,$.retryTracker),...$.managementUrl?{managementUrl:$.managementUrl}:{}}),digestProvider:fe$}})}var Oe$=W.object({summary:W.object({draft:W.number(),queued:W.number(),generating:W.number(),published:W.number(),failed:W.number(),needsOperator:W.number()})});function fe$(A){let{summary:Q}=Oe$.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();v0();var xe$=W.object({workspaceUrl:W.string()}),Re$=W.object({confirmed:W.literal(!0),confirmationToken:W.string().min(1),contentHash:W.string().min(1),expiresAt:W.string().datetime()}),ve$=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:Re$.optional()})]);async function ae2(A,Q,$){let w=Go(A,Q,$.providerRegistry,$.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",priority:40,entityTypes:$.providerRegistry.getRegisteredTypes(),dataProvider:()=>Af0(A,$.providerRegistry,$.queueManager,$.retryTracker),actionHandler:async(Z,H)=>{let K=ve$.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return Ce$(A,$,w,K.data,H)}},X=await A.messaging.send({type:h_,payload:B});if(!("success"in X)||!X.success)return;let Y=xe$.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function Ce$(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 te2={name:"@brains/content-pipeline",version:"0.2.0-alpha.206",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 EIA extends d6{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",te2,A,he2)}async onRegister(A){this.pluginContext=A,this.queueManager=WI.createFresh(),this.publicationQueueService=new hIA(A,this.queueManager),this.providerRegistry=HI.createFresh(),this.retryTracker=UI.createFresh(),this.publishAssetRegistry=GI.createFresh(),this.publishAssetPreflight=new aO0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new Uo({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=re2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),de2(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 ae2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await se2(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[tO0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),Go(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),eO0(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(),WI.resetInstance(),HI.resetInstance(),UI.resetInstance(),GI.resetInstance()}}function TIA(A={}){return new EIA(A)}zA();v0();var ee2=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")}),yIA=W.object({cloudflare:ee2.optional()});zA();v0();var Ee$=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 Te$(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 A0Q(A,Q,$){let w=[];if(!$)return w;return w.push(e8(A,"query",`Query website analytics from Cloudflare.
8359
8359
 
8360
8360
  Date range options (use only one):
8361
8361
  - No params: yesterday only
@@ -8493,7 +8493,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,Ee$,
8493
8493
  }
8494
8494
  }
8495
8495
  }
8496
- `,{...this.baseVariables(A),limit:A.limit??20})).map((w)=>({country:w.dimensions.countryName,visits:w.sum.visits}))}}var SIA=7,ye$=10;function $0Q(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=mJ0(),$=LL1(SIA),w=Bl($),B=Bl(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:B}),A.getTopPages({startDate:w,endDate:B,limit:ye$})]);return{days:SIA,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:SIA}}}}var w0Q={name:"@brains/analytics",version:"0.2.0-alpha.204",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 B0Q extends d6{cloudflareClient;constructor(A={}){super("analytics",w0Q,A,yIA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new gIA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",$0Q(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:Q0Q(Q)}})}async getTools(){return A0Q(this.id,this.getContext(),this.cloudflareClient)}}function Se$(A={}){return new B0Q(A)}var Qf0=Se$;zA();v0();zA();v0();import{join as re$}from"path";p2();var X0Q="note",me$=new Set(["description","excerpt","summary","tagline","story"]);function ue$(A){if(A.endsWith("s"))return A;return B3(A)}function e90(A){return A===X0Q}function Y0Q(A,Q){let $=A===X0Q?"Note":tj(A),w=Q?.label??$;return{label:w,pluralLabel:Q?.pluralName??ue$(w)}}function a90(A){return typeof A==="object"&&A!==null}function my(A){if(!a90(A))return;let Q=A.def;return a90(Q)?Q:void 0}function Z0Q(A){let Q=my(A)?.type;return typeof Q==="string"?Q:void 0}function ce$(A){return typeof A==="function"?A():A}function mIA(A,Q=!1,$){let w=Z0Q(A),B=my(A);if(w==="optional"||w==="nullable")return mIA(B?.innerType,!0,$);if(w==="default")return mIA(B?.innerType,!0,ce$(B?.defaultValue));let X={inner:A,isOptional:Q};if($!==void 0)X.defaultValue=$;return X}function pe$(A){let Q=my(A)?.entries;if(!a90(Q))return;let $=Object.values(Q);return $.every((w)=>typeof w==="string")?$:void 0}function le$(A){let Q=my(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function ie$(A){let Q=my(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some(($)=>{return my($)?.format==="datetime"})}function de$(A){return A==="imageId"||A.endsWith("ImageId")}function ne$(A){if(!a90(A))return;let Q=A.shape;return a90(Q)?Q:void 0}function t90(A,Q){let{inner:$,isOptional:w,defaultValue:B}=mIA(Q),X=Z0Q($),Y=B??le$($),Z={name:A,label:tj(A),widget:"string",...w&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(de$(A))return{...Z,widget:"image"};if(ie$($))return{...Z,widget:"datetime"};if(me$.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=pe$($);return{...Z,widget:"select",...H?{options:H}:{}}}case"array":{let H=my($)?.element,K=t90("item",H);if(K.widget==="object"&&K.fields)return{...Z,widget:"list",fields:K.fields};return{...Z,widget:"list",field:{name:A,label:tj(A),widget:K.widget}}}case"object":{let H=Object.entries(ne$($)??{}).map(([K,U])=>t90(K,U));return{...Z,widget:"object",fields:H}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function W0Q(A){return`<!doctype html>
8496
+ `,{...this.baseVariables(A),limit:A.limit??20})).map((w)=>({country:w.dimensions.countryName,visits:w.sum.visits}))}}var SIA=7,ye$=10;function $0Q(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=mJ0(),$=LL1(SIA),w=Bl($),B=Bl(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:w,endDate:B}),A.getTopPages({startDate:w,endDate:B,limit:ye$})]);return{days:SIA,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:SIA}}}}var w0Q={name:"@brains/analytics",version:"0.2.0-alpha.206",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 B0Q extends d6{cloudflareClient;constructor(A={}){super("analytics",w0Q,A,yIA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new gIA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",$0Q(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:Q0Q(Q)}})}async getTools(){return A0Q(this.id,this.getContext(),this.cloudflareClient)}}function Se$(A={}){return new B0Q(A)}var Qf0=Se$;zA();v0();zA();v0();import{join as re$}from"path";p2();var X0Q="note",me$=new Set(["description","excerpt","summary","tagline","story"]);function ue$(A){if(A.endsWith("s"))return A;return B3(A)}function e90(A){return A===X0Q}function Y0Q(A,Q){let $=A===X0Q?"Note":tj(A),w=Q?.label??$;return{label:w,pluralLabel:Q?.pluralName??ue$(w)}}function a90(A){return typeof A==="object"&&A!==null}function my(A){if(!a90(A))return;let Q=A.def;return a90(Q)?Q:void 0}function Z0Q(A){let Q=my(A)?.type;return typeof Q==="string"?Q:void 0}function ce$(A){return typeof A==="function"?A():A}function mIA(A,Q=!1,$){let w=Z0Q(A),B=my(A);if(w==="optional"||w==="nullable")return mIA(B?.innerType,!0,$);if(w==="default")return mIA(B?.innerType,!0,ce$(B?.defaultValue));let X={inner:A,isOptional:Q};if($!==void 0)X.defaultValue=$;return X}function pe$(A){let Q=my(A)?.entries;if(!a90(Q))return;let $=Object.values(Q);return $.every((w)=>typeof w==="string")?$:void 0}function le$(A){let Q=my(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function ie$(A){let Q=my(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some(($)=>{return my($)?.format==="datetime"})}function de$(A){return A==="imageId"||A.endsWith("ImageId")}function ne$(A){if(!a90(A))return;let Q=A.shape;return a90(Q)?Q:void 0}function t90(A,Q){let{inner:$,isOptional:w,defaultValue:B}=mIA(Q),X=Z0Q($),Y=B??le$($),Z={name:A,label:tj(A),widget:"string",...w&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(de$(A))return{...Z,widget:"image"};if(ie$($))return{...Z,widget:"datetime"};if(me$.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=pe$($);return{...Z,widget:"select",...H?{options:H}:{}}}case"array":{let H=my($)?.element,K=t90("item",H);if(K.widget==="object"&&K.fields)return{...Z,widget:"list",fields:K.fields};return{...Z,widget:"list",field:{name:A,label:tj(A),widget:K.widget}}}case"object":{let H=Object.entries(ne$($)??{}).map(([K,U])=>t90(K,U));return{...Z,widget:"object",fields:H}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function W0Q(A){return`<!doctype html>
8497
8497
  <html lang="en" data-climate="paper">
8498
8498
  <head>
8499
8499
  <meta charset="utf-8" />
@@ -8551,7 +8551,7 @@ ${Kn}
8551
8551
  </html>`}var oe$=re$(import.meta.dir,"..","dist","ui","cms-app.js"),se$=W.object({entityType:W.string(),id:W.string(),frontmatter:W.record(W.string(),W.unknown()),body:W.string().optional(),baseContentHash:W.string().optional()}),ae$=W.object({entityType:W.string(),frontmatter:W.record(W.string(),W.unknown()),body:W.string().optional()}),te$=W.object({id:W.string().trim().min(1),action:W.unknown()}),uIA={entityType:W.string(),body:W.string(),frontmatter:W.record(W.string(),W.unknown())},ee$=W.union([W.object({...uIA,variant:W.literal("rewrite").optional(),instruction:W.string().trim().min(1),selection:W.string().min(1).max(8000)}),W.object({...uIA,variant:W.literal("summarise"),targetField:W.string().trim().min(1),body:W.string().min(1)}),W.object({...uIA,variant:W.literal("tag-suggest"),targetField:W.string().trim().min(1),body:W.string().min(1)})]),H0Q=W.object({suggestion:W.string()}),A08=W.object({suggestions:W.array(W.string().trim().min(1)).max(12)}),Q08=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)}),$08=W.looseObject({response:W.string()}),w08=W.object({agents:W.array(W.object({id:W.string(),label:W.string()}))}),B08="file",K0Q=10485760,X08=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 U0Q(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(W0Q({assetPath:Y,surfaces:_f($().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(oe$);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 Z08($(),B(),X)}},{path:Z("workspace"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return W08(X,K)}},{path:Z("workspace"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return H08(X,K)}},{path:Z("schema"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return K08($(),K)}},{path:Z("entities"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return U08($(),K)}},{path:Z("entities"),method:"PUT",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return G08($(),K)}},{path:Z("entities"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return D08($(),K)}},{path:Z("entities"),method:"DELETE",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return q08($(),K)}},{path:Z("upload"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return F08($(),K,Z("upload"))}},{path:Z("assist"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return z08($(),K)}},{path:Z("agents"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return J08($())}},{path:Z("ask-agent"),method:"POST",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return V08($(),K)}},{path:Z("sync-status"),method:"GET",public:!0,handler:async(K)=>{let U=await H(K);if(U)return U;return Y08($())}}]}async function Y08(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=X08.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 Z08(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:Y0Q(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 W08(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 H08(A,Q){let $;try{$=te$.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 K08(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=e90($),Y=X?[]:Object.entries(w.shape).map(([Z,H])=>t90(Z,H));return PQ({entityType:$,format:X?"raw":"frontmatter",isSingleton:B?.isSingleton===!0,hasBody:X||B?.hasBody!==!1,fields:Y})}async function U08(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}=cIA(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:cIA(w,Y.content).frontmatter,updated:Y.updated}))})}async function G08(A,Q){let $;try{$=se$.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=G0Q(A,w,$.body);if(Y)return Y;let Z=e90(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??cIA(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},V=await A.entityService.updateEntity({entity:q});return PQ({entityId:V.entityId,jobId:V.jobId,skipped:V.skipped})}async function D08(A,Q){let $;try{$=ae$.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=G0Q(A,w,$.body);if(X)return X;let Y=e90(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 q08(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 z08(A,Q){let $;try{$=ee$.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=t90($.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(`
8552
8552
  `),H0Q);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(`
8553
8553
  `),A08);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(`
8554
- `),{object:X}=await A.ai.generateObject(B,H0Q);return PQ({suggestion:X.suggestion})}async function J08(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return PQ({agents:[]});let $=w08.safeParse(Q.data);return PQ($.success?$.data:{agents:[]})}async function V08(A,Q){let $;try{$=Q08.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=$08.safeParse(w.data);if(!B.success)return PQ({error:"Invalid response from agent"},502);return PQ({agentId:$.agent,response:B.data.response})}async function F08(A,Q,$){let w=Number(Q.headers.get("content-length"));if(Number.isFinite(w)&&w>K0Q)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(B08);if(!(X instanceof File))return PQ({error:"Missing upload file"},400);if(X.size>K0Q)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 G0Q(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 cIA(A,Q){if(e90(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"}})}v0();var L08=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 pIA{workspaces=new Map;register(A){let Q=L08.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 D0Q={name:"@brains/cms",version:"0.2.0-alpha.204",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 N08=W.looseObject({label:W.string().optional(),pluralName:W.string().optional()}),_08=W.object({entityDisplay:W.record(W.string(),N08).optional(),routePath:W.string().default("/cms")});class lIA extends d6{workspaceRegistry=new pIA;constructor(A={}){super("cms",D0Q,A,_08)}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(h_,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 U0Q({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:P08,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay,workspaceRegistry:this.workspaceRegistry})}}function uy(A={}){return new lIA(A)}async function P08(A){return Boolean(await vY()?.getOperatorSession(A))}zA();v0();zA();v0();var $f0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],b08=new Set($f0),j08=W.enum(["public","trusted","anchor"]);function iIA(A){return b08.has(A)}var q0Q=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),z0Q=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:j08.default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(q0Q).max(4).optional()});class wf0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let $={...z0Q.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}}yZ();var J0Q=`/* Deprecated aliases for custom widgets authored before WidgetTabs. */
8554
+ `),{object:X}=await A.ai.generateObject(B,H0Q);return PQ({suggestion:X.suggestion})}async function J08(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return PQ({agents:[]});let $=w08.safeParse(Q.data);return PQ($.success?$.data:{agents:[]})}async function V08(A,Q){let $;try{$=Q08.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=$08.safeParse(w.data);if(!B.success)return PQ({error:"Invalid response from agent"},502);return PQ({agentId:$.agent,response:B.data.response})}async function F08(A,Q,$){let w=Number(Q.headers.get("content-length"));if(Number.isFinite(w)&&w>K0Q)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(B08);if(!(X instanceof File))return PQ({error:"Missing upload file"},400);if(X.size>K0Q)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 G0Q(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 cIA(A,Q){if(e90(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"}})}v0();var L08=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 pIA{workspaces=new Map;register(A){let Q=L08.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 D0Q={name:"@brains/cms",version:"0.2.0-alpha.206",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 N08=W.looseObject({label:W.string().optional(),pluralName:W.string().optional()}),_08=W.object({entityDisplay:W.record(W.string(),N08).optional(),routePath:W.string().default("/cms")});class lIA extends d6{workspaceRegistry=new pIA;constructor(A={}){super("cms",D0Q,A,_08)}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(h_,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 U0Q({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:P08,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay,workspaceRegistry:this.workspaceRegistry})}}function uy(A={}){return new lIA(A)}async function P08(A){return Boolean(await vY()?.getOperatorSession(A))}zA();v0();zA();v0();var $f0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],b08=new Set($f0),j08=W.enum(["public","trusted","anchor"]);function iIA(A){return b08.has(A)}var q0Q=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),z0Q=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:j08.default("public"),needsOperator:W.number().int().nonnegative().optional(),digest:W.array(q0Q).max(4).optional()});class wf0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let $={...z0Q.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}}yZ();var J0Q=`/* Deprecated aliases for custom widgets authored before WidgetTabs. */
8555
8555
  .view-tabs {
8556
8556
  display: flex;
8557
8557
  gap: 24px;
@@ -10606,7 +10606,7 @@ ${J0Q}`;var Xf0=`(function () {
10606
10606
  `);function C08(A){return`${A.replace(/\/+$/,"")}/assets`}class dIA{basePath;assets=new Map;dashboardStylesUrl;dashboardScriptUrl;constructor(A){this.basePath=C08(A),this.dashboardStylesUrl=this.register("dashboard","css","text/css; charset=utf-8",Bf0),this.dashboardScriptUrl=this.register("dashboard","js","text/javascript; charset=utf-8",v08)}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":R08,"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 Yf0{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:sA(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:sA($)}),{}}}async fetch(A,Q,$){return await this.getDashboardData()}}import{render as NA8}from"preact-render-to-string";p2();import{jsxDEV as Zf0}from"preact/jsx-dev-runtime";function h08(A,Q){let $=A.endpoints.find((w)=>w.label.toLowerCase().includes("doc"));if(!$)return null;return tS($.url,Q)}function N0Q(A){let{title:Q,appInfo:$,baseUrl:w}=A,B=h08($,w);return Zf0("footer",{class:"colophon",children:[Zf0("span",{class:"colophon-mark",children:[Q," \xB7 dashboard"]},void 0,!0,void 0,this),Zf0("span",{class:"colophon-actions",children:B&&Zf0("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 eY}from"preact/jsx-dev-runtime";function _0Q({dashboardPath:A,surfaces:Q,operatorAccess:$}){let w=$?.isOperator?$.logoutUrl:$?.loginUrl??"/login",B=$?.isOperator?"Operator":"Visitor",X=$?.isOperator?"Sign out":"Sign in";return eY("header",{class:"console-strip","aria-label":"Operator surfaces",children:[eY("a",{class:"console-mark",href:A,"aria-label":"Dashboard home",children:[eY("span",{class:"pulse"},void 0,!1,void 0,this),eY("span",{children:["Brain"," ",eY("span",{class:"console-mark-long",children:["\xB7 ",eY("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),eY("nav",{class:"surface-nav","aria-label":"Console surfaces",children:Q.map((Y)=>eY("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),eY("button",{class:"command-chip",type:"button","aria-label":"Search or jump",children:[eY("span",{class:"command-chip-hint",children:"Search or jump\u2026"},void 0,!1,void 0,this),eY("kbd",{children:"\u2318K"},void 0,!1,void 0,this),eY("span",{class:"command-chip-icon","aria-hidden":"true",children:"\u2315"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),eY("button",{id:"climateToggle",class:"climate-chip",type:"button","aria-label":"Toggle climate",children:"\u25D0"},void 0,!1,void 0,this),eY("a",{class:$?.isOperator?"session-chip":"session-chip is-visitor",href:w,"aria-label":`${B} \xB7 ${X}`,children:[eY("span",{children:B},void 0,!1,void 0,this),eY("strong",{children:X},void 0,!1,void 0,this),eY("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 E08=["knowledge","publishing","network","system"],T08={knowledge:"Knowledge",publishing:"Publishing",network:"Network",system:"System"};function Do(A){let Q=T08[A];if(Q)return Q;return A.split(/[-_\s]+/).filter(Boolean).map(($)=>`${$.slice(0,1).toUpperCase()}${$.slice(1)}`).join(" ")}function Wf0(A){let Q=new Map(E08.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 Do($).localeCompare(Do(w))})}import{jsxDEV as qo}from"preact/jsx-dev-runtime";function nIA(){return{primary:[],secondary:[],sidebar:[]}}function Hf0(A){return[...A.widgets.primary,...A.widgets.secondary,...A.widgets.sidebar]}function Kf0(A){return Hf0(A).length}function y08(A){return Hf0(A).reduce((Q,$)=>Q+($.widget.needsOperator??0),0)}function g08(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function P0Q(A){let Q=new Map;for(let w of Object.values(A)){let B=w.widget.group,X=Q.get(B)??nIA();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,nIA());return Wf0(Array.from(Q.keys())).map((w)=>{let B=g08(w),X=$.get(B)??0,Y=Q.get(w)??nIA(),Z={id:X===0?B:`${B}-${X+1}`,group:w,label:Do(w),widgets:Y,widgetCount:0,needsOperator:0};return $.set(B,X+1),{...Z,widgetCount:Kf0(Z),needsOperator:y08(Z)}})}function b0Q({tabs:A}){return qo("nav",{class:"dashboard-tabs","aria-label":"Dashboard sections",role:"tablist",children:[qo("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)=>qo("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:[qo("span",{children:Q.label},void 0,!1,void 0,this),Q.needsOperator>0?qo("span",{class:"tab-badge tab-badge--needs",children:Q.needsOperator},void 0,!1,void 0,this):Q.widgetCount>0?qo("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 cy,Fragment as j0Q}from"preact/jsx-dev-runtime";function S08({title:A}){let Q=A.trim(),$=Q.lastIndexOf(" ");if($<=0)return cy(j0Q,{children:Q},void 0,!1,void 0,this);return cy(j0Q,{children:[Q.slice(0,$)," ",cy("em",{children:Q.slice($+1)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function M0Q(A){let{title:Q,tagline:$}=A;return cy("header",{class:"masthead",children:[cy("h1",{class:"brand",children:cy(S08,{title:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&cy("p",{class:"tagline",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as c$,Fragment as k0Q}from"preact/jsx-dev-runtime";import{createElement as rIA}from"preact";function DI(...A){return A.filter(Boolean).join(" ")}function oIA(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 c$("div",{class:"card-head",children:[c$("span",{class:"card-title",children:A},void 0,!1,void 0,this),Q?c$("span",{class:"card-from",children:Q},void 0,!1,void 0,this):$?c$("span",{class:"card-subtitle",children:$},void 0,!1,void 0,this):w]},void 0,!0,void 0,this)}function Jx({items:A}){return c$("dl",{class:"kv",children:A.map((Q,$)=>c$("div",{class:"kv-row",children:[c$("dt",{children:Q.label},void 0,!1,void 0,this),c$("dd",{children:Q.value},void 0,!1,void 0,this)]},$,!0,void 0,this))},void 0,!1,void 0,this)}function Cb({children:A="Nothing to show yet.",className:Q}){return c$("p",{class:DI("muted",Q),children:A},void 0,!1,void 0,this)}var VD=Cb;function A70({label:A,children:Q,className:$}){return c$("nav",{class:DI("widget-actions",$),"aria-label":A,children:Q},void 0,!1,void 0,this)}function Q70({href:A,children:Q,external:$=!1,emphasis:w="secondary"}){return c$("a",{class:DI("widget-action",`widget-action--${w}`),href:A,...$?{target:"_blank",rel:"noreferrer"}:{},children:[c$("span",{children:Q},void 0,!1,void 0,this),c$("span",{class:"widget-action-arrow","aria-hidden":"true",children:$?"\u2197":"\u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function zo({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":DI("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 c$("div",{...H,class:Z,"data-ui-tabs":!0,"data-ui-tabs-default":$,...Y?{"data-ui-tabs-state-attribute":Y}:{},children:[c$("div",{class:K,role:"tablist","aria-label":Q,children:w.map((q)=>{let V=q.value===$,L=`${A}-tab-${q.value}`,F=`${A}-panel-${q.value}`;return rIA("button",{...q.triggerProps,id:L,key:q.value,class:DI(U,V&&"is-active"),type:"button",role:"tab","data-ui-tab":q.value,"aria-controls":F,"aria-selected":V?"true":"false"},B==="pill"?c$(k0Q,{children:[q.count!==void 0&&c$("span",{class:G,children:q.count},void 0,!1,void 0,this),c$("span",{class:D,children:q.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this):c$(k0Q,{children:[q.label,q.count!==void 0&&c$("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 V=q.value===$;return rIA("div",{...q.panelProps,id:`${A}-panel-${q.value}`,key:q.value,class:DI(q.panelClassName,V&&"is-active"),"data-ui-panel":q.value,role:"tabpanel","aria-labelledby":`${A}-tab-${q.value}`,hidden:!V},q.content)})]},void 0,!0,void 0,this)}function sIA({label:A,defaultValue:Q,options:$,children:w,emptyState:B,className:X,allValue:Y="all"}){return c$("div",{class:X,"data-ui-filter":!0,"data-ui-filter-default":Q,"data-ui-filter-all":Y,children:[c$("div",{class:"widget-filter-tabs widget-filter-tabs--compact","aria-label":A,children:$.map((Z)=>{let H=Z.value===Q;return rIA("button",{...Z.triggerProps,key:Z.value,class:DI("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&&c$("span",{class:"widget-filter-count",children:Z.count},void 0,!1,void 0,this),c$("span",{class:"widget-filter-label",children:Z.label},void 0,!1,void 0,this))})},void 0,!1,void 0,this),w,B!==void 0&&c$("div",{"data-ui-filter-empty":!0,hidden:!0,children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Vx({children:A,className:Q}){return c$("ul",{class:DI("list",Q),children:A},void 0,!1,void 0,this)}function O0Q({segments:A}){if(A.length===0)return null;return c$("span",{class:"list-meta-text",children:A.map((Q,$)=>c$("span",{children:[$>0&&c$("span",{class:"sep",children:"\xB7"},void 0,!1,void 0,this),Q]},`${Q}:${$}`,!0,void 0,this))},void 0,!1,void 0,this)}function f0Q({tags:A}){if(A.length===0)return null;return c$("div",{class:"list-tags",children:A.map((Q,$)=>c$("span",{class:"tag",children:Q},`${Q}:${$}`,!1,void 0,this))},void 0,!1,void 0,this)}function py({children:A,tone:Q="plain"}){let $={plain:"",warn:"pill--warn",error:"pill--err",ok:"pill--ok",muted:"pill--mute"}[Q];return c$("span",{class:DI("pill",$),children:A},void 0,!1,void 0,this)}function Fx({title:A,description:Q,meta:$=[],tags:w=[],trailing:B,filterValues:X,className:Y,itemProps:Z}){return c$("li",{...Z,class:DI("list-item",Y),...X?{"data-ui-filter-values":JSON.stringify(X)}:{},children:[c$("div",{class:"list-main",children:[c$("span",{class:"list-name",children:A},void 0,!1,void 0,this),Q&&c$("span",{class:"list-desc",children:Q},void 0,!1,void 0,this),c$(O0Q,{segments:$},void 0,!1,void 0,this),c$(f0Q,{tags:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B&&c$("div",{class:"list-meta",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function x0Q(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 $70(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 Uf0(A){return A.indexStatus?.ready??A.indexReady??A.appInfo.embeddings>0}function m08(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 u08(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 c08({status:A}){let Q=m08(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:u08(A)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function R0Q({input:A}){let Q=Uf0(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(c08,{status:A.indexStatus},void 0,!1,void 0,this):w8(Jx,{items:[{label:"Semantic index",value:Q?"Ready":"Pending"}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function v0Q({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(Jx,{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 ${x0Q(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(A70,{label:"Content sync actions",children:w8(Q70,{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 p08={pending:"run",processing:"run",completed:"done",failed:"fail"},l08={pending:"pending",processing:"running",completed:"done",failed:"failed"};function C0Q({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(VD,{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:$70(Q.updatedAt)},void 0,!1,void 0,this),w8("td",{children:w8("span",{class:`status-pill status-pill--${p08[Q.status]}`,children:[l08[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 i08(A,Q){if(A.group==="system"){let $=Uf0(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:Kf0(A)===1?"Widget":"Widgets",value:String(Kf0(A))}]}function d08(A,Q){return A.map(($)=>{let w=Hf0($).flatMap((B)=>B.widget.digest??[]).slice(0,4);return{id:$.id,label:$.label,href:`#${$.id}`,lines:w.length>0?w:i08($,Q)}})}function n08({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 r08({input:A}){let Q=Uf0(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:$?$70($.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 o08({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 s08({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(VD,{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 h0Q={created:{glyph:"\uFF0B",tone:""},updated:{glyph:"\u2713",tone:" ledger-glyph--ok"},deleted:{glyph:"\u2212",tone:" ledger-glyph--warn"}};function a08({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(VD,{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:$70(Q.timestamp)},void 0,!1,void 0,this),kQ("span",{class:`ledger-glyph${h0Q[Q.action].tone}`,"aria-hidden":"true",children:h0Q[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 E0Q({input:A,tabs:Q,showOperatorGate:$}){let w=d08(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(r08,{input:A},void 0,!1,void 0,this),kQ(o08,{input:A},void 0,!1,void 0,this),$&&A.operatorAccess&&kQ(n08,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),kQ("div",{class:"overview-grid",children:[kQ(s08,{cards:w},void 0,!1,void 0,this),kQ(a08,{events:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}p2();import{jsxDEV as ly}from"preact/jsx-dev-runtime";function t08(A){try{let Q=new URL(A);return Q.host+Q.pathname.replace(/\/$/,"")}catch{return A}}function T0Q(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 ly("aside",{class:"card",children:[ly(DX,{title:"Endpoints"},void 0,!1,void 0,this),ly("dl",{class:"links",children:w.map((B)=>{let X=tS(B.url,$);return ly("a",{class:"link",href:X,target:"_blank",rel:"noopener noreferrer",children:[ly("dt",{children:MW0(B.label)},void 0,!1,void 0,this),ly("dd",{children:t08(X)},void 0,!1,void 0,this),ly("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 FW}from"preact/jsx-dev-runtime";function e08({entityType:A,count:Q,max:$}){let w=Math.max(4,Math.round(Q/$*100));return FW("div",{class:"breakdown-row",children:[FW("span",{class:"breakdown-name",children:tj(A)},void 0,!1,void 0,this),FW("span",{class:"breakdown-count",children:Q},void 0,!1,void 0,this),FW("div",{class:"breakdown-bar",children:FW("i",{style:{width:`${w}%`}},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function y0Q(A){let{total:Q,entityCounts:$}=A;if($.length===0)return FW("article",{class:"card card--entity-summary",children:[FW(DX,{title:"Entities"},void 0,!1,void 0,this),FW(VD,{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 FW("article",{class:"card card--entity-summary",children:[FW(DX,{title:"Entities",subtitle:"corpus \xB7 sorted by volume"},void 0,!1,void 0,this),FW("div",{class:"entities",children:[FW("div",{children:[FW("div",{class:"entity-summary-number",children:Q},void 0,!1,void 0,this),FW("div",{class:"entity-summary-label",children:"indexed entities"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),FW("div",{class:"breakdown",children:w.map((X)=>FW(e08,{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 Lx}from"preact/jsx-dev-runtime";var AA8={human:"Human",agent:"Agent",admin:"Admin",protocol:"Protocol"};function g0Q(A){let{interactions:Q,baseUrl:$}=A;if(Q.length===0)return null;return Lx("aside",{class:"card interactions-card",children:[Lx(DX,{title:"Ways to connect"},void 0,!1,void 0,this),Lx("div",{class:"interactions-list",children:Q.slice(0,5).map((w)=>{let B=tS(w.href,$);return Lx("a",{class:`interaction-link interaction-link--${w.kind}`,href:B,target:"_blank",rel:"noopener noreferrer",children:[Lx("span",{children:[Lx("strong",{children:MW0(w.label)},void 0,!1,void 0,this),w.description&&Lx("em",{children:w.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Lx("small",{children:AA8[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 aIA}from"preact/jsx-dev-runtime";function QA8(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 $A8(A){let Q=($)=>String($).padStart(2,"0");return`${A.getFullYear()}-${Q(A.getMonth()+1)}-${Q(A.getDate())} ${Q(A.getHours())}:${Q(A.getMinutes())}`}function S0Q(A){let{appInfo:Q,now:$}=A,w=Q.daemons.length,B=Q.daemons.filter((X)=>X.health?.status==="healthy").length;return aIA("aside",{class:"card runtime-card",children:[aIA(DX,{title:"Runtime",source:"core"},void 0,!1,void 0,this),aIA(Jx,{items:[{label:"Version",value:`v${Q.version}`},{label:"Daemons",value:w===0?"\u2014":`${B}/${w} healthy`},{label:"Model",value:Q.model},{label:"Uptime",value:QA8(Q.uptime)},{label:"Embeddings",value:Q.embeddings},{label:"Rendered",value:$A8($)}]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}p2();v0();import{jsxDEV as q8,Fragment as LA8}from"preact/jsx-dev-runtime";var wA8=new Set(["rendered","version"]),BA8=new Set(["StatsWidget","SystemWidget"]),XA8=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()}),YA8=W.object({items:W.array(XA8)}),ZA8=W.record(W.string(),W.unknown()),WA8=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()}),HA8={crit:"error",critical:"error",high:"warn",med:"plain",medium:"plain",low:"muted"};function KA8(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 UA8(A){if(typeof A==="object")return JSON.stringify(A);return String(A)}function m0Q(A){let Q=YA8.safeParse(A);if(!Q.success||Q.data.items.length===0)return[];return Q.data.items}function GA8(A){let Q=ZA8.safeParse(A);return Q.success?Q.data:null}function DA8({widget:A}){if(A.widget.rendererName!=="ListWidget")return null;let Q=m0Q(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 qA8({widget:A}){let Q=GA8(A.data);if(!Q)return q8(VD,{},void 0,!1,void 0,this);let $=Object.entries(Q).filter(([w,B])=>!wA8.has(w)&&!KA8(B));if($.length===0)return q8(VD,{},void 0,!1,void 0,this);return q8(Jx,{items:$.map(([w,B])=>({label:tj(w),value:UA8(B)}))},void 0,!1,void 0,this)}function zA8({item:A}){let Q=A.priority?HA8[A.priority.toLowerCase()]??"plain":"plain",$=typeof A.count==="number"||Boolean(A.priority??A.status);return q8(Fx,{title:A.name,description:A.description,meta:A.meta,tags:A.tags,trailing:$?q8(LA8,{children:[typeof A.count==="number"&&q8("span",{class:"list-count",children:A.count},void 0,!1,void 0,this),A.priority&&q8(py,{tone:Q,children:A.priority},void 0,!1,void 0,this),A.status&&q8(py,{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 JA8({widget:A}){let Q=m0Q(A.data);if(Q.length===0)return q8(VD,{},void 0,!1,void 0,this);return q8(Vx,{children:Q.map(($)=>q8(zA8,{item:$},$.id,!1,void 0,this))},void 0,!1,void 0,this)}function Gf0({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 VA8({widget:A}){let Q=WA8.safeParse(A.data);if(!Q.success)return q8(VD,{},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(Gf0,{label:"Queued",value:$.queued},void 0,!1,void 0,this),q8(Gf0,{label:"Generating",value:$.generating},void 0,!1,void 0,this),q8(Gf0,{label:"Awaiting review",value:$.needsOperator,tone:$.needsOperator>0?"warn":""},void 0,!1,void 0,this),q8(Gf0,{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(A70,{label:"Publication actions",children:q8(Q70,{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 FA8({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:oIA(A.widget.pluginId,A.widget.id)},void 0,!1,void 0,this)}switch(A.widget.rendererName){case"PipelineWidget":return q8(VA8,{widget:A},void 0,!1,void 0,this);case"ListWidget":return q8(JA8,{widget:A},void 0,!1,void 0,this);default:return q8(qA8,{widget:A},void 0,!1,void 0,this)}}function tIA({widget:A,featured:Q=!1}){let $=BA8.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(DA8,{widget:A},void 0,!1,void 0,this)},void 0,!1,void 0,this),q8(FA8,{widget:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as AZ,Fragment as u0Q}from"preact/jsx-dev-runtime";function c0Q({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 AZ("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:[AZ("header",{class:"tab-section-head",children:AZ("h2",{children:A.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),AZ("div",{class:`layout tab-layout${Y?"":" tab-layout--main-only"}`,children:[AZ("div",{class:"main-column",children:[X&&AZ(y0Q,{total:Q.appInfo.entities,entityCounts:Q.appInfo.entityCounts},void 0,!1,void 0,this),B&&AZ(u0Q,{children:[AZ(R0Q,{input:Q},void 0,!1,void 0,this),Q.directorySyncStatus&&AZ(v0Q,{status:Q.directorySyncStatus},void 0,!1,void 0,this),AZ(C0Q,{jobs:Q.jobProgress??[]},void 0,!1,void 0,this)]},void 0,!0,void 0,this),w.map((Z)=>AZ(tIA,{widget:Z},`${Z.widget.pluginId}:${Z.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),Y&&AZ("div",{class:"sidebar-column",children:[B&&AZ(u0Q,{children:[AZ(T0Q,{endpoints:Q.appInfo.endpoints,baseUrl:Q.baseUrl},void 0,!1,void 0,this),AZ(S0Q,{appInfo:Q.appInfo,now:$},void 0,!1,void 0,this),AZ(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)=>AZ(tIA,{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 IA8}from"preact/jsx-dev-runtime";function p0Q({input:A}){let Q=P0Q(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:$50,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:Bf0}},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(`
10607
10607
 
10608
10608
  `)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Yw("body",{children:[Yw(_0Q,{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(M0Q,{title:A.title,tagline:A.profile.description},void 0,!1,void 0,this),Yw(b0Q,{tabs:Q},void 0,!1,void 0,this),Yw("div",{class:"canvas",children:Yw("div",{class:"dashboard-tab-panels",children:[Yw(E0Q,{input:A,tabs:Q,showOperatorGate:Boolean($)},void 0,!1,void 0,this),Q.map((X)=>Yw(c0Q,{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(N0Q,{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(IA8,{children:[Yw("script",{dangerouslySetInnerHTML:{__html:sP}},void 0,!1,void 0,this),Yw("script",{dangerouslySetInnerHTML:{__html:aP}},void 0,!1,void 0,this),Yw("script",{dangerouslySetInnerHTML:{__html:Xf0}},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 _A8}from"preact/jsx-dev-runtime";function l0Q(A){return`<!doctype html>
10609
- ${NA8(_A8(p0Q,{input:A},void 0,!1,void 0,this))}`}function PA8(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function i0Q(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=Wf0([...new Set(A.groups)]).map((B)=>({group:B,label:Do(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}#${PA8(B)}`,tag:"dashboard"}));if(w.length>0)$.push({id:"tabs",label:"Dashboard",items:w});return $}function d0Q(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.204",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 jA8=W.object({version:W.string().default("1.0.0"),routePath:W.string().default("/dashboard"),themeCSS:W.string().optional()}),MA8=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(!iIA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),kA8=W.object({pluginId:W.string(),widgetId:W.string().optional()}),OA8=W.object({entityType:W.string(),entityId:W.string(),conversationId:W.string().optional()}),fA8=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()}),xA8=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 RA8(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,jA8);this.assetRegistry=new dIA(this.config.routePath)}recordActivity(A,Q){let $=OA8.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=fA8.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:sA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=xA8.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:sA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new wf0(this.logger),this.datasource=new Yf0(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 $=MA8.parse(Q.payload),w=RA8($);return this.widgetRegistry?.register(w),this.logger.debug("Widget registered via messaging",{widgetId:$.id,pluginId:$.pluginId,rendererName:$.rendererName,builtIn:$f0.includes($.rendererName)}),{success:!0}}catch($){return this.logger.error("Failed to register widget",{error:sA($),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let $=kA8.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:sA($),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 vY()?.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(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),L={...K,endpoints:K.endpoints.filter((O)=>$9.hasPermission(B,O.visibility)),interactions:K.interactions.filter((O)=>$9.hasPermission(B,O.visibility))},F=q.name||K.model||"Brain Dashboard",_=new URL(A.url),j=`${_.pathname}${_.search}`,b=encodeURIComponent(j),k=d0Q(H.widgets,this.widgetRegistry),v=this.assetRegistry.createRenderUrls({themeCSS:this.config.themeCSS,widgetStyles:k.widgetStyles,widgetScripts:k.widgetScripts}),R={title:F,baseUrl:V,widgets:k.widgets,widgetStyles:k.widgetStyles,widgetScripts:k.widgetScripts,assetUrls:v,dashboardPath:this.config.routePath,surfaces:_f(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:q,appInfo:L,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(l0Q(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 vY()?.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=_f($.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:i0Q({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 Ix(A={}){return new eIA(A)}v0();var vA8=W.enum(["public","trusted","anchor"]),CA8=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),hA8=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:vA8,needsOperator:W.number().int().nonnegative().optional(),digest:W.array(CA8).max(4).optional(),component:W.custom().optional()}),EA8=W.object({widget:hA8,data:W.unknown()}),TA8=W.object({widgets:W.record(W.string(),EA8)});zA();v0();zA();v0();import{h as A18}from"preact";zA();yZ();p2();v0();var Df0=W.enum(["generating","draft","queued","published","failed"]),yA8=W.enum(["generating","draft","queued","published","failed"]),qf0=W.object({subject:W.string(),status:Df0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional()}),r0Q=W.object({subject:W.string(),status:Df0,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()}),gA8=W.object({subject:W.string(),status:yA8,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()}),Jo=U6.extend({entityType:W.literal("newsletter"),metadata:gA8});zA();class o0Q extends zQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Jo,frontmatterSchema:qf0})}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 s0Q=new o0Q;zA();zA();p2();v0();var SA8=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()}),mA8=W.looseObject({entityType:W.string().optional(),query:SA8.optional()});function a0Q(A){try{let{content:Q}=MQ(A.content,qf0);return Q}catch{return A.content}}class ANA 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=mA8.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=a0Q(A),$={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:lW(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=a0Q(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();v0();var uA8=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 QNA extends SZ{constructor(A,Q){super(A,Q,{schema:uA8,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 V=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let F=`Create an engaging newsletter that highlights these blog posts:
10609
+ ${NA8(_A8(p0Q,{input:A},void 0,!1,void 0,this))}`}function PA8(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function i0Q(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=Wf0([...new Set(A.groups)]).map((B)=>({group:B,label:Do(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}#${PA8(B)}`,tag:"dashboard"}));if(w.length>0)$.push({id:"tabs",label:"Dashboard",items:w});return $}function d0Q(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.206",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 jA8=W.object({version:W.string().default("1.0.0"),routePath:W.string().default("/dashboard"),themeCSS:W.string().optional()}),MA8=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(!iIA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),kA8=W.object({pluginId:W.string(),widgetId:W.string().optional()}),OA8=W.object({entityType:W.string(),entityId:W.string(),conversationId:W.string().optional()}),fA8=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()}),xA8=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 RA8(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,jA8);this.assetRegistry=new dIA(this.config.routePath)}recordActivity(A,Q){let $=OA8.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=fA8.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:sA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=xA8.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:sA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new wf0(this.logger),this.datasource=new Yf0(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 $=MA8.parse(Q.payload),w=RA8($);return this.widgetRegistry?.register(w),this.logger.debug("Widget registered via messaging",{widgetId:$.id,pluginId:$.pluginId,rendererName:$.rendererName,builtIn:$f0.includes($.rendererName)}),{success:!0}}catch($){return this.logger.error("Failed to register widget",{error:sA($),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let $=kA8.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:sA($),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 vY()?.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(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),L={...K,endpoints:K.endpoints.filter((O)=>$9.hasPermission(B,O.visibility)),interactions:K.interactions.filter((O)=>$9.hasPermission(B,O.visibility))},F=q.name||K.model||"Brain Dashboard",_=new URL(A.url),j=`${_.pathname}${_.search}`,b=encodeURIComponent(j),k=d0Q(H.widgets,this.widgetRegistry),v=this.assetRegistry.createRenderUrls({themeCSS:this.config.themeCSS,widgetStyles:k.widgetStyles,widgetScripts:k.widgetScripts}),R={title:F,baseUrl:V,widgets:k.widgets,widgetStyles:k.widgetStyles,widgetScripts:k.widgetScripts,assetUrls:v,dashboardPath:this.config.routePath,surfaces:_f(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:q,appInfo:L,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(l0Q(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 vY()?.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=_f($.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:i0Q({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 Ix(A={}){return new eIA(A)}v0();var vA8=W.enum(["public","trusted","anchor"]),CA8=W.object({label:W.string(),value:W.string(),tone:W.enum(["plain","good","warn"]).optional()}),hA8=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:vA8,needsOperator:W.number().int().nonnegative().optional(),digest:W.array(CA8).max(4).optional(),component:W.custom().optional()}),EA8=W.object({widget:hA8,data:W.unknown()}),TA8=W.object({widgets:W.record(W.string(),EA8)});zA();v0();zA();v0();import{h as A18}from"preact";zA();yZ();p2();v0();var Df0=W.enum(["generating","draft","queued","published","failed"]),yA8=W.enum(["generating","draft","queued","published","failed"]),qf0=W.object({subject:W.string(),status:Df0,entityIds:W.array(W.string()).optional(),scheduledFor:W.string().datetime().optional(),sentAt:W.string().datetime().optional(),buttondownId:W.string().optional(),sourceEntityType:W.string().optional()}),r0Q=W.object({subject:W.string(),status:Df0,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()}),gA8=W.object({subject:W.string(),status:yA8,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()}),Jo=U6.extend({entityType:W.literal("newsletter"),metadata:gA8});zA();class o0Q extends zQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Jo,frontmatterSchema:qf0})}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 s0Q=new o0Q;zA();zA();p2();v0();var SA8=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()}),mA8=W.looseObject({entityType:W.string().optional(),query:SA8.optional()});function a0Q(A){try{let{content:Q}=MQ(A.content,qf0);return Q}catch{return A.content}}class ANA 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=mA8.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=a0Q(A),$={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:lW(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=a0Q(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();v0();var uA8=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 QNA extends SZ{constructor(A,Q){super(A,Q,{schema:uA8,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 V=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let F=`Create an engaging newsletter that highlights these blog posts:
10610
10610
 
10611
10611
  ${V.map((b)=>`## ${b.metadata.title}
10612
10612
 
@@ -10675,17 +10675,17 @@ Newsletter-specific guidelines:
10675
10675
  - "Reply and let me know..."
10676
10676
  - "Until next time..."
10677
10677
 
10678
- The goal is to build a relationship with readers through valuable, authentic content.`});v0();zA();import{jsxDEV as yH,Fragment as nA8}from"preact/jsx-dev-runtime";var pA8=W.enum(["generating","draft","queued","published","failed"]),lA8=W.object({id:W.string(),subject:W.string(),status:pA8,excerpt:W.string(),created:W.string(),sentAt:W.string().optional(),url:W.string()}),iA8=W.object({newsletters:W.array(lA8),totalCount:W.number(),pagination:rD0.nullable()}),dA8=({newsletters:A,totalCount:Q,pageTitle:$,pagination:w,baseUrl:B="/newsletters"})=>{let X=$??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return yH(nA8,{children:[yH(E6,{title:X,description:Y},void 0,!1,void 0,this),yH("div",{className:"newsletter-list bg-theme",children:yH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[yH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?yH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):yH("div",{className:"space-y-4",children:A.map((Z)=>yH(C8,{href:Z.url,children:[yH($Y,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),yH(uY,{children:yH("div",{className:"flex items-center gap-3",children:[yH(eK,{status:Z.status},void 0,!1,void 0,this),yH("span",{className:"text-sm text-theme-muted",children:S9(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&&yH("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&&yH(Db,{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)},e0Q=W2({name:"newsletter-list",description:"Newsletter list page template",schema:iA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:dA8}});v0();zA();import{jsxDEV as u5,Fragment as tA8}from"preact/jsx-dev-runtime";var rA8=W.enum(["generating","draft","queued","published","failed"]),oA8=W.object({id:W.string(),title:W.string(),url:W.string()}),AAQ=W.object({id:W.string(),subject:W.string(),url:W.string()}),sA8=W.object({id:W.string(),subject:W.string(),status:rA8,content:W.string(),created:W.string(),updated:W.string(),sentAt:W.string().optional(),scheduledFor:W.string().optional(),sourceEntities:W.array(oA8).optional(),prevNewsletter:AAQ.nullable().optional(),nextNewsletter:AAQ.nullable().optional()}),aA8=({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 u5(tA8,{children:[u5(E6,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),u5("section",{className:"newsletter-detail-section",children:u5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:u5("div",{className:"max-w-3xl mx-auto",children:[u5(SL,{items:K},void 0,!1,void 0,this),u5("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),u5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[u5(eK,{status:Q},void 0,!1,void 0,this),u5("span",{children:[G,": ",S9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&u5("span",{children:["Scheduled for: ",S9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&u5(C8,{variant:"compact",className:"mb-8",children:[u5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),u5("ul",{className:"space-y-1",children:Y.map((D)=>u5("li",{children:u5("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),u5(BX,{markdown:$},void 0,!1,void 0,this),(Z??H)&&u5("nav",{className:"mt-12 pt-8 border-t border-theme",children:u5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?u5(C8,{href:Z.url,variant:"compact",children:[u5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),u5("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):u5("div",{},void 0,!1,void 0,this),H&&u5(C8,{href:H.url,variant:"compact",className:"md:text-right",children:[u5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),u5("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)},QAQ=W2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:sA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:aA8}});var zf0={name:"@brains/newsletter",version:"0.2.0-alpha.204",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 Q18=W.looseObject({}),$18=W.object({prompt:W.string().optional(),content:W.string().optional()});class Jf0 extends c6{entityType="newsletter";schema=Jo;adapter=s0Q;constructor(A={}){super("newsletter",zf0,A,Q18)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new QNA(this.logger,A)}getTemplates(){return{generation:t0Q,"newsletter-list":e0Q,"newsletter-detail":QAQ}}getDataSources(){return[new ANA(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:()=>A18(RzA,{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:sA($)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let $=$18.parse(Q),w=$.content?`Create an engaging newsletter based on this content:
10678
+ The goal is to build a relationship with readers through valuable, authentic content.`});v0();zA();import{jsxDEV as yH,Fragment as nA8}from"preact/jsx-dev-runtime";var pA8=W.enum(["generating","draft","queued","published","failed"]),lA8=W.object({id:W.string(),subject:W.string(),status:pA8,excerpt:W.string(),created:W.string(),sentAt:W.string().optional(),url:W.string()}),iA8=W.object({newsletters:W.array(lA8),totalCount:W.number(),pagination:rD0.nullable()}),dA8=({newsletters:A,totalCount:Q,pageTitle:$,pagination:w,baseUrl:B="/newsletters"})=>{let X=$??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return yH(nA8,{children:[yH(E6,{title:X,description:Y},void 0,!1,void 0,this),yH("div",{className:"newsletter-list bg-theme",children:yH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[yH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?yH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):yH("div",{className:"space-y-4",children:A.map((Z)=>yH(C8,{href:Z.url,children:[yH($Y,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),yH(uY,{children:yH("div",{className:"flex items-center gap-3",children:[yH(eK,{status:Z.status},void 0,!1,void 0,this),yH("span",{className:"text-sm text-theme-muted",children:S9(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&&yH("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&&yH(Db,{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)},e0Q=W2({name:"newsletter-list",description:"Newsletter list page template",schema:iA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:dA8}});v0();zA();import{jsxDEV as u5,Fragment as tA8}from"preact/jsx-dev-runtime";var rA8=W.enum(["generating","draft","queued","published","failed"]),oA8=W.object({id:W.string(),title:W.string(),url:W.string()}),AAQ=W.object({id:W.string(),subject:W.string(),url:W.string()}),sA8=W.object({id:W.string(),subject:W.string(),status:rA8,content:W.string(),created:W.string(),updated:W.string(),sentAt:W.string().optional(),scheduledFor:W.string().optional(),sourceEntities:W.array(oA8).optional(),prevNewsletter:AAQ.nullable().optional(),nextNewsletter:AAQ.nullable().optional()}),aA8=({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 u5(tA8,{children:[u5(E6,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),u5("section",{className:"newsletter-detail-section",children:u5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:u5("div",{className:"max-w-3xl mx-auto",children:[u5(SL,{items:K},void 0,!1,void 0,this),u5("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),u5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[u5(eK,{status:Q},void 0,!1,void 0,this),u5("span",{children:[G,": ",S9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&u5("span",{children:["Scheduled for: ",S9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&u5(C8,{variant:"compact",className:"mb-8",children:[u5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),u5("ul",{className:"space-y-1",children:Y.map((D)=>u5("li",{children:u5("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),u5(BX,{markdown:$},void 0,!1,void 0,this),(Z??H)&&u5("nav",{className:"mt-12 pt-8 border-t border-theme",children:u5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?u5(C8,{href:Z.url,variant:"compact",children:[u5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),u5("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):u5("div",{},void 0,!1,void 0,this),H&&u5(C8,{href:H.url,variant:"compact",className:"md:text-right",children:[u5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),u5("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)},QAQ=W2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:sA8,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:aA8}});var zf0={name:"@brains/newsletter",version:"0.2.0-alpha.206",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 Q18=W.looseObject({}),$18=W.object({prompt:W.string().optional(),content:W.string().optional()});class Jf0 extends c6{entityType="newsletter";schema=Jo;adapter=s0Q;constructor(A={}){super("newsletter",zf0,A,Q18)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new QNA(this.logger,A)}getTemplates(){return{generation:t0Q,"newsletter-list":e0Q,"newsletter-detail":QAQ}}getDataSources(){return[new ANA(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:()=>A18(RzA,{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:sA($)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let $=$18.parse(Q),w=$.content?`Create an engaging newsletter based on this content:
10679
10679
 
10680
10680
  ${$.content}`:$.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:w,templateName:"newsletter:generation"})})}}function Vf0(A={}){return new Jf0(A)}zA();v0();v0();var B18="https://api.buttondown.email/v1",X18=W.enum(["unactivated","regular","unsubscribed","already_subscribed"]),Y18=W.enum(["draft","about_to_send","scheduled","sent"]),$NA=W.looseObject({id:W.string(),email:W.string(),subscriber_type:X18,metadata:W.record(W.string(),W.string()).optional()}),$AQ=W.looseObject({id:W.string(),subject:W.string(),body:W.string().optional(),status:Y18,publish_date:W.string().optional()}),Z18=W.looseObject({results:W.array($NA),count:W.number()}),W18=W.looseObject({detail:W.string().optional(),message:W.string().optional(),code:W.string().optional()});class wNA extends Error{status;code;constructor(A,Q,$){super(A);this.name="ButtondownApiError",this.status=Q,this.code=$}}class iy{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let $=`${B18}${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=W18.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 wNA(`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 $NA.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch($){if($ instanceof wNA&&$.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 $NA.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 Z18.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"}),$AQ.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return $AQ.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}zA();v0();var wAQ=W.string().email({pattern:W.regexes.html5Email}),H18=W.object({email:wAQ.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)")}),K18=W.object({email:wAQ.describe("Email address to unsubscribe")}),U18=W.object({type:W.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:W.number().optional().describe("Maximum number of results")});function BAQ(A,Q,$){let w=new iy(Q,$);return[e8(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",H18,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 kY(sA(X))}}),e8(A,"unsubscribe","Unsubscribe an email address from the newsletter.",K18,async(B)=>{try{return await w.unsubscribe(B.email),d7({email:B.email},`Unsubscribed ${B.email} successfully`)}catch(X){return kY(sA(X))}}),e8(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",U18,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 kY(sA(X))}})]}async function XAQ(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=sA(X);return w.error("Failed to send newsletter for post",{postId:B.id,error:Y}),{success:!1,error:Y}}}var G18=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 Ff0 extends d6{constructor(A={}){super("buttondown",zf0,A,G18)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new iy({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:sA(w)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async($)=>{let w=await XAQ($.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 BAQ(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 Lf0(A={}){return new Ff0(A)}var D18=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 YAQ(A={}){let Q=D18.safeParse(A);if(!Q.success)throw new GN("newsletter",Q.error.issues.map((w)=>({path:w.path.map(String).join("."),code:w.code,message:w.message})));let $=Q.data;return[Vf0({}),Lf0({...$.apiKey!==void 0&&{apiKey:$.apiKey},...$.doubleOptIn!==void 0&&{doubleOptIn:$.doubleOptIn},...$.autoSendOnPublish!==void 0&&{autoSendOnPublish:$.autoSendOnPublish}})]}zA();v0();import{existsSync as k18,mkdirSync as O18,writeFileSync as f18}from"fs";import{join as hb}from"path";v0();var BNA=W.object({baseFolder:W.string().default("_obsidian")});function XNA(A){return typeof A==="object"&&A!==null}function w70(A){if(!XNA(A))return;let Q=A.def;return XNA(Q)?Q:void 0}function ZAQ(A){let Q=w70(A)?.type;return typeof Q==="string"?Q:void 0}function q18(A){return typeof A==="function"?A():A}function z18(A){let Q=A,$=!0,w=void 0,B=!1,X=!0;while(X){X=!1;let Z=w70(Q),H=ZAQ(Q);if(H==="optional"||H==="nullable"){$=!1,Q=Z?.innerType,X=!0;continue}if(H==="default")$=!1,B=!0,w=q18(Z?.defaultValue),Q=Z?.innerType,X=!0}let Y={inner:Q,required:$};if(B)Y.defaultValue=w;return Y}function J18(A){let $=w70(A)?.entries;if(!XNA($))return;let w=Object.values($);if(!w.every((B)=>typeof B==="string"))return;return w}function V18(A){let Q=w70(A),$=Q?.values;if(Array.isArray($))return $[0];return Q?.value}function WAQ(A){let Q=ZAQ(A);if(Q==="enum"){let $=J18(A);return $?{type:"enum",enumValues:$}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:V18(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 $=w70(A);return WAQ($?.out)}return{type:"unknown"}}function HAQ(A){let Q=[];for(let[$,w]of Object.entries(A.shape)){let{inner:B,required:X,defaultValue:Y}=z18(w),Z=WAQ(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 F18(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 KAQ(A,Q,$=""){let w=["---"];for(let B of Q){let X=F18(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(`
10681
10681
  `)}Np();var L18={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function I18(A){let Q={name:A.name,id:A.name,type:L18[A.type]};if(A.type==="enum"&&A.enumValues){let $={};A.enumValues.forEach((w,B)=>{$[String(B)]=w}),Q.options=$}return Q}function UAQ(A,Q){let $={filesPaths:A,fields:Q.map(I18)};return`---
10682
10682
  ${Ip($)}---
10683
- `}p2();Np();var N18=new Set(["entityType"]),_18={base:"Notes"},P18=new Set(["note"]);function b18(A){let Q=["file.name"];for(let $ of A)if(!N18.has($.name))Q.push($.name);return Q}function j18(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function GAQ(A,Q){let $=_18[A]??eyA(A),w=j18(Q),B=b18(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:[P18.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${$}.base`,content:Ip(Z),hasStatus:w}}function DAQ(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 Ip($)}function qAQ(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 Ip($)}var zAQ={name:"@brains/obsidian-vault",version:"0.2.0-alpha.204",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 x18={mkdir:O18,writeFile:f18,existsFile:k18},R18=W.object({entityTypes:W.array(W.string()).optional().describe("Entity types to generate templates for (default: all)")});class YNA extends d6{deps;constructor(A={},Q={}){super("obsidian-vault",zAQ,A,BNA);this.deps={...x18,...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.",R18,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let $=A.entityService.getEntityTypes(),w=Q?$.filter((F)=>Q.includes(F)):$,B=hb(A.dataDir,this.config.baseFolder),X=hb(B,"templates"),Y=hb(B,"fileClasses"),Z=hb(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 F of w){let _=A.entities.getEffectiveFrontmatterSchema(F);if(!_){this.logger.debug(`Skipping ${F}: no frontmatter schema`),K.push(F);continue}let j=HAQ(_),b=A.entities.getAdapter(F),k=b?.isSingleton===!0,v=UAQ(F,j);if(this.deps.writeFile(hb(Y,`${F}.md`),v),U.push(F),k){D.push(F),this.logger.debug(`Generated fileClass (singleton): ${F}`);continue}let R=b?.getBodyTemplate()??"",O=KAQ(F,j,R);this.deps.writeFile(hb(X,`${F}.md`),O),H.push(F);let g=GAQ(F,j),m=hb(Z,g.filename);if(!this.deps.existsFile(m))this.deps.writeFile(m,g.content),G.push(F),this.logger.debug(`Generated base: ${g.filename}`);if(g.hasStatus)q.push({entityType:F,fields:j});this.logger.debug(`Generated template + fileClass: ${F}`)}let V=DAQ(D);if(V){let F=hb(Z,"Settings.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,V),G.push("Settings"),this.logger.debug("Generated Settings.base")}let L=qAQ(q);if(L){let F=hb(Z,"Pipeline.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,L),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:$}),kY($ instanceof Error?$.message:"Unknown error")}}}function ZNA(A={},Q){return new YNA(A,Q)}K20();zA();v0();var JAQ={name:"@brains/notifications",version:"0.2.0-alpha.204",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"};K20();var C18=W.looseObject({defaultRecipient:pz0.optional()});class VAQ extends d6{constructor(A={}){super("notifications",JAQ,A,C18)}async onRegister(A){A.messaging.subscribe(Bh,async(Q)=>{let $=zAA.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:Nb0,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 If0(A={}){return new VAQ(A)}Kw();zA();zA();p2();b9();zA();v0();var Nf0=W.enum(["draft","active","archived"]),_f0=W.enum(["anchor","trusted","public"]),Pf0=W.enum(["agent-confirmed","manual"]),h18=W.enum(["draft","active","archived"]),E18=W.enum(["anchor","trusted","public"]),T18=W.enum(["agent-confirmed","manual"]),qI=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),Eb=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),WNA=W.object({event:W.string().min(1),target:W.string().min(1),operatorAction:W.boolean().optional(),label:Eb,description:Eb,operatorDescription:Eb}),HNA=W.object({id:W.string().min(1),title:W.string().min(1),prompt:Eb,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(WNA).default([])}),bf0=W.object({purpose:W.string().min(1),operatingRules:W.array(W.string().min(1)).default([]),initialState:W.string().min(1),states:W.array(HNA).min(1),finalStates:W.array(W.string().min(1)).min(1),nextPrompts:W.array(W.string().min(1)).default([])}),Vo=W.object({title:W.string(),status:Nf0.default("active"),audience:_f0.default("anchor"),trigger:qI.optional(),lifecycle:qI.optional(),once:W.boolean().optional(),starterText:qI.optional(),description:qI.optional(),starterPrompt:qI.optional(),completionMode:Pf0.default("agent-confirmed")}),FAQ=W.object({title:W.string(),status:Nf0,audience:_f0,trigger:qI.optional(),lifecycle:qI.optional(),once:W.boolean().optional(),starterText:qI.optional(),description:qI.optional(),starterPrompt:qI.optional(),completionMode:Pf0}),y18=W.object({title:W.string(),status:h18,audience:E18,trigger:Eb.optional(),lifecycle:Eb.optional(),once:W.boolean().optional(),starterText:Eb.optional(),description:Eb.optional(),starterPrompt:Eb.optional(),completionMode:T18}),Fo=U6.extend({entityType:W.literal("playbook"),metadata:y18});class jf0 extends P${constructor(){super(bf0,{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:KNA,parser:UNA},{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:g18,parser:S18},{key:"label",label:"Label",type:"custom",formatter:KNA,parser:UNA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:KNA,parser:UNA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var B70=new jf0;function KNA(A){return typeof A==="string"?A:""}function UNA(A){let Q=A.trim();return Q.length>0?Q:void 0}function g18(A){return typeof A==="boolean"?String(A):""}function S18(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function GNA(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 m18(A,$))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Lo(A){let Q=GNA(A);if(!Q.valid)throw Error(Q.errors.join(`
10683
+ `}p2();Np();var N18=new Set(["entityType"]),_18={base:"Notes"},P18=new Set(["note"]);function b18(A){let Q=["file.name"];for(let $ of A)if(!N18.has($.name))Q.push($.name);return Q}function j18(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function GAQ(A,Q){let $=_18[A]??eyA(A),w=j18(Q),B=b18(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:[P18.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${$}.base`,content:Ip(Z),hasStatus:w}}function DAQ(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 Ip($)}function qAQ(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 Ip($)}var zAQ={name:"@brains/obsidian-vault",version:"0.2.0-alpha.206",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 x18={mkdir:O18,writeFile:f18,existsFile:k18},R18=W.object({entityTypes:W.array(W.string()).optional().describe("Entity types to generate templates for (default: all)")});class YNA extends d6{deps;constructor(A={},Q={}){super("obsidian-vault",zAQ,A,BNA);this.deps={...x18,...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.",R18,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let $=A.entityService.getEntityTypes(),w=Q?$.filter((F)=>Q.includes(F)):$,B=hb(A.dataDir,this.config.baseFolder),X=hb(B,"templates"),Y=hb(B,"fileClasses"),Z=hb(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 F of w){let _=A.entities.getEffectiveFrontmatterSchema(F);if(!_){this.logger.debug(`Skipping ${F}: no frontmatter schema`),K.push(F);continue}let j=HAQ(_),b=A.entities.getAdapter(F),k=b?.isSingleton===!0,v=UAQ(F,j);if(this.deps.writeFile(hb(Y,`${F}.md`),v),U.push(F),k){D.push(F),this.logger.debug(`Generated fileClass (singleton): ${F}`);continue}let R=b?.getBodyTemplate()??"",O=KAQ(F,j,R);this.deps.writeFile(hb(X,`${F}.md`),O),H.push(F);let g=GAQ(F,j),m=hb(Z,g.filename);if(!this.deps.existsFile(m))this.deps.writeFile(m,g.content),G.push(F),this.logger.debug(`Generated base: ${g.filename}`);if(g.hasStatus)q.push({entityType:F,fields:j});this.logger.debug(`Generated template + fileClass: ${F}`)}let V=DAQ(D);if(V){let F=hb(Z,"Settings.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,V),G.push("Settings"),this.logger.debug("Generated Settings.base")}let L=qAQ(q);if(L){let F=hb(Z,"Pipeline.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,L),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:$}),kY($ instanceof Error?$.message:"Unknown error")}}}function ZNA(A={},Q){return new YNA(A,Q)}K20();zA();v0();var JAQ={name:"@brains/notifications",version:"0.2.0-alpha.206",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"};K20();var C18=W.looseObject({defaultRecipient:pz0.optional()});class VAQ extends d6{constructor(A={}){super("notifications",JAQ,A,C18)}async onRegister(A){A.messaging.subscribe(Bh,async(Q)=>{let $=zAA.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:Nb0,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 If0(A={}){return new VAQ(A)}Kw();zA();zA();p2();b9();zA();v0();var Nf0=W.enum(["draft","active","archived"]),_f0=W.enum(["anchor","trusted","public"]),Pf0=W.enum(["agent-confirmed","manual"]),h18=W.enum(["draft","active","archived"]),E18=W.enum(["anchor","trusted","public"]),T18=W.enum(["agent-confirmed","manual"]),qI=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),Eb=W.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,W.string().min(1).optional()),WNA=W.object({event:W.string().min(1),target:W.string().min(1),operatorAction:W.boolean().optional(),label:Eb,description:Eb,operatorDescription:Eb}),HNA=W.object({id:W.string().min(1),title:W.string().min(1),prompt:Eb,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(WNA).default([])}),bf0=W.object({purpose:W.string().min(1),operatingRules:W.array(W.string().min(1)).default([]),initialState:W.string().min(1),states:W.array(HNA).min(1),finalStates:W.array(W.string().min(1)).min(1),nextPrompts:W.array(W.string().min(1)).default([])}),Vo=W.object({title:W.string(),status:Nf0.default("active"),audience:_f0.default("anchor"),trigger:qI.optional(),lifecycle:qI.optional(),once:W.boolean().optional(),starterText:qI.optional(),description:qI.optional(),starterPrompt:qI.optional(),completionMode:Pf0.default("agent-confirmed")}),FAQ=W.object({title:W.string(),status:Nf0,audience:_f0,trigger:qI.optional(),lifecycle:qI.optional(),once:W.boolean().optional(),starterText:qI.optional(),description:qI.optional(),starterPrompt:qI.optional(),completionMode:Pf0}),y18=W.object({title:W.string(),status:h18,audience:E18,trigger:Eb.optional(),lifecycle:Eb.optional(),once:W.boolean().optional(),starterText:Eb.optional(),description:Eb.optional(),starterPrompt:Eb.optional(),completionMode:T18}),Fo=U6.extend({entityType:W.literal("playbook"),metadata:y18});class jf0 extends P${constructor(){super(bf0,{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:KNA,parser:UNA},{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:g18,parser:S18},{key:"label",label:"Label",type:"custom",formatter:KNA,parser:UNA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:KNA,parser:UNA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var B70=new jf0;function KNA(A){return typeof A==="string"?A:""}function UNA(A){let Q=A.trim();return Q.length>0?Q:void 0}function g18(A){return typeof A==="boolean"?String(A):""}function S18(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function GNA(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 m18(A,$))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Lo(A){let Q=GNA(A);if(!Q.valid)throw Error(Q.errors.join(`
10684
10684
  `))}function m18(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 kf0 extends zQ{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:Fo,frontmatterSchema:Vo})}createPlaybookContent(A,Q){return this.buildMarkdown(B70.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,Vo),$=this.extractBody(A).trim(),w=u18($)?c18($):B70.parse($);return Lo(w),{frontmatter:Vo.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 dy=new kf0;function u18(A){return/^##\s+Steps\s*$/im.test(A)}function c18(A){let Q=p18(DNA(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:l18(A,"Purpose"),operatingRules:LAQ(A,"Operating Rules"),initialState:Q[0]?.id??"",states:$,finalStates:[Q.at(-1)?.id??""],nextPrompts:LAQ(A,"Next Prompts")}}function p18(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(`
10685
10685
  `);return{title:w.title,id:O1(w.title),...IAQ(B,"Say")?{prompt:IAQ(B,"Say")}:{},requiredDetails:Mf0(B,"Required details"),instructions:Mf0(B,"To do"),doneWhen:Mf0(B,"Done when"),choices:i18(B,"Choices"),...NAQ(B)?{skip:NAQ(B)}:{}}})}function DNA(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(`
10686
10686
  `).trim()}function l18(A,Q){return DNA(A,Q).split(/\r?\n/).map(($)=>$.trim()).filter(($)=>$.length>0&&!$.startsWith("#")).join(`
10687
10687
  `).trim()}function LAQ(A,Q){return _AQ(DNA(A,Q))}function IAQ(A,Q){return new RegExp(`^${n18(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function Mf0(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 _AQ(B.join(`
10688
- `))}function i18(A,Q){return Mf0(A,Q).map(d18)}function d18(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 NAQ(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 _AQ(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function n18(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}v0();var Of0=W.object({}).catchall(W.unknown()).transform(()=>({}));var ff0={name:"@brains/playbooks",version:"0.2.0-alpha.204",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 o18="playbook";class qNA extends c6{entityType=o18;schema=Fo;adapter=dy;constructor(A={}){super("playbook",ff0,A,Of0)}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 zNA(A={}){return new qNA(A)}Kw();zA();v0();yZ();Y20();function xf0(A,Q){return A.length===Q.length&&A.every(($,w)=>$===Q[w])}function JNA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function Rf0(A,Q){return Q.gateVerdicts.some(($)=>$.stateId===A.id&&xf0($.goal,A.doneWhen)&&$.met)}function s18(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,...JNA(w,X.event)?{guard:()=>Rf0(w,$)}:{}}]))}}]}))})}function VNA(A,Q){let $=s18(Q.playbookId,A,Q);return F2.createActor($,{snapshot:$.resolveState({value:Q.currentState})})}function a18(A,Q,$){let w=VNA(Q,A);w.start();let B=w.getSnapshot().can({type:$});return w.stop(),B}function Io(A,Q,$){return $.transitions.filter((w)=>a18(A,Q,w.event))}function X70(A,Q,$){let w=new Set(Io(A,Q,$).map((B)=>`${B.event}\x00${B.target}`));return $.transitions.filter((B)=>!w.has(`${B.event}\x00${B.target}`))}function PAQ(A,Q){return A.evidence.filter(($)=>!$.stateId||$.stateId===Q)}function ny(A,Q){return A.states.find(($)=>$.id===Q)}function ry(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function bAQ(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let $=A.gateVerdicts.find((w)=>w.stateId===Q.id&&xf0(w.goal,Q.doneWhen));if(!$)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return $.met?`- Met: ${$.reason}`:`- Not yet met: ${$.reason}`}function jAQ(A,Q,$){let w=Io(A,Q,$),B=w.filter((H)=>H.operatorAction!==!0),X=w.filter((H)=>H.operatorAction===!0),Y=X70(A,Q,$),Z=A.gateVerdicts.find((H)=>H.stateId===$.id&&xf0(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)=>ry(H)):["- none"],"Available operator actions:",...X.length>0?X.map((H)=>ry(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>ry(H)):["- none"]].join(`
10688
+ `))}function i18(A,Q){return Mf0(A,Q).map(d18)}function d18(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 NAQ(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 _AQ(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function n18(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}v0();var Of0=W.object({}).catchall(W.unknown()).transform(()=>({}));var ff0={name:"@brains/playbooks",version:"0.2.0-alpha.206",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 o18="playbook";class qNA extends c6{entityType=o18;schema=Fo;adapter=dy;constructor(A={}){super("playbook",ff0,A,Of0)}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 zNA(A={}){return new qNA(A)}Kw();zA();v0();yZ();Y20();function xf0(A,Q){return A.length===Q.length&&A.every(($,w)=>$===Q[w])}function JNA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function Rf0(A,Q){return Q.gateVerdicts.some(($)=>$.stateId===A.id&&xf0($.goal,A.doneWhen)&&$.met)}function s18(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,...JNA(w,X.event)?{guard:()=>Rf0(w,$)}:{}}]))}}]}))})}function VNA(A,Q){let $=s18(Q.playbookId,A,Q);return F2.createActor($,{snapshot:$.resolveState({value:Q.currentState})})}function a18(A,Q,$){let w=VNA(Q,A);w.start();let B=w.getSnapshot().can({type:$});return w.stop(),B}function Io(A,Q,$){return $.transitions.filter((w)=>a18(A,Q,w.event))}function X70(A,Q,$){let w=new Set(Io(A,Q,$).map((B)=>`${B.event}\x00${B.target}`));return $.transitions.filter((B)=>!w.has(`${B.event}\x00${B.target}`))}function PAQ(A,Q){return A.evidence.filter(($)=>!$.stateId||$.stateId===Q)}function ny(A,Q){return A.states.find(($)=>$.id===Q)}function ry(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function bAQ(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let $=A.gateVerdicts.find((w)=>w.stateId===Q.id&&xf0(w.goal,Q.doneWhen));if(!$)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return $.met?`- Met: ${$.reason}`:`- Not yet met: ${$.reason}`}function jAQ(A,Q,$){let w=Io(A,Q,$),B=w.filter((H)=>H.operatorAction!==!0),X=w.filter((H)=>H.operatorAction===!0),Y=X70(A,Q,$),Z=A.gateVerdicts.find((H)=>H.stateId===$.id&&xf0(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)=>ry(H)):["- none"],"Available operator actions:",...X.length>0?X.map((H)=>ry(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>ry(H)):["- none"]].join(`
10689
10689
  `)}function MAQ(A){let{run:Q,body:$,state:w,playbookTitle:B}=A,X=Io(Q,$,w),Y=X.filter((F)=>F.operatorAction!==!0),Z=X.filter((F)=>F.operatorAction===!0),H=X70(Q,$,w),K=Y.map((F)=>ry(F)).join(`
10690
10690
  `),U=Z.map((F)=>ry(F)).join(`
10691
10691
  `),G=H.map((F)=>ry(F)).join(`
@@ -10759,9 +10759,9 @@ ${Object.entries(A).map(([$,w])=>`- ${$}: playbookId=${w.playbookId}, trigger=${
10759
10759
  ${A.guidance}`:B}}function gAQ(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:G28(Q.data)}))}}function G28(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function D28(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 q28(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function SAQ(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function mAQ(A,Q){let $=A.filter(Q),w=$.filter((B)=>B.status==="active"||B.status==="offered");return PNA(w)??PNA($)}function PNA(A){return[...A].sort((Q,$)=>($.completedAt??$.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function z28(A){return{async evaluate(Q){let $=Q.goal.join(`
10760
10760
  `),w=await A.entityService.search({query:$,options:{limit:8,excludeTypes:["playbook"],visibilityScope:e5("anchor")}}),B=J28(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:Z28});return X}}}function J28(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)=>V28(w+1,$)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map(($,w)=>F28(w+1,$)):["No relevant KB excerpts found."]].join(`
10761
10761
  `)}function V28(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${cAQ(Q.data)}`}function F28(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${pAQ(Q.entity.content,1200)}`,`Metadata: ${cAQ(Q.entity.metadata)}`].join(`
10762
- `)}function cAQ(A){try{return pAQ(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function pAQ(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var L28={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function jNA(A={},Q={}){return new bNA(A,Q)}Kw();zA();v0();import{readFile as N28}from"fs/promises";import{join as _28}from"path";var lAQ={name:"@brains/rover-onboarding",version:"0.2.0-alpha.204",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 P28=W.object({enabled:W.boolean().default(!1)}).strict(),iAQ=[{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 dAQ extends d6{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",lAQ,A,P28)}async onReady(A){if(!this.config.enabled)return;for(let Q of iAQ)await this.seedPlaybookIfMissing(A,Q);for(let Q of iAQ){if(!Q.starter)continue;await A.messaging.send({type:uS,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let w=await N28(_28(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 dAQ(A)}zA();v0();v0();zA();var MNA=W.enum(["new","planned","in-progress","done","declined"]),kNA=W.enum(["low","medium","high","critical"]),b28=W.enum(["new","planned","in-progress","done","declined"]),j28=W.enum(["low","medium","high","critical"]),Y70=W.object({title:W.string(),status:MNA,priority:kNA.default("medium"),requested:W.number().int().default(1),declinedReason:W.string().optional()}),M28=W.object({title:W.string(),status:MNA,priority:kNA,requested:W.number().int(),slug:W.string()}),k28=W.object({title:W.string(),status:b28,priority:j28,requested:W.number().int(),slug:W.string()}),Z70=U6.extend({entityType:W.literal("wish"),metadata:k28});v0();var ONA=W.object({}).catchall(W.unknown()).transform(()=>({}));zA();p2();class W70 extends zQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Z70,frontmatterSchema:Y70})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Y70);return{frontmatter:Y70.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 rAQ=new W70;p2();p2();async function oAQ(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 Ef0{logger;context;adapter=new W70;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 oAQ({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 sAQ={critical:0,high:1,medium:2,low:3};function aAQ(A){A.sort((Q,$)=>{let w=$.metadata.requested-Q.metadata.requested;if(w!==0)return w;return sAQ[Q.metadata.priority]-sAQ[$.metadata.priority]})}var tAQ={name:"@brains/wishlist",version:"0.2.0-alpha.204",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 f28=W.object({items:W.array(W.object({name:W.string(),count:W.number()}))}),x28="wish";class eAQ extends c6{entityType=x28;schema=Z70;adapter=rAQ;constructor(A={}){super("wishlist",tAQ,A,ONA)}async interceptCreate(A,Q,$){let w=await new Ef0(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}=f28.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 aAQ($),{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 Ef0(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 R28(A={}){return new eAQ(A)}var Tf0=R28;zA();zA();v0();var H70=W.object({title:W.string(),target:W.string()}),A1Q=W.object({title:W.string(),target:W.string(),slug:W.string().optional()}),K70=U6.extend({entityType:W.literal("prompt"),metadata:A1Q});zA();p2();class fNA extends zQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:K70,frontmatterSchema:H70})}toMarkdown(A){let Q=this.extractBody(A.content),$=this.parseFrontMatter(A.content,H70);return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,H70),$=O1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:$}}}}var xNA=new fNA;var Q1Q={name:"@brains/prompt",version:"0.2.0-alpha.204",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 C28="prompt";class RNA extends c6{entityType=C28;schema=K70;adapter=xNA;constructor(){super("prompt",Q1Q,{},MY)}getEntityTypeConfig(){return{embeddable:!1}}}function sy(){return new RNA}zA();v0();v0();class yf0{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=E28.parse(await w.json());return{photos:B.results.map(T28),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 h28=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()}),E28=W.looseObject({total:W.number().int().nonnegative(),total_pages:W.number().int().nonnegative(),results:W.array(h28)});function T28(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}}v0();async function gf0(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 y28={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")},g28={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")},S28=W.object({query:W.string(),perPage:W.number().min(1).max(30).default(10),page:W.number().min(1).default(1)}),m28=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 $1Q(A,Q){return[u28(A,Q),c28(A,Q)]}function u28(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:y28,visibility:"anchor",sideEffects:"none",handler:async($)=>{let w=S28.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 c28(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:g28,visibility:"anchor",sideEffects:"external",handler:async($)=>{let w=m28.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,V={photographerName:Y,photographerUrl:Z,sourceUrl:H},L=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(L[0]){let j={imageEntityId:L[0].id,alreadyExisted:!0,attribution:V};if(D&&q)j.coverSet=await gf0(Q.entityService,D,q,L[0].id);return{success:!0,data:j}}let F=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:V,jobId:F,status:"generating"};if(D&&q)_.coverSet=!1;return{success:!0,data:_}}}}zA();v0();lZ();var p28=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 vNA extends H8{deps;constructor(A,Q){super(A,{schema:p28,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=KG.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 gf0(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}}}lZ();var w1Q={name:"@brains/stock-photo",version:"0.2.0-alpha.204",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 i28=W.object({provider:W.enum(["unsplash"]).default("unsplash"),apiKey:W.string().optional().describe("Stock photo provider API key")});class CNA extends d6{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",w1Q,A,i28);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=$1Q(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??yq,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new vNA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??yq}))}createProvider(){return new yf0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function hNA(A={},Q={}){return new CNA(A,Q)}zA();v0();zA();zA();v0();var B1Q=W.enum(["ai","foundation","work"]),X1Q=W.object({suffix:B1Q,title:W.string(),body:W.string(),linkLabel:W.string(),linkHref:W.string()}),U70=W.object({eyebrow:W.string(),headline:W.string(),cards:W.array(X1Q).min(1)}),ENA=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),d28=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),G70=U6.extend({entityType:W.literal("ecosystem-section"),metadata:d28});class Y1Q extends zQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:G70,frontmatterSchema:ENA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var TNA=new Y1Q;v0();function n28(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function yNA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function D70(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function Sf0(A){let Q=n28(A),w=yNA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return U70.parse({eyebrow:yNA(Q,"Eyebrow"),headline:yNA(Q,"Headline"),cards:w.map((B)=>({suffix:D70(B,"Suffix"),title:D70(B,"Title"),body:D70(B,"Body"),linkLabel:D70(B,"Link Label"),linkHref:D70(B,"Link Href")}))})}function Z1Q(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(`
10762
+ `)}function cAQ(A){try{return pAQ(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function pAQ(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var L28={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function jNA(A={},Q={}){return new bNA(A,Q)}Kw();zA();v0();import{readFile as N28}from"fs/promises";import{join as _28}from"path";var lAQ={name:"@brains/rover-onboarding",version:"0.2.0-alpha.206",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 P28=W.object({enabled:W.boolean().default(!1)}).strict(),iAQ=[{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 dAQ extends d6{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",lAQ,A,P28)}async onReady(A){if(!this.config.enabled)return;for(let Q of iAQ)await this.seedPlaybookIfMissing(A,Q);for(let Q of iAQ){if(!Q.starter)continue;await A.messaging.send({type:uS,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let w=await N28(_28(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 dAQ(A)}zA();v0();v0();zA();var MNA=W.enum(["new","planned","in-progress","done","declined"]),kNA=W.enum(["low","medium","high","critical"]),b28=W.enum(["new","planned","in-progress","done","declined"]),j28=W.enum(["low","medium","high","critical"]),Y70=W.object({title:W.string(),status:MNA,priority:kNA.default("medium"),requested:W.number().int().default(1),declinedReason:W.string().optional()}),M28=W.object({title:W.string(),status:MNA,priority:kNA,requested:W.number().int(),slug:W.string()}),k28=W.object({title:W.string(),status:b28,priority:j28,requested:W.number().int(),slug:W.string()}),Z70=U6.extend({entityType:W.literal("wish"),metadata:k28});v0();var ONA=W.object({}).catchall(W.unknown()).transform(()=>({}));zA();p2();class W70 extends zQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Z70,frontmatterSchema:Y70})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Y70);return{frontmatter:Y70.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 rAQ=new W70;p2();p2();async function oAQ(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 Ef0{logger;context;adapter=new W70;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 oAQ({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 sAQ={critical:0,high:1,medium:2,low:3};function aAQ(A){A.sort((Q,$)=>{let w=$.metadata.requested-Q.metadata.requested;if(w!==0)return w;return sAQ[Q.metadata.priority]-sAQ[$.metadata.priority]})}var tAQ={name:"@brains/wishlist",version:"0.2.0-alpha.206",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 f28=W.object({items:W.array(W.object({name:W.string(),count:W.number()}))}),x28="wish";class eAQ extends c6{entityType=x28;schema=Z70;adapter=rAQ;constructor(A={}){super("wishlist",tAQ,A,ONA)}async interceptCreate(A,Q,$){let w=await new Ef0(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}=f28.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 aAQ($),{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 Ef0(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 R28(A={}){return new eAQ(A)}var Tf0=R28;zA();zA();v0();var H70=W.object({title:W.string(),target:W.string()}),A1Q=W.object({title:W.string(),target:W.string(),slug:W.string().optional()}),K70=U6.extend({entityType:W.literal("prompt"),metadata:A1Q});zA();p2();class fNA extends zQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:K70,frontmatterSchema:H70})}toMarkdown(A){let Q=this.extractBody(A.content),$=this.parseFrontMatter(A.content,H70);return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,H70),$=O1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:$}}}}var xNA=new fNA;var Q1Q={name:"@brains/prompt",version:"0.2.0-alpha.206",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 C28="prompt";class RNA extends c6{entityType=C28;schema=K70;adapter=xNA;constructor(){super("prompt",Q1Q,{},MY)}getEntityTypeConfig(){return{embeddable:!1}}}function sy(){return new RNA}zA();v0();v0();class yf0{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=E28.parse(await w.json());return{photos:B.results.map(T28),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 h28=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()}),E28=W.looseObject({total:W.number().int().nonnegative(),total_pages:W.number().int().nonnegative(),results:W.array(h28)});function T28(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}}v0();async function gf0(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 y28={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")},g28={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")},S28=W.object({query:W.string(),perPage:W.number().min(1).max(30).default(10),page:W.number().min(1).default(1)}),m28=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 $1Q(A,Q){return[u28(A,Q),c28(A,Q)]}function u28(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:y28,visibility:"anchor",sideEffects:"none",handler:async($)=>{let w=S28.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 c28(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:g28,visibility:"anchor",sideEffects:"external",handler:async($)=>{let w=m28.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,V={photographerName:Y,photographerUrl:Z,sourceUrl:H},L=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(L[0]){let j={imageEntityId:L[0].id,alreadyExisted:!0,attribution:V};if(D&&q)j.coverSet=await gf0(Q.entityService,D,q,L[0].id);return{success:!0,data:j}}let F=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:V,jobId:F,status:"generating"};if(D&&q)_.coverSet=!1;return{success:!0,data:_}}}}zA();v0();lZ();var p28=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 vNA extends H8{deps;constructor(A,Q){super(A,{schema:p28,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=KG.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 gf0(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}}}lZ();var w1Q={name:"@brains/stock-photo",version:"0.2.0-alpha.206",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 i28=W.object({provider:W.enum(["unsplash"]).default("unsplash"),apiKey:W.string().optional().describe("Stock photo provider API key")});class CNA extends d6{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",w1Q,A,i28);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=$1Q(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??yq,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new vNA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??yq}))}createProvider(){return new yf0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function hNA(A={},Q={}){return new CNA(A,Q)}zA();v0();zA();zA();v0();var B1Q=W.enum(["ai","foundation","work"]),X1Q=W.object({suffix:B1Q,title:W.string(),body:W.string(),linkLabel:W.string(),linkHref:W.string()}),U70=W.object({eyebrow:W.string(),headline:W.string(),cards:W.array(X1Q).min(1)}),ENA=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),d28=W.object({title:W.string(),slug:W.string(),status:W.enum(["draft","published"])}),G70=U6.extend({entityType:W.literal("ecosystem-section"),metadata:d28});class Y1Q extends zQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:G70,frontmatterSchema:ENA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var TNA=new Y1Q;v0();function n28(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function yNA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function D70(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function Sf0(A){let Q=n28(A),w=yNA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return U70.parse({eyebrow:yNA(Q,"Eyebrow"),headline:yNA(Q,"Headline"),cards:w.map((B)=>({suffix:D70(B,"Suffix"),title:D70(B,"Title"),body:D70(B,"Body"),linkLabel:D70(B,"Link Label"),linkHref:D70(B,"Link Href")}))})}function Z1Q(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(`
10763
10763
  `)}var r28=W.looseObject({query:W.object({id:W.string().optional()}).optional()});class mf0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,$){let B=r28.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(Sf0(X.content))}}import{jsxDEV as a28}from"preact/jsx-dev-runtime";var o28="px-6 md:px-10 xl:px-20",s28=`${o28} relative z-[1]`,W1Q=({id:A,className:Q,children:$})=>a28("section",{id:A,className:wQ(s28,Q),children:$},void 0,!1,void 0,this);import{jsxDEV as uf0}from"preact/jsx-dev-runtime";var t28=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),H1Q=({name:A="rizom",brandSuffix:Q,className:$,dotClassName:w,suffixClassName:B})=>{let X=t28.get(Q);return uf0("span",{className:wQ("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",$),children:[uf0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),uf0("span",{className:wQ(X??"text-accent",w),children:"."},void 0,!1,void 0,this),uf0("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 gNA}from"preact";import{jsxDEV as q70}from"preact/jsx-dev-runtime";var e28=/(\*[^*]+\*)/;function K1Q(A,Q){let $=A.split(`
10764
- `);return q70(gNA,{children:$.map((w,B)=>q70(gNA,{children:[B>0&&q70("br",{},void 0,!1,void 0,this),w.split(e28).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return q70("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return q70(gNA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as XU,Fragment as KQ8}from"preact/jsx-dev-runtime";var AQ8="italic text-accent font-normal",QQ8="You are here",$Q8={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},wQ8={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},BQ8={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},XQ8="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",YQ8="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",ZQ8="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",WQ8="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",HQ8=({card:A})=>{let Q=A.linkLabel===QQ8,$=A.linkHref.trim().length===0,w=XU(KQ8,{children:[XU(H1Q,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),XU("span",{className:`${XQ8} ${$Q8[A.suffix]}`,children:A.title},void 0,!1,void 0,this),XU("p",{className:YQ8,children:A.body},void 0,!1,void 0,this),Q?XU("span",{className:WQ8,children:A.linkLabel},void 0,!1,void 0,this):XU("span",{className:ZQ8,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?wQ8[A.suffix]:"border-white/10"}`;return Q||$?XU("div",{className:B,children:w},void 0,!1,void 0,this):XU("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${BQ8[A.suffix]}`,children:w},void 0,!1,void 0,this)},U1Q=({eyebrow:A,headline:Q,cards:$})=>XU(W1Q,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[XU("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[XU("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),XU("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:K1Q(Q,AQ8)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),XU("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)=>XU(HQ8,{card:w},w.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);zA();var SNA=W2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:U70,formatter:{parse:Sf0,format:Z1Q},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:U1Q}});var G1Q={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.204",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 GQ8=W.object({}).catchall(W.unknown()).transform(()=>({})),DQ8="ecosystem-section";class mNA extends c6{entityType=DQ8;schema=G70;adapter=TNA;constructor(A={}){super("rizom-ecosystem",G1Q,A,GQ8)}getTemplates(){return{ecosystem:SNA}}getDataSources(){return[new mf0]}}function ay(A={}){return new mNA(A)}zA();zA();p2();v0();b9();v0();zA();var bw="agent",D1Q="agent-discovery";var q1Q="agent-network",z1Q="AgentNetworkWidget",J1Q="agent-proximity",V1Q="AgentProximityWidget",z70="agent-discovery:entities",cf0="agent-discovery:proximity-map",uNA="proximity-map",cNA="agent-list",pNA="agent-detail",u9="skill",F1Q="skill",pf0="skill-derivation",L1Q="skill:project",I1Q="skill-derivation",N1Q="skill:skill-derivation",_1Q="skills";var lf0=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),Nx=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),P1Q=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),qQ8=W.enum(["professional","team","collective"]),eJ=W.object({name:W.string(),kind:qQ8,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:Nx,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")}),b1Q=W.object({name:W.string(),url:W.string().url(),status:Nx,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()}),zQ8=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:P1Q,discoveredAt:W.string().datetime(),introducedBy:W.array(W.string()).optional(),hops:W.number().int().min(2).optional()}),JQ8=W.object({name:W.string(),url:W.string().url(),status:P1Q,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()}),J70=MB.extend({entityType:W.literal(bw),metadata:b1Q}),VQ8=U6.extend({entityType:W.literal(bw),metadata:JQ8}),V70=VQ8.extend({frontmatter:zQ8,about:W.string(),skills:W.array(lf0),notes:W.string()}),FQ8=V70.extend({url:W.string().optional(),typeLabel:W.string().optional()}),LQ8=V70.extend({url:W.string(),typeLabel:W.string()});v0();var IQ8=W.array(lf0);function j1Q(A){let Q=IQ8.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(`
10764
+ `);return q70(gNA,{children:$.map((w,B)=>q70(gNA,{children:[B>0&&q70("br",{},void 0,!1,void 0,this),w.split(e28).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return q70("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return q70(gNA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as XU,Fragment as KQ8}from"preact/jsx-dev-runtime";var AQ8="italic text-accent font-normal",QQ8="You are here",$Q8={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},wQ8={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},BQ8={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},XQ8="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",YQ8="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",ZQ8="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",WQ8="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",HQ8=({card:A})=>{let Q=A.linkLabel===QQ8,$=A.linkHref.trim().length===0,w=XU(KQ8,{children:[XU(H1Q,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),XU("span",{className:`${XQ8} ${$Q8[A.suffix]}`,children:A.title},void 0,!1,void 0,this),XU("p",{className:YQ8,children:A.body},void 0,!1,void 0,this),Q?XU("span",{className:WQ8,children:A.linkLabel},void 0,!1,void 0,this):XU("span",{className:ZQ8,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?wQ8[A.suffix]:"border-white/10"}`;return Q||$?XU("div",{className:B,children:w},void 0,!1,void 0,this):XU("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${BQ8[A.suffix]}`,children:w},void 0,!1,void 0,this)},U1Q=({eyebrow:A,headline:Q,cards:$})=>XU(W1Q,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[XU("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[XU("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),XU("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:K1Q(Q,AQ8)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),XU("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)=>XU(HQ8,{card:w},w.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);zA();var SNA=W2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:U70,formatter:{parse:Sf0,format:Z1Q},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:U1Q}});var G1Q={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.206",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 GQ8=W.object({}).catchall(W.unknown()).transform(()=>({})),DQ8="ecosystem-section";class mNA extends c6{entityType=DQ8;schema=G70;adapter=TNA;constructor(A={}){super("rizom-ecosystem",G1Q,A,GQ8)}getTemplates(){return{ecosystem:SNA}}getDataSources(){return[new mf0]}}function ay(A={}){return new mNA(A)}zA();zA();p2();v0();b9();v0();zA();var bw="agent",D1Q="agent-discovery";var q1Q="agent-network",z1Q="AgentNetworkWidget",J1Q="agent-proximity",V1Q="AgentProximityWidget",z70="agent-discovery:entities",cf0="agent-discovery:proximity-map",uNA="proximity-map",cNA="agent-list",pNA="agent-detail",u9="skill",F1Q="skill",pf0="skill-derivation",L1Q="skill:project",I1Q="skill-derivation",N1Q="skill:skill-derivation",_1Q="skills";var lf0=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),Nx=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),P1Q=W.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),qQ8=W.enum(["professional","team","collective"]),eJ=W.object({name:W.string(),kind:qQ8,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:Nx,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")}),b1Q=W.object({name:W.string(),url:W.string().url(),status:Nx,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()}),zQ8=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:P1Q,discoveredAt:W.string().datetime(),introducedBy:W.array(W.string()).optional(),hops:W.number().int().min(2).optional()}),JQ8=W.object({name:W.string(),url:W.string().url(),status:P1Q,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()}),J70=MB.extend({entityType:W.literal(bw),metadata:b1Q}),VQ8=U6.extend({entityType:W.literal(bw),metadata:JQ8}),V70=VQ8.extend({frontmatter:zQ8,about:W.string(),skills:W.array(lf0),notes:W.string()}),FQ8=V70.extend({url:W.string().optional(),typeLabel:W.string().optional()}),LQ8=V70.extend({url:W.string(),typeLabel:W.string()});v0();var IQ8=W.array(lf0);function j1Q(A){let Q=IQ8.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(`
10765
10765
  `)}function M1Q(A){if(!A.trim())return[];let Q=[];for(let $ of A.split(`
10766
10766
  `)){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 NQ8=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),_Q8=W.object({about:W.string(),skills:W.array(NQ8),notes:W.string()}),k1Q=new P$(_Q8,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:j1Q,parser:M1Q},{key:"notes",label:"Notes",type:"string"}]});class L4 extends zQ{constructor(){super({entityType:bw,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:J70,frontmatterSchema:eJ,publishedStatuses:["approved"]})}fromMarkdown(A){let Q=this.parseFrontMatter(A,eJ),$=aS(Q.url);return{content:A,entityType:bw,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:Nx.parse(A.status),discoveredAt:A.discoveredAt,...A.introducedBy?.length&&{introducedBy:A.introducedBy},...A.hops!==void 0&&{hops:A.hops}},$=k1Q.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 $=k1Q.parse(Q);return{about:$.about,skills:$.skills,notes:$.notes}}catch{return{about:"",skills:[],notes:""}}}parseEntity(A){return{frontmatter:this.parseFrontMatter(A.content,eJ),body:this.parseAgentContent(A.content)}}}zA();v0();var PQ8=new L4,O1Q=W.enum(["discovered","approved","archived"]),bQ8=W.looseObject({id:W.string().optional(),limit:W.number().optional(),page:W.number().optional(),pageSize:W.number().optional(),baseUrl:W.string().optional(),status:O1Q.optional()}),jQ8=W.looseObject({entityType:W.string().optional(),query:bQ8.optional()});function MQ8(A){let Q=MQ(A.content,eJ),$=PQ8.parseAgentContent(A.content);return V70.parse({...A,frontmatter:Q.metadata,about:$.about,skills:$.skills,notes:$.notes})}class if0 extends n7{id=z70;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:bw,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return MQ8(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=jQ8.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,$){let w=O1Q.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 kQ8=180*(3-Math.sqrt(5));function lNA(A){return Math.max(0,Math.min(1,A))}function iNA(A,Q){let[$,w]=A;if(Math.hypot($,w)<=0.000000000001)return Q*kQ8%360;return(Math.atan2(w,$)*180/Math.PI%360+360)%360}function f1Q(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:OQ8(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 OQ8(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}`}v0();var fQ8=eJ.shape.kind,xQ8=W.object({kind:W.enum(["identity","centroid"])}),RQ8=W.object({id:W.string(),name:W.string(),kind:fQ8,status:Nx,tags:W.array(W.string()),distance:W.number().min(0).max(1),bearing:W.number().min(0).lt(360)}),vQ8=W.object({sourceId:W.string(),targetId:W.string()}),CQ8=W.object({label:W.string(),memberIds:W.array(W.string()).min(2),links:W.array(vQ8).min(1)}),hQ8=W.object({min:W.number().min(0),max:W.number().min(0)}),x1Q=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()}),EQ8=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)}),Tb=W.object({center:xQ8,nodes:W.array(RQ8),clusters:W.array(CQ8),sightings:W.array(EQ8),distanceRange:hQ8,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 TQ8=new L4;function R1Q(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function zI(A){let Q=new Set,$=[];for(let w of A){let B=R1Q(w);if(!B||Q.has(B))continue;Q.add(B),$.push(B)}return $}function yQ8(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function v1Q(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:u9,options:{filter:{visibilityScope:B}}}),A.entityService.listEntities({entityType:bw,options:{filter:{visibilityScope:B}}})]),H=(K)=>{for(let U of zI(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=TQ8.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(yQ8).slice(0,w)}function C1Q(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(`
10767
10767
  `)}var gQ8={entityId:"brain-character",entityType:"brain-character"},SQ8=0.25,mQ8=0.5,uQ8=new L4;function h1Q(A){return A.status==="discovered"&&(A.introducedBy?.length??0)>0}async function df0(A){let[Q,$]=await Promise.all([A.entityService.listEntities({entityType:bw}),A.semantic.project({types:[bw],origin:gQ8,maxNeighborDistance:SQ8})]),w=new Map($.points.map((D)=>[D.entityId,D])),B=Q.slice().sort((D,q)=>D.id.localeCompare(q.id)).map((D)=>({agent:D,...uQ8.parseEntity(D)})),X=B.filter((D)=>!h1Q(D.frontmatter)),Y=B.filter((D)=>h1Q(D.frontmatter)),Z=[];for(let{agent:D,frontmatter:q,body:V}of X){let L=w.get(D.id);if(!L)continue;Z.push({id:D.id,name:q.name,kind:q.kind,status:q.status,tags:E1Q(V.skills),distance:lNA(L.distanceToOrigin),bearing:iNA(L.coordinates,Z.length)})}let H=Z.filter((D)=>D.status!=="archived"),K=new Set(H.map((D)=>D.id)),U=Math.max(mQ8,...H.map((D)=>D.distance)),G=[];for(let{agent:D,frontmatter:q,body:V}of Y){let L=w.get(D.id);if(!L)continue;let F=lNA(L.distanceToOrigin);if(F>U)continue;let _=(q.introducedBy??[]).filter((j)=>K.has(j));if(_.length===0)continue;G.push({id:D.id,name:q.name,viaIds:_,tags:E1Q(V.skills),distance:F,bearing:iNA(L.coordinates,G.length)})}return Tb.parse({center:{kind:$.origin.kind==="entity"?"identity":"centroid"},nodes:Z,clusters:f1Q(H,$.neighbors),sightings:G,distanceRange:$.distanceRange,pendingCount:Math.max(0,X.length-Z.length)})}function E1Q(A){return zI(A.flatMap((Q)=>Q.tags))}class nf0{id=cf0;name="Agent Proximity Map DataSource";description="Builds a public semantic proximity map for saved agents";async fetch(A,Q,$){let w=await df0({entityService:$.entityService,semantic:{project:(B)=>$.entityService.projectSemanticSpace(B)}});return Q.parse(w)}}zA();v0();Kw();zA();async function _o(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 Q10(Y)}catch{if($?.aborted)throw $.reason;return null}}function yb(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 cQ8=new L4;function Po(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:cQ8.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(`
@@ -11759,7 +11759,7 @@ ${A.guidance}`:B}}function gAQ(A){return{...A,evidence:A.evidence.map((Q)=>({...
11759
11759
  /* the shimmer delay is inlined per node, so the override needs force */
11760
11760
  .agent-proximity-site .proximity-agent { animation: none !important; }
11761
11761
  }
11762
- `,ko={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 R68(A){return A.split(/\*([^*]+)\*/g).map((Q,$)=>$%2===1?zX("b",{children:Q},Q,!1,void 0,this):Q)}function Q_A(A){let Q=A.nodes.filter((H)=>H.status!=="archived").length,$=A.kicker??ko.kicker,w=A.headingLead??ko.headingLead,B=A.headingAccent??ko.headingAccent,X=A.lede??ko.lede,Y=A.ctaLabel??ko.ctaLabel,Z=A.ctaHref??ko.ctaHref;return zX("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[zX("style",{children:x68},void 0,!1,void 0,this),zX("div",{class:"agent-proximity-site__grid",children:[zX("div",{class:"agent-proximity-site__copy",children:[zX("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),zX("h2",{class:"agent-proximity-site__heading",children:[w," ",zX("em",{children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),zX("p",{class:"agent-proximity-site__lede",children:R68(X)},void 0,!1,void 0,this),zX("a",{class:"agent-proximity-site__cta",href:Z,children:Y},void 0,!1,void 0,this),A.pendingCount>0&&zX("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&zX("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),zX("div",{class:"agent-proximity-site__map",children:[zX(af0,{data:A,surface:"site"},void 0,!1,void 0,this),zX("div",{class:"agent-proximity-site__foot","aria-label":"Network summary",children:[zX("span",{class:"agent-proximity-site__count",children:[zX("b",{children:Q},void 0,!1,void 0,this)," agents \xB7 ",zX("b",{children:A.clusters.length},void 0,!1,void 0,this)," ","constellations discovered"]},void 0,!0,void 0,this),zX("span",{class:"agent-proximity-site__live",children:"the map is live"},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)}var v68=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}),C68=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),h68=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),$_A=W.enum(["discovered","approved","archived"]),E68=W.enum(["professional","team","collective"]),T68=W.object({name:W.string(),kind:E68,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:$_A,discoveredAt:W.string()}),y68=W.object({name:W.string(),url:W.url(),status:$_A,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()}),ef0=W.object({id:W.string(),entityType:W.literal(bw),content:W.string(),created:W.string(),updated:W.string(),visibility:v68,metadata:y68,contentHash:W.string(),frontmatter:T68,about:W.string(),skills:W.array(h68),notes:W.string(),url:W.string().optional(),typeLabel:W.string().optional()}),g68=W.object({agents:W.array(ef0),pageTitle:W.string().optional(),pagination:C68.nullable(),baseUrl:W.string().optional(),selectedStatus:W.union([W.literal("all"),$_A])}),w2Q="/scripts/agent-proximity-map.js",S68=new P$(x1Q,{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 B2Q(){return{[uNA]:W2({name:uNA,description:"Semantic agent proximity map site section",schema:Tb,dataSourceId:cf0,overlayFormatter:S68,requiredPermission:"public",runtimeScripts:[{src:w2Q,defer:!0}],staticAssets:{[w2Q]:bo},layout:{component:Q_A}}),[cNA]:W2({name:cNA,description:"Agent directory list page template",schema:g68,dataSourceId:z70,requiredPermission:"public",layout:{component:A2Q}}),[pNA]:W2({name:pNA,description:"Individual agent profile template",schema:W.object({agent:ef0,prevAgent:ef0.nullable(),nextAgent:ef0.nullable()}),dataSourceId:z70,requiredPermission:"public",layout:{component:$2Q}})}}var Oo={name:"@brains/agent-discovery",version:"0.2.0-alpha.204",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 u68=new L4;class w_A extends c6{entityType=bw;schema=J70;adapter=u68;constructor(){super(D1Q,Oo,{},MY)}createGenerationHandler(A){return new dNA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return B2Q()}getDataSources(){return[new if0(this.logger.child("AgentDataSource")),new nf0]}async onRegister(A){r1Q(A),d1Q(A,this.id)}async getInstructions(){return o1Q()}}function B_A(){return new w_A}zA();yZ();v0();c4();v0();var X2Q=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()}),c68=new L4;function p68(A){let Q=yb(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function l68(A,Q){return(yb(Q)||A).toLowerCase()}async function i68(A){let{context:Q,entityId:$,card:w}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:bw,id:$}),Y=Po(w,{status:"approved"}),H={...c68.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:bw,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function Y2Q(A,Q=globalThis.fetch){let w=new $G;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:X2Q.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=X2Q.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=p68(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(bw,"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 _o(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=l68(H.domain,D.url),{entity:V,created:L}=await i68({context:A,entityId:q,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:L,a2aEndpoint:D.url,skills:D.skills.map((F)=>({name:F.name,description:F.description,tags:F.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}}}}v0();var Z2Q=W.object({}),d68=W.object({agents:W.array(W.object({name:W.string(),url:W.string()}))}),X_A=new L4;async function n68(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=d68.safeParse(await B.json());return X.success?X.data:null}catch{if($?.aborted)throw $.reason;return null}}async function Y_A(A,Q=globalThis.fetch,$){let w=await A.entityService.listEntities({entityType:bw}),B=w.filter((F)=>F.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let F of B){$?.throwIfAborted();let _=await n68(F.id,Q,$);if(!_){Z+=1;continue}for(let j of _.agents){let b=yb(j.url).toLowerCase();if(!b||b===X||b===F.id)continue;let k=Y.get(b)??new Set;k.add(F.id),Y.set(b,k)}}let H=new Map(w.map((F)=>[F.id,F])),K=new Date().toISOString(),U=[],G=new Set,D=0,q=0,V=0,L=0;for(let[F,_]of Y){$?.throwIfAborted();let j=H.get(F);if(j){let{frontmatter:R,body:O}=X_A.parseEntity(j),g=R.introducedBy??[];if(R.status!=="discovered"||g.length===0){V+=1;continue}let m=[...g,...[..._].filter((l)=>!g.includes(l))];if(m.length===g.length)continue;await A.entityService.updateEntity({entity:{...j,content:X_A.createAgentContent({...R,introducedBy:m,about:O.about,skills:O.skills,notes:O.notes}),updated:K}}),q+=1;continue}let b=await _o(F,Q,$);if(!b){L+=1;continue}let k=Po(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),v=X_A.fromMarkdown(k.content);await A.entityService.createEntity({entity:{id:F,entityType:bw,content:k.content,metadata:{...v.metadata,...k.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(F);for(let R of _)G.add(R)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:q,alreadyKnown:V,unverified:L,createdDomains:U,introducingPeers:[...G],observedAt:K}}function W2Q(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:Z2Q.shape,visibility:"trusted",sideEffects:"external",handler:async($,w)=>{let B=Z2Q.safeParse($);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(bw,"create",w)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await Y_A(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();v0();var r68=W.enum(["public","trusted"]),H2Q=W.object({agent:W.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:r68.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()}),o68=W.object({keys:W.array(W.unknown())}),s68=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),kid:W.string().optional(),alg:W.literal("EdDSA").optional()}).passthrough();function K2Q(A){return(yb(A)||A.trim()).toLowerCase()}async function a68(A,Q){let $=K2Q(Q),w=await A.entityService.getEntity({entityType:bw,id:$});if(!w)return null;let B=K2Q(w.metadata.a2aEndpoint??w.metadata.url);if(!B)return null;return{domain:B}}async function t68(A,Q){try{let $=await Q(`https://${A}/.well-known/jwks.json`);if(!$.ok)return null;let w=o68.safeParse(await $.json());if(!w.success)return null;let B=w.data.keys.map((X)=>s68.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return hUA(B.data)}catch{return null}}function U2Q(A,Q=globalThis.fetch){let w=new $G;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:H2Q.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=H2Q.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=vY();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await a68(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 t68(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 Ax0=W.object({notifyOnNewAgents:W.boolean().default(!1).describe("Notify when directory scans discover new agents")}).strict();class Z_A extends d6{fetchFn;constructor(A,Q={}){super("agent",Oo,Q,Ax0);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",deliverAlerts:this.config.notifyOnNewAgents,run:async({signal:Q})=>{let $=await Y_A(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[Y2Q(this.getContext(),this.fetchFn),W2Q(this.getContext(),this.fetchFn),U2Q(this.getContext(),this.fetchFn)]}}function W_A(A={}){return new Z_A(void 0,A)}zA();zA();v0();var ey=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),G2Q=ey,_70=MB.extend({entityType:W.literal(u9),metadata:G2Q});zA();class fo extends zQ{constructor(){super({entityType:u9,purpose:"A capability advertised by a remote agent.",schema:_70,frontmatterSchema:ey})}fromMarkdown(A){let Q=this.parseFrontMatter(A,ey);return{content:A,entityType:u9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}zA();v0();var e68=W.object({skills:W.array(ey).max(8)}),D2Q=W2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:e68,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
11762
+ `,ko={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 R68(A){return A.split(/\*([^*]+)\*/g).map((Q,$)=>$%2===1?zX("b",{children:Q},Q,!1,void 0,this):Q)}function Q_A(A){let Q=A.nodes.filter((H)=>H.status!=="archived").length,$=A.kicker??ko.kicker,w=A.headingLead??ko.headingLead,B=A.headingAccent??ko.headingAccent,X=A.lede??ko.lede,Y=A.ctaLabel??ko.ctaLabel,Z=A.ctaHref??ko.ctaHref;return zX("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[zX("style",{children:x68},void 0,!1,void 0,this),zX("div",{class:"agent-proximity-site__grid",children:[zX("div",{class:"agent-proximity-site__copy",children:[zX("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),zX("h2",{class:"agent-proximity-site__heading",children:[w," ",zX("em",{children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),zX("p",{class:"agent-proximity-site__lede",children:R68(X)},void 0,!1,void 0,this),zX("a",{class:"agent-proximity-site__cta",href:Z,children:Y},void 0,!1,void 0,this),A.pendingCount>0&&zX("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&zX("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),zX("div",{class:"agent-proximity-site__map",children:[zX(af0,{data:A,surface:"site"},void 0,!1,void 0,this),zX("div",{class:"agent-proximity-site__foot","aria-label":"Network summary",children:[zX("span",{class:"agent-proximity-site__count",children:[zX("b",{children:Q},void 0,!1,void 0,this)," agents \xB7 ",zX("b",{children:A.clusters.length},void 0,!1,void 0,this)," ","constellations discovered"]},void 0,!0,void 0,this),zX("span",{class:"agent-proximity-site__live",children:"the map is live"},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)}var v68=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}),C68=W.object({currentPage:W.number(),totalPages:W.number(),totalItems:W.number(),pageSize:W.number(),hasNextPage:W.boolean(),hasPrevPage:W.boolean()}),h68=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),$_A=W.enum(["discovered","approved","archived"]),E68=W.enum(["professional","team","collective"]),T68=W.object({name:W.string(),kind:E68,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:$_A,discoveredAt:W.string()}),y68=W.object({name:W.string(),url:W.url(),status:$_A,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()}),ef0=W.object({id:W.string(),entityType:W.literal(bw),content:W.string(),created:W.string(),updated:W.string(),visibility:v68,metadata:y68,contentHash:W.string(),frontmatter:T68,about:W.string(),skills:W.array(h68),notes:W.string(),url:W.string().optional(),typeLabel:W.string().optional()}),g68=W.object({agents:W.array(ef0),pageTitle:W.string().optional(),pagination:C68.nullable(),baseUrl:W.string().optional(),selectedStatus:W.union([W.literal("all"),$_A])}),w2Q="/scripts/agent-proximity-map.js",S68=new P$(x1Q,{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 B2Q(){return{[uNA]:W2({name:uNA,description:"Semantic agent proximity map site section",schema:Tb,dataSourceId:cf0,overlayFormatter:S68,requiredPermission:"public",runtimeScripts:[{src:w2Q,defer:!0}],staticAssets:{[w2Q]:bo},layout:{component:Q_A}}),[cNA]:W2({name:cNA,description:"Agent directory list page template",schema:g68,dataSourceId:z70,requiredPermission:"public",layout:{component:A2Q}}),[pNA]:W2({name:pNA,description:"Individual agent profile template",schema:W.object({agent:ef0,prevAgent:ef0.nullable(),nextAgent:ef0.nullable()}),dataSourceId:z70,requiredPermission:"public",layout:{component:$2Q}})}}var Oo={name:"@brains/agent-discovery",version:"0.2.0-alpha.206",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 u68=new L4;class w_A extends c6{entityType=bw;schema=J70;adapter=u68;constructor(){super(D1Q,Oo,{},MY)}createGenerationHandler(A){return new dNA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return B2Q()}getDataSources(){return[new if0(this.logger.child("AgentDataSource")),new nf0]}async onRegister(A){r1Q(A),d1Q(A,this.id)}async getInstructions(){return o1Q()}}function B_A(){return new w_A}zA();yZ();v0();c4();v0();var X2Q=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()}),c68=new L4;function p68(A){let Q=yb(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function l68(A,Q){return(yb(Q)||A).toLowerCase()}async function i68(A){let{context:Q,entityId:$,card:w}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:bw,id:$}),Y=Po(w,{status:"approved"}),H={...c68.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:bw,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function Y2Q(A,Q=globalThis.fetch){let w=new $G;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:X2Q.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=X2Q.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=p68(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(bw,"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 _o(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=l68(H.domain,D.url),{entity:V,created:L}=await i68({context:A,entityId:q,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:L,a2aEndpoint:D.url,skills:D.skills.map((F)=>({name:F.name,description:F.description,tags:F.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}}}}v0();var Z2Q=W.object({}),d68=W.object({agents:W.array(W.object({name:W.string(),url:W.string()}))}),X_A=new L4;async function n68(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=d68.safeParse(await B.json());return X.success?X.data:null}catch{if($?.aborted)throw $.reason;return null}}async function Y_A(A,Q=globalThis.fetch,$){let w=await A.entityService.listEntities({entityType:bw}),B=w.filter((F)=>F.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let F of B){$?.throwIfAborted();let _=await n68(F.id,Q,$);if(!_){Z+=1;continue}for(let j of _.agents){let b=yb(j.url).toLowerCase();if(!b||b===X||b===F.id)continue;let k=Y.get(b)??new Set;k.add(F.id),Y.set(b,k)}}let H=new Map(w.map((F)=>[F.id,F])),K=new Date().toISOString(),U=[],G=new Set,D=0,q=0,V=0,L=0;for(let[F,_]of Y){$?.throwIfAborted();let j=H.get(F);if(j){let{frontmatter:R,body:O}=X_A.parseEntity(j),g=R.introducedBy??[];if(R.status!=="discovered"||g.length===0){V+=1;continue}let m=[...g,...[..._].filter((l)=>!g.includes(l))];if(m.length===g.length)continue;await A.entityService.updateEntity({entity:{...j,content:X_A.createAgentContent({...R,introducedBy:m,about:O.about,skills:O.skills,notes:O.notes}),updated:K}}),q+=1;continue}let b=await _o(F,Q,$);if(!b){L+=1;continue}let k=Po(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),v=X_A.fromMarkdown(k.content);await A.entityService.createEntity({entity:{id:F,entityType:bw,content:k.content,metadata:{...v.metadata,...k.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(F);for(let R of _)G.add(R)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:q,alreadyKnown:V,unverified:L,createdDomains:U,introducingPeers:[...G],observedAt:K}}function W2Q(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:Z2Q.shape,visibility:"trusted",sideEffects:"external",handler:async($,w)=>{let B=Z2Q.safeParse($);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(bw,"create",w)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await Y_A(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();v0();var r68=W.enum(["public","trusted"]),H2Q=W.object({agent:W.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:r68.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()}),o68=W.object({keys:W.array(W.unknown())}),s68=W.object({kty:W.literal("OKP"),crv:W.literal("Ed25519"),x:W.string(),kid:W.string().optional(),alg:W.literal("EdDSA").optional()}).passthrough();function K2Q(A){return(yb(A)||A.trim()).toLowerCase()}async function a68(A,Q){let $=K2Q(Q),w=await A.entityService.getEntity({entityType:bw,id:$});if(!w)return null;let B=K2Q(w.metadata.a2aEndpoint??w.metadata.url);if(!B)return null;return{domain:B}}async function t68(A,Q){try{let $=await Q(`https://${A}/.well-known/jwks.json`);if(!$.ok)return null;let w=o68.safeParse(await $.json());if(!w.success)return null;let B=w.data.keys.map((X)=>s68.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return hUA(B.data)}catch{return null}}function U2Q(A,Q=globalThis.fetch){let w=new $G;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:H2Q.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=H2Q.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=vY();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await a68(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 t68(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 Ax0=W.object({notifyOnNewAgents:W.boolean().default(!1).describe("Notify when directory scans discover new agents")}).strict();class Z_A extends d6{fetchFn;constructor(A,Q={}){super("agent",Oo,Q,Ax0);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",deliverAlerts:this.config.notifyOnNewAgents,run:async({signal:Q})=>{let $=await Y_A(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[Y2Q(this.getContext(),this.fetchFn),W2Q(this.getContext(),this.fetchFn),U2Q(this.getContext(),this.fetchFn)]}}function W_A(A={}){return new Z_A(void 0,A)}zA();zA();v0();var ey=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),G2Q=ey,_70=MB.extend({entityType:W.literal(u9),metadata:G2Q});zA();class fo extends zQ{constructor(){super({entityType:u9,purpose:"A capability advertised by a remote agent.",schema:_70,frontmatterSchema:ey})}fromMarkdown(A){let Q=this.parseFrontMatter(A,ey);return{content:A,entityType:u9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}zA();v0();var e68=W.object({skills:W.array(ey).max(8)}),D2Q=W2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:e68,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
11763
11763
 
11764
11764
  Given knowledge domains, CONSOLIDATE related topics into broader skills.
11765
11765
  There should be FEWER skills than topics \u2014 combine related domains.
@@ -12021,9 +12021,9 @@ ${JSON.stringify($,null,2)}`}function Wx0(A){return A.map((Q)=>Q.detail===null?{
12021
12021
  border-bottom: none;
12022
12022
  }
12023
12023
  }
12024
- `;import{jsxDEV as LW}from"preact/jsx-dev-runtime";var O2Q=k2Q,Kx0=W.object({title:W.string(),detail:W.string().optional()}),j$8=W.discriminatedUnion("status",[W.object({status:W.literal("generating")}),W.object({status:W.literal("ready"),strengths:W.array(Kx0).default([]),weaknesses:W.array(Kx0).default([]),opportunities:W.array(Kx0).default([]),threats:W.array(Kx0).default([]),derivedAt:W.string()})]);function M$8({items:A}){if(A.length===0)return LW("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return LW("ul",{class:"swot-list",children:A.map((Q)=>LW("li",{class:"swot-item",children:[LW("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?LW("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 Ux0({title:A,tone:Q,items:$}){return LW("section",{class:`swot-cell is-${Q}`,children:[LW("div",{class:"swot-head",children:A},void 0,!1,void 0,this),LW(M$8,{items:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function L_A({data:A}){let Q=j$8.safeParse(A);if(!Q.success||Q.data.status==="generating")return LW("div",{"data-swot-widget":!0,children:LW("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let $=Q.data;return LW("div",{"data-swot-widget":!0,children:LW("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[LW(Ux0,{title:"Strengths",tone:"s",items:$.strengths},void 0,!1,void 0,this),LW(Ux0,{title:"Weaknesses",tone:"w",items:$.weaknesses},void 0,!1,void 0,this),LW(Ux0,{title:"Opportunities",tone:"o",items:$.opportunities},void 0,!1,void 0,this),LW(Ux0,{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 I_A={name:"@brains/assessment",version:"0.2.0-alpha.204",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 O$8=W.object({status:W.enum(["ready","generating"])}),N_A=new Sb;class __A extends c6{entityType="swot";schema=xo;adapter=N_A;initialSyncComplete=!1;constructor(){super("swot",I_A,{},MY)}async onRegister(A){let Q=new Hx0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=yW.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 N_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}=O$8.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:L_A,clientStyles:O2Q,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=N_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 P_A(){return new __A}zA();b9();v0();var dIB=new Sb,f2Q=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),x2Q=W.enum(["discovered","approved"]),f$8=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:x2Q,discoveredAt:W.string().datetime()}),x$8=MB.extend({entityType:W.literal("agent"),metadata:W.object({name:W.string(),url:W.string().url(),status:x2Q,slug:W.string()})}),b_A=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),R$8=MB.extend({entityType:W.literal("skill"),metadata:b_A}),v$8=W.object({about:W.string(),skills:W.array(f2Q),notes:W.string()});function C$8(A){if(!Array.isArray(A)||A.length===0)return"";return A.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
12024
+ `;import{jsxDEV as LW}from"preact/jsx-dev-runtime";var O2Q=k2Q,Kx0=W.object({title:W.string(),detail:W.string().optional()}),j$8=W.discriminatedUnion("status",[W.object({status:W.literal("generating")}),W.object({status:W.literal("ready"),strengths:W.array(Kx0).default([]),weaknesses:W.array(Kx0).default([]),opportunities:W.array(Kx0).default([]),threats:W.array(Kx0).default([]),derivedAt:W.string()})]);function M$8({items:A}){if(A.length===0)return LW("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return LW("ul",{class:"swot-list",children:A.map((Q)=>LW("li",{class:"swot-item",children:[LW("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?LW("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 Ux0({title:A,tone:Q,items:$}){return LW("section",{class:`swot-cell is-${Q}`,children:[LW("div",{class:"swot-head",children:A},void 0,!1,void 0,this),LW(M$8,{items:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function L_A({data:A}){let Q=j$8.safeParse(A);if(!Q.success||Q.data.status==="generating")return LW("div",{"data-swot-widget":!0,children:LW("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let $=Q.data;return LW("div",{"data-swot-widget":!0,children:LW("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[LW(Ux0,{title:"Strengths",tone:"s",items:$.strengths},void 0,!1,void 0,this),LW(Ux0,{title:"Weaknesses",tone:"w",items:$.weaknesses},void 0,!1,void 0,this),LW(Ux0,{title:"Opportunities",tone:"o",items:$.opportunities},void 0,!1,void 0,this),LW(Ux0,{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 I_A={name:"@brains/assessment",version:"0.2.0-alpha.206",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 O$8=W.object({status:W.enum(["ready","generating"])}),N_A=new Sb;class __A extends c6{entityType="swot";schema=xo;adapter=N_A;initialSyncComplete=!1;constructor(){super("swot",I_A,{},MY)}async onRegister(A){let Q=new Hx0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=yW.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 N_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}=O$8.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:L_A,clientStyles:O2Q,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=N_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 P_A(){return new __A}zA();b9();v0();var dIB=new Sb,f2Q=W.object({name:W.string(),description:W.string(),tags:W.array(W.string())}),x2Q=W.enum(["discovered","approved"]),f$8=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:x2Q,discoveredAt:W.string().datetime()}),x$8=MB.extend({entityType:W.literal("agent"),metadata:W.object({name:W.string(),url:W.string().url(),status:x2Q,slug:W.string()})}),b_A=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),R$8=MB.extend({entityType:W.literal("skill"),metadata:b_A}),v$8=W.object({about:W.string(),skills:W.array(f2Q),notes:W.string()});function C$8(A){if(!Array.isArray(A)||A.length===0)return"";return A.map(($)=>{let w=$.tags.length>0?` [${$.tags.join(", ")}]`:"";return`- ${$.name}: ${$.description}${w}`}).join(`
12025
12025
  `)}function h$8(A){if(!A.trim())return[];return A.split(`
12026
- `).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 E$8=new P$(v$8,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:C$8,parser:h$8},{key:"notes",label:"Notes",type:"string"}]});class R2Q extends zQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:x$8,frontmatterSchema:f$8})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=E$8.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 v2Q extends zQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:R$8,frontmatterSchema:b_A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,b_A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var nIB=new R2Q,rIB=new v2Q,T$8=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),oIB=W.object({skills:W.array(T$8),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(f2Q),notes:W.string().default("")}))});var y$8=W.object({}).strict();function Gx0(A={}){return y$8.parse(A),[P_A()]}zA();v0();v0();var j_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")});v0();var g$8=W.looseObject({message:W.string()}),S$8=W.looseObject({did:W.string(),handle:W.string(),accessJwt:W.string(),refreshJwt:W.string()}),M_A=W.looseObject({uri:W.string(),cid:W.string()}),m$8=M_A.extend({value:W.record(W.string(),W.unknown())}),u$8=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})),c$8=W.looseObject({blob:u$8});function p$8(A){return A.replace(/\/+$/,"")}var l$8=(A,Q)=>fetch(A,Q);async function b70(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=g$8.safeParse(w);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(w)}class j70{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=p$8(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??l$8}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 b70(A,S$8);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 b70($,M_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 b70($,M_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 b70($,m$8)}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 b70($,c$8)}async getSession(){return this.session??=await this.createSession(),this.session}}function Qg(A){return A?.startsWith("did:web:")??!1}function Dx0(A){if(!Qg(A))return;let Q=A.slice(8);if(!Q)return;let[$]=Q.split(":");if(!$)return;try{return decodeURIComponent($)}catch{return $}}function h2Q(A){if(!Qg(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 E2Q(A){return A.replace(/\/+$/,"")}function M70(A){return`did:web:${encodeURIComponent(A)}`}function qx0(A){return`${M70(A)}:anchor`}function k_A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function T2Q(A,Q){let $=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...k_A(Q),...$&&{alsoKnownAs:$},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:E2Q(A.pdsEndpoint)}]}}function y2Q(A){if(!Qg(A.brainDid))return null;return T2Q(A,A.brainDid)}function C2Q(A,Q){if(!A||!Q)return;let $=Dx0(A),w=h2Q(A);if(!$||!w)return;return{path:w,hostname:$,document:Q}}function zx0(A){let Q=[],$=C2Q(A.brainDid,y2Q(A));if($)Q.push($);if(Qg(A.anchorDid)&&A.anchorDid!==A.brainDid){let w=C2Q(A.anchorDid,k_A(A.anchorDid));if(w)Q.push(w)}return Q}function O_A(A,Q){let $=[];if(!A.brainDid){let w=M70(Q);$.push({path:"/.well-known/did.json",hostname:Q,document:T2Q(A,w)})}if(!A.anchorDid){let w=qx0(Q);$.push({path:"/anchor/did.json",hostname:Q,document:k_A(w)})}return $}function i$8(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function d$8(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 S2Q(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 n$8(A){let Q=A.metadata,$=g2Q(Q,"name"),w=g2Q(Q,"description");if(!$||!w)return;let B=S2Q(Q,"tags"),X=S2Q(Q,"examples");return{id:d$8($),name:$,description:w,...B&&{tags:B},...X&&{examples:X}}}async function r$8(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map(($)=>n$8($)).filter(($)=>$!==void 0).slice(0,100)}async function f_A(A,Q,$=new Date){let w=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=i$8(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??M70(Z),K=Q.anchorDid??qx0(Z);if(Qg(H)){if(Dx0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await r$8(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 m2Q={name:"@brains/atproto",version:"0.2.0-alpha.204",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 u2Q=i8["ai.rizom.brain.card"],s$8=W.looseObject({did:W.string()}),a$8=W.looseObject({service:W.array(W.looseObject({id:W.string().optional(),type:W.string().optional(),serviceEndpoint:W.string().optional()})).optional()}),t$8="ai.rizom.brain.card",e$8="self",c2Q=50;class x_A extends d6{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",m2Q,A,j_A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??D9.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=zx0(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=[...zx0(this.config),...O_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 f_A(A,this.config);eP(u2Q,$);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>c2Q)throw Error(`AT Protocol discovery accepts at most ${c2Q} 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:t$8,rkey:e$8});eP(u2Q,H.value);let K=Q88(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:Y50,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:sA(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:sA(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 eP($.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(eP($.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:A88(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 j70({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=s$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($88(A)):void 0,$=a$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 j70({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function A88(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function Q88(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function $88(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 Jx0(A,Q){return new x_A(A,Q)}zA();v0();var Vx0={name:"@brains/rover",version:"0.2.0-alpha.204",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 B88=W.looseObject({});class p2Q extends d6{constructor(A={}){super("rover-profile",Vx0,A,B88)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",SC)}}function l2Q(A={}){return new p2Q(A)}zA();v0();aw();zA();zA();var k70=E_.extend(SC.shape);class Fx0{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([kc(w,k70),Hk0(w,{entityType:"post",count:3,parse:A90}),Hk0(w,{entityType:"deck",count:3,parse:Z90}),tB0(w)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:jVA(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}zA();class Lx0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,$){let B={profile:await kc($.entityService,k70)};return Q.parse(B)}}import{jsxDEV as V5,Fragment as Z88}from"preact/jsx-dev-runtime";var X88="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",Y88="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",R_A=({number:A,title:Q,blurb:$,children:w})=>V5("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:V5("div",{className:"max-w-6xl mx-auto",children:V5("div",{className:X88,children:[V5(MzA,{title:Q,number:A,blurb:$},void 0,!1,void 0,this),V5("div",{className:Y88,"aria-hidden":"true"},void 0,!1,void 0,this),V5("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),v_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 V5(Z88,{children:[V5(E6,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),V5("div",{className:"homepage-list bg-theme",children:[V5("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:V5("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&V5("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[V5("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),V5("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&V5("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:_j0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&V5("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:_j0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V5(R_A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:V5(Nj0,{items:H,viewAllUrl:w,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&V5(R_A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:V5(Nj0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&V5(R_A,{number:"03",title:"About",blurb:Y.about?.blurb,children:V5("div",{className:"flex flex-col gap-8",children:[A.description&&V5("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&&V5(kzA,{subjects:A.expertise},void 0,!1,void 0,this),V5("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",V5("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),V5(UzA,{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 xw,Fragment as W88}from"preact/jsx-dev-runtime";var C_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 xw(W88,{children:[xw(E6,{title:Q,description:$,ogType:"profile"},void 0,!1,void 0,this),xw("div",{className:"about-page bg-theme",children:[xw("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:xw("div",{className:"relative z-10 max-w-4xl mx-auto",children:[xw("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&&xw("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),xw("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&xw("section",{className:"content-section-reveal mb-20 md:mb-28",children:xw(BX,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&xw("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),xw("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>xw("li",{className:s50({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&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),xw("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&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),xw("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)&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),xw("div",{className:"space-y-4",children:[A.email&&xw("p",{className:"text-lg",children:xw("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&&xw("p",{className:"text-lg",children:xw("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&&xw("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>xw(wX,{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 IW,Fragment as i2Q}from"preact/jsx-dev-runtime";var h_A=()=>{return IW(i2Q,{children:[IW(E6,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),IW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IW("div",{className:"text-center max-w-md",children:[IW("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),IW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),IW("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),IW(wX,{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)},E_A=()=>{return IW(i2Q,{children:[IW(E6,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),IW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IW("div",{className:"text-center max-w-md",children:[IW("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),IW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),IW("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),IW(wX,{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)};v0();var d2Q=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')")}),H88={post:{label:"Post"},deck:{label:"Deck"}},n2Q=W.object({entityDisplay:W.object({post:d2Q,deck:d2Q}).default(H88).describe("Display metadata for post and deck entity types used by the homepage")});var r2Q={name:"@brains/site-professional",version:"0.2.0-alpha.204",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 U88=W.object({blurb:W.string().optional().describe("Short italic subtitle under the section title")}),G88=W.object({heading:W.string(),buttonText:W.string(),buttonLink:W.string()}),o2Q=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()}),D88=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()}),q88=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 T_A extends d6{dependencies=["blog","decks"];constructor(A){super("professional-site",r2Q,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 Fx0(w,B);A.entities.registerDataSource(X);let Y=new Lx0;A.entities.registerDataSource(Y);let Z=W.object({profile:o2Q,posts:W.array(D88),decks:W.array(q88),postsListUrl:W.string(),decksListUrl:W.string(),cta:G88,sections:W.record(W.string(),U88)}),H=W.object({profile:o2Q}),K=W.object({});A.templates.register({"homepage-list":W2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:v_A}}),about:W2({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:C_A}}),"subscribe-thanks":W2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:h_A}}),"subscribe-error":W2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:E_A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function s2Q(A){return new T_A(A??{})}var a2Q=[{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 Ix0}from"preact/jsx-dev-runtime";function t2Q({sections:A,siteInfo:Q,slots:$,wordmark:w}){return Ix0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[Ix0(zzA,{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),Ix0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),Ix0(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 z88={layouts:{default:t2Q},routes:a2Q,plugin:s2Q,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"}}}},O70=z88;var e2Q=`/*
12026
+ `).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 E$8=new P$(v$8,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:C$8,parser:h$8},{key:"notes",label:"Notes",type:"string"}]});class R2Q extends zQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:x$8,frontmatterSchema:f$8})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=E$8.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 v2Q extends zQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:R$8,frontmatterSchema:b_A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,b_A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var nIB=new R2Q,rIB=new v2Q,T$8=W.object({name:W.string(),description:W.string(),tags:W.array(W.string()),examples:W.array(W.string())}),oIB=W.object({skills:W.array(T$8),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(f2Q),notes:W.string().default("")}))});var y$8=W.object({}).strict();function Gx0(A={}){return y$8.parse(A),[P_A()]}zA();v0();v0();var j_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"),accountDid:W.string().optional().describe("Owner's atproto account DID (did:plc:\u2026). When set, the brain serves it at /.well-known/atproto-did so the owner's handle can verify against this domain (HTTP method) \u2014 member handles under the fleet domain")});v0();var g$8=W.looseObject({message:W.string()}),S$8=W.looseObject({did:W.string(),handle:W.string(),accessJwt:W.string(),refreshJwt:W.string()}),M_A=W.looseObject({uri:W.string(),cid:W.string()}),m$8=M_A.extend({value:W.record(W.string(),W.unknown())}),u$8=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})),c$8=W.looseObject({blob:u$8});function p$8(A){return A.replace(/\/+$/,"")}var l$8=(A,Q)=>fetch(A,Q);async function b70(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=g$8.safeParse(w);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(w)}class j70{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=p$8(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??l$8}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 b70(A,S$8);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 b70($,M_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 b70($,M_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 b70($,m$8)}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 b70($,c$8)}async getSession(){return this.session??=await this.createSession(),this.session}}function Qg(A){return A?.startsWith("did:web:")??!1}function Dx0(A){if(!Qg(A))return;let Q=A.slice(8);if(!Q)return;let[$]=Q.split(":");if(!$)return;try{return decodeURIComponent($)}catch{return $}}function h2Q(A){if(!Qg(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 E2Q(A){return A.replace(/\/+$/,"")}function M70(A){return`did:web:${encodeURIComponent(A)}`}function qx0(A){return`${M70(A)}:anchor`}function k_A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function T2Q(A,Q){let $=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...k_A(Q),...$&&{alsoKnownAs:$},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:E2Q(A.pdsEndpoint)}]}}function y2Q(A){if(!Qg(A.brainDid))return null;return T2Q(A,A.brainDid)}function C2Q(A,Q){if(!A||!Q)return;let $=Dx0(A),w=h2Q(A);if(!$||!w)return;return{path:w,hostname:$,document:Q}}function zx0(A){let Q=[],$=C2Q(A.brainDid,y2Q(A));if($)Q.push($);if(Qg(A.anchorDid)&&A.anchorDid!==A.brainDid){let w=C2Q(A.anchorDid,k_A(A.anchorDid));if(w)Q.push(w)}return Q}function O_A(A,Q){let $=[];if(!A.brainDid){let w=M70(Q);$.push({path:"/.well-known/did.json",hostname:Q,document:T2Q(A,w)})}if(!A.anchorDid){let w=qx0(Q);$.push({path:"/anchor/did.json",hostname:Q,document:k_A(w)})}return $}function i$8(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function d$8(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 S2Q(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 n$8(A){let Q=A.metadata,$=g2Q(Q,"name"),w=g2Q(Q,"description");if(!$||!w)return;let B=S2Q(Q,"tags"),X=S2Q(Q,"examples");return{id:d$8($),name:$,description:w,...B&&{tags:B},...X&&{examples:X}}}async function r$8(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map(($)=>n$8($)).filter(($)=>$!==void 0).slice(0,100)}async function f_A(A,Q,$=new Date){let w=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=i$8(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??M70(Z),K=Q.anchorDid??qx0(Z);if(Qg(H)){if(Dx0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await r$8(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 m2Q={name:"@brains/atproto",version:"0.2.0-alpha.206",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 u2Q=i8["ai.rizom.brain.card"],s$8=W.looseObject({did:W.string()}),a$8=W.looseObject({service:W.array(W.looseObject({id:W.string().optional(),type:W.string().optional(),serviceEndpoint:W.string().optional()})).optional()}),t$8="ai.rizom.brain.card",e$8="self",c2Q=50;class x_A extends d6{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",m2Q,A,j_A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??D9.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=zx0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]],w=[...new Set([...A.map((X)=>X.path),...Q])].map((X)=>({path:X,method:"GET",public:!0,handler:(Y)=>{let Z=new URL(Y.url).hostname,H=[...zx0(this.config),...O_A(this.config,Z)].filter((U)=>U.path===X),K=H.find((U)=>U.hostname===Z)??H[0];if(!K)return new Response("Not found",{status:404});return new Response(JSON.stringify(K.document),{headers:{"Content-Type":"application/did+json"}})}})),B=this.config.accountDid;if(B)w.push({path:"/.well-known/atproto-did",method:"GET",public:!0,handler:()=>new Response(B,{headers:{"Content-Type":"text/plain"}})});return w}async publishBrainCard(A,Q={}){let $=await f_A(A,this.config);eP(u2Q,$);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>c2Q)throw Error(`AT Protocol discovery accepts at most ${c2Q} 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:t$8,rkey:e$8});eP(u2Q,H.value);let K=Q88(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:Y50,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:sA(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:sA(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 eP($.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(eP($.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:A88(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 j70({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=s$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($88(A)):void 0,$=a$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 j70({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function A88(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function Q88(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function $88(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 Jx0(A,Q){return new x_A(A,Q)}zA();v0();var Vx0={name:"@brains/rover",version:"0.2.0-alpha.206",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 B88=W.looseObject({});class p2Q extends d6{constructor(A={}){super("rover-profile",Vx0,A,B88)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",SC)}}function l2Q(A={}){return new p2Q(A)}zA();v0();aw();zA();zA();var k70=E_.extend(SC.shape);class Fx0{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([kc(w,k70),Hk0(w,{entityType:"post",count:3,parse:A90}),Hk0(w,{entityType:"deck",count:3,parse:Z90}),tB0(w)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:jVA(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}zA();class Lx0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,$){let B={profile:await kc($.entityService,k70)};return Q.parse(B)}}import{jsxDEV as V5,Fragment as Z88}from"preact/jsx-dev-runtime";var X88="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",Y88="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",R_A=({number:A,title:Q,blurb:$,children:w})=>V5("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:V5("div",{className:"max-w-6xl mx-auto",children:V5("div",{className:X88,children:[V5(MzA,{title:Q,number:A,blurb:$},void 0,!1,void 0,this),V5("div",{className:Y88,"aria-hidden":"true"},void 0,!1,void 0,this),V5("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),v_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 V5(Z88,{children:[V5(E6,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),V5("div",{className:"homepage-list bg-theme",children:[V5("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:V5("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&V5("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[V5("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),V5("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&V5("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:_j0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&V5("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:_j0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V5(R_A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:V5(Nj0,{items:H,viewAllUrl:w,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&V5(R_A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:V5(Nj0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&V5(R_A,{number:"03",title:"About",blurb:Y.about?.blurb,children:V5("div",{className:"flex flex-col gap-8",children:[A.description&&V5("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&&V5(kzA,{subjects:A.expertise},void 0,!1,void 0,this),V5("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",V5("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),V5(UzA,{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 xw,Fragment as W88}from"preact/jsx-dev-runtime";var C_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 xw(W88,{children:[xw(E6,{title:Q,description:$,ogType:"profile"},void 0,!1,void 0,this),xw("div",{className:"about-page bg-theme",children:[xw("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:xw("div",{className:"relative z-10 max-w-4xl mx-auto",children:[xw("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&&xw("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),xw("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&xw("section",{className:"content-section-reveal mb-20 md:mb-28",children:xw(BX,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&xw("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),xw("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>xw("li",{className:s50({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&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),xw("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&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),xw("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)&&xw("section",{children:[xw("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),xw("div",{className:"space-y-4",children:[A.email&&xw("p",{className:"text-lg",children:xw("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&&xw("p",{className:"text-lg",children:xw("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&&xw("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>xw(wX,{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 IW,Fragment as i2Q}from"preact/jsx-dev-runtime";var h_A=()=>{return IW(i2Q,{children:[IW(E6,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),IW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IW("div",{className:"text-center max-w-md",children:[IW("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),IW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),IW("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),IW(wX,{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)},E_A=()=>{return IW(i2Q,{children:[IW(E6,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),IW("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IW("div",{className:"text-center max-w-md",children:[IW("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),IW("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),IW("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),IW(wX,{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)};v0();var d2Q=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')")}),H88={post:{label:"Post"},deck:{label:"Deck"}},n2Q=W.object({entityDisplay:W.object({post:d2Q,deck:d2Q}).default(H88).describe("Display metadata for post and deck entity types used by the homepage")});var r2Q={name:"@brains/site-professional",version:"0.2.0-alpha.206",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 U88=W.object({blurb:W.string().optional().describe("Short italic subtitle under the section title")}),G88=W.object({heading:W.string(),buttonText:W.string(),buttonLink:W.string()}),o2Q=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()}),D88=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()}),q88=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 T_A extends d6{dependencies=["blog","decks"];constructor(A){super("professional-site",r2Q,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 Fx0(w,B);A.entities.registerDataSource(X);let Y=new Lx0;A.entities.registerDataSource(Y);let Z=W.object({profile:o2Q,posts:W.array(D88),decks:W.array(q88),postsListUrl:W.string(),decksListUrl:W.string(),cta:G88,sections:W.record(W.string(),U88)}),H=W.object({profile:o2Q}),K=W.object({});A.templates.register({"homepage-list":W2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:v_A}}),about:W2({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:C_A}}),"subscribe-thanks":W2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:h_A}}),"subscribe-error":W2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:E_A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function s2Q(A){return new T_A(A??{})}var a2Q=[{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 Ix0}from"preact/jsx-dev-runtime";function t2Q({sections:A,siteInfo:Q,slots:$,wordmark:w}){return Ix0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[Ix0(zzA,{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),Ix0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),Ix0(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 z88={layouts:{default:t2Q},routes:a2Q,plugin:s2Q,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"}}}},O70=z88;var e2Q=`/*
12027
12027
  * Default theme \u2014 simplified editorial base inspired by the Rizom family.
12028
12028
  *
12029
12029
  * This theme is intentionally less branded than @brains/theme-rizom. It
@@ -15008,7 +15008,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});v0();var l
15008
15008
  `);return this.truncateContent(w||Q||As(A))}truncateContent(A){if(A.length<=Q4Q)return A;let Q=A.slice(0,Q4Q-1),$=Q.search(/\s\S*$/);return`${($>0?Q.slice(0,$):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===c9}isDecisionEntity(A){return A.entityType===ND}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return QV(Q)}}var FW8=5,LW8=3;function ojA(A){A.messaging.subscribe(gR,async(Q)=>{let $=Qt.parse(Q.payload);return{success:!0,data:await mR0(A,$)}})}async function mR0(A,Q){let $=e5(Q.userPermissionLevel);if(!Q.channelId)return $4Q(A,Q,{visibilityScope:$,reason:"no-channel-context",items:[]}),{items:[]};let w=new Qs(A),B=await w.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:FW8,visibilityScope:$}),X=B.results.length===0?await w.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:LW8,visibilityScope:$}):void 0,Y=B.results.length>0,Z=Y?B.results:X?.results??[];return $4Q(A,Q,{visibilityScope:$,spaceId:B.spaceId??X?.spaceId,reason:Z.length>0?"memory-injected":"no-same-space-memory",items:Z.map((H)=>IW8(H,Y))}),{items:Z.map(NW8)}}function $4Q(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 IW8(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 NW8(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}}}v0();yZ();var X4Q=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}),Y4Q=W.enum(["user","assistant"]),_W8=W.object({actorId:W.string(),canonicalId:W.string().optional(),interfaceType:W.string(),role:Y4Q,displayName:W.string().optional(),username:W.string().optional(),isBot:W.boolean().optional()}),PW8=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()}),ajA=W.object({role:Y4Q,content:W.string(),timestamp:W.string().datetime().optional(),actor:_W8.optional(),source:PW8.optional()}),bW8=W.object({conversationId:W.string().default("eval-conversation"),messages:W.array(ajA)}),jW8=W.object({conversationId:W.string()}),MW8=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(ajA)}),uR0=W.object({actorId:W.string(),canonicalId:W.string().optional(),displayName:W.string().optional()}),kW8=uR0.extend({roles:W.array(W.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:W.array(W.string()).optional()}),OW8=W.object({actorId:W.string().optional(),canonicalId:W.string().optional(),displayName:W.string()}),Z4Q=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:X4Q,status:W.string().optional(),participants:W.array(kW8).optional(),decidedBy:W.array(uR0).optional(),mentionedBy:W.array(uR0).optional(),assignedTo:W.array(OW8).optional(),requestedBy:W.array(uR0).optional()}),fW8=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:X4Q.optional(),memory:W.array(Z4Q).optional()}),xW8=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(Z4Q).optional()}),RW8=W.object({conversationId:W.string().default("eval-conversation"),existingSummary:W.string().optional(),existingMessageCount:W.number().int().min(0).default(0),messages:W.array(ajA)});function W4Q(A){let{context:Q,logger:$,config:w}=A;Q.eval.registerHandler("summarizeMessages",async(B)=>{let X=bW8.parse(B),Y=sjA(X.messages,X.conversationId),H=await new ao(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(`
15009
15009
  `),decisionsText:U.join(`
15010
15010
  `),actionItemsText:G.join(`
15011
- `)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=RW8.parse(B),Y=sjA(X.messages,X.conversationId),Z=X.existingSummary?w4Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null;return new Cx(Q,$,w).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=fW8.parse(B),Y=X.memory?B4Q(Q,X.memory):Q;return new Qs(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=xW8.parse(B),Y=X.memory?B4Q(Q,X.memory):Q;return mR0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=MW8.parse(B),Y=sjA(X.messages,X.conversationId),Z=vW8({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?w4Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null,K=[],U=[],G=CW8({context:Q,conversation:Z,messages:Y,existing:H,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new Cx(G,$,w).projectConversation(X.conversationId),summaries:K.filter((V)=>V.entityType==="summary"),decisions:K.filter((V)=>V.entityType==="decision"),actionItems:K.filter((V)=>V.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=jW8.parse(B);return new Cx(Q,$,w).projectConversation(X.conversationId)})}function w4Q(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 sjA(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 vW8(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 CW8(A){let Q=QV(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 B4Q(A,Q){let $=Q.map(hW8),w=$.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??As(B)}));return{...A,entityService:{...A.entityService,search:async()=>w,listEntities:async({entityType:B})=>$.filter((X)=>X.entityType===B)}}}function hW8(A){if(A.entityType==="summary")return EW8(A);if(A.entityType==="decision")return TW8(A);return yW8(A)}function tjA(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 EW8(A){return{...tjA(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 TW8(A){return{...tjA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:QV(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 yW8(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...tjA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:QV(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 H4Q={name:"@brains/conversation-memory",version:"0.2.0-alpha.204",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 SW8=new hz,mW8=new ro,uW8=new oo,cW8=W.object({conversationId:W.string()});class ejA extends c6{entityType=c9;schema=J40;adapter=SW8;constructor(A={}){super(fR0,H4Q,A,ijA)}getConfig(){return this.config}getTemplates(){return{"summary-list":h7Q,"summary-detail":E7Q,"ai-response":T7Q}}getDataSources(){return[new rjA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:c9,job:{type:b7Q,handler:new ER0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await xC(A,c9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:ujA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:fR0}}},sourceChange:{sourceKind:VA0,sourceTypes:[VA0],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[ru],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:ujA,deduplication:"skip",deduplicationKey:`conversation-memory:${$}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${$}`,pluginId:fR0}}}}}]}parseConversationMessagePayload(A){return cW8.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:$}=this.parseConversationMessagePayload(Q),w=await A.conversations.get($);if(!w)return!1;return Ug({conversation:w,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(ND,V40,mW8),A.entities.register(Cz,F40,uW8),S7Q({context:A,pluginId:this.id}),u7Q({context:A,pluginId:this.id}),s7Q({context:A,pluginId:this.id}),e7Q({context:A,pluginId:this.id,config:this.config}),ojA(A),W4Q({context:A,logger:this.logger,config:this.config})}}function AMA(A={}){return new ejA(A)}zA();v0();v0();b9();var K4Q=W.object({label:W.string(),href:W.string()}),U4Q=W.object({label:W.string(),title:W.string(),detail:W.string()}),pW8=W.object({eyebrow:W.string(),name:W.string(),sub:W.string()}),lW8=W.object({tone:W.enum(["capture","synthesis","share"]),title:W.string(),text:W.string()}),QMA=W.object({captures:W.number(),links:W.number(),topics:W.number(),summaries:W.number(),peers:W.number()}),$s=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:K4Q,secondaryCta:K4Q,inputs:W.array(U4Q).min(1),outputs:W.array(U4Q).min(1),core:pW8,legend:W.array(lW8).min(1)}),$MA=$s.extend({counts:QMA}),G4Q={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."}]},D4Q=new P$($s,{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 cR0(A){return D4Q.parse(A)}function q4Q(A){return D4Q.format(A)}v0();var iW8=W.looseObject({query:W.object({routeId:W.string().default("home"),sectionId:W.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),dW8={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class wMA{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=iW8.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 G4Q;return $s.parse(cR0(w.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(dW8).map(async([$,w])=>[$,await this.countOrZero(A,w)]));return QMA.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 z4Q=W.object({label:W.string(),href:W.string()}),nW8=W.object({label:W.string(),value:W.string(),note:W.string()}),rW8=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:z4Q,secondaryCta:z4Q,signals:W.array(nW8)}),oW8=W.object({phase:W.string(),title:W.string(),text:W.string()}),sW8=W.object({eyebrow:W.string(),title:W.string(),intro:W.string(),steps:W.array(oW8)}),aW8=W.object({label:W.string(),title:W.string(),text:W.string()}),tW8=W.object({title:W.string(),intro:W.string(),cards:W.array(aW8)}),eW8=W.object({title:W.string(),intro:W.string(),points:W.array(W.string())}),AH8={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."]},QH8="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function J4Q({href:A,label:Q}){return C1("a",{href:A,className:QH8,children:Q},void 0,!1,void 0,this)}function $H8({siteInfo:A,children:Q}){let $=[...A.navigation.primary,...A.navigation.secondary],w=A.cta??{buttonText:"Start here",buttonLink:"/about"};return C1(xPA,{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(J4Q,{...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(J4Q,{...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 wH8=({sections:A,siteInfo:Q})=>C1($H8,{siteInfo:Q,children:A},void 0,!1,void 0,this);function BH8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,signals:X}){return C1(co,{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(m70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(m70,{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 XH8({eyebrow:A,title:Q,intro:$,steps:w}){return C1(co,{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 YH8({title:A,intro:Q,cards:$}){return C1(co,{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 ZH8({title:A,intro:Q,points:$}){return C1(co,{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 WH8=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},HH8=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),N40=(A,Q,$=`${Q}s`)=>`${HH8(A)} ${A===1?Q:$}`;function KH8({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:N40(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:N40(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:N40(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:N40(K.summaries,"summary","summaries")}];return C1(co,{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(m70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(m70,{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:[N40(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 ${WH8(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 UH8=W2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:$MA,formatter:{parse:(A)=>$MA.parse({...cR0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>q4Q($s.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:KH8}}),GH8=(A)=>BH8(rW8.parse(A)),DH8=(A)=>XH8(sW8.parse(A)),qH8=(A)=>YH8(tW8.parse(A)),zH8=(A)=>ZH8(eW8.parse(A)),V4Q={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},F4Q={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:GH8,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...V4Q,label:"Primary CTA"},secondaryCta:{...V4Q,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:DH8,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:qH8,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:zH8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},JH8=[{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:AH8}]}],L4Q=N7Q({packageName:"@brains/relay/site",themeProfile:"studio",layout:wH8,routes:JH8,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":UH8},dataSources:[new wMA]}});var I4Q={name:"@brains/relay",version:"0.2.0-alpha.204",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 N4Q=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],_4Q=[...N4Q,"image","site-info","site-content","site-builder"],LH8=[..._4Q,"docs","decks"],IH8=["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."],NH8=mk({name:"relay",version:I4Q.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:L4Q,theme:io,presets:{core:N4Q,default:_4Q,full:LH8},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:IH8,capabilities:[["prompt",sy,void 0],["note",Ry,{}],["link",Cy,{}],["image",_Q0,void 0],["topics",lO0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",AMA,{memoryVisibility:"shared"}],["docs",U90,void 0],["decks",W90,void 0],["agents",$x0,void 0],["assessment",Gx0,void 0],["auth-service",G$0,void 0],["notifications",If0,void 0],["email-resend",_b0,void 0],["cms",uy,{}],["dashboard",Ix,void 0],["directory-sync",CT,{seedContent:!0,seedContentPath:FH8(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Fy,{definitions:F4Q}],["rizom-ecosystem",ay,void 0],["site-info",Ly,void 0],["site-builder",Vy,{}]],interfaces:[["mcp",jO,()=>({})],["discord",Kf,()=>({captureUrls:!0})],["a2a",Gn,()=>({})],["webserver",Nf,()=>({})],["web-chat",Un,()=>({})]],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"}}}),P4Q=NH8;import{readFileSync as $D8}from"fs";import{join as wD8}from"path";import{execSync as BD8}from"child_process";import{parseArgs as bH8}from"util";var jH8={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 $V(A,Q){let $=A[Q];return typeof $==="string"?$:void 0}function Ex(A,Q){let $=A[Q];return typeof $==="boolean"?$:void 0}function b4Q(A){let{values:Q,positionals:$}=bH8({args:A,options:jH8,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:$V(Q,"model"),domain:$V(Q,"domain"),"content-repo":$V(Q,"content-repo"),backend:$V(Q,"backend"),"push-to":$V(Q,"push-to"),"ai-api-key":$V(Q,"ai-api-key"),"no-interactive":Ex(Q,"no-interactive"),preview:Ex(Q,"preview"),deploy:Ex(Q,"deploy"),regen:Ex(Q,"regen"),all:Ex(Q,"all"),only:$V(Q,"only"),"dry-run":Ex(Q,"dry-run"),"startup-check":Ex(Q,"startup-check"),"storage-dir":$V(Q,"storage-dir"),yes:Ex(Q,"yes"),remote:$V(Q,"remote"),token:$V(Q,"token"),outputDir:$V(Q,"outputDir")}}}_40();import{mkdirSync as dG8}from"fs";import{join as nG8}from"path";import{execSync as rG8}from"child_process";var lR0={name:"@rizom/brain",version:"0.2.0-alpha.204",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 S4Q,writeFileSync as b40,chmodSync as j40,existsSync as DMA,readFileSync as qMA}from"fs";import{basename as zMA,dirname as JMA,join as pB,resolve as XK8}from"path";import{fileURLToPath as YK8}from"url";var j4Q=`ARG BUN_VERSION=1.3.10
15011
+ `)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=RW8.parse(B),Y=sjA(X.messages,X.conversationId),Z=X.existingSummary?w4Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null;return new Cx(Q,$,w).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=fW8.parse(B),Y=X.memory?B4Q(Q,X.memory):Q;return new Qs(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=xW8.parse(B),Y=X.memory?B4Q(Q,X.memory):Q;return mR0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=MW8.parse(B),Y=sjA(X.messages,X.conversationId),Z=vW8({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?w4Q({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:w.projectionVersion,visibility:w.memoryVisibility}):null,K=[],U=[],G=CW8({context:Q,conversation:Z,messages:Y,existing:H,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new Cx(G,$,w).projectConversation(X.conversationId),summaries:K.filter((V)=>V.entityType==="summary"),decisions:K.filter((V)=>V.entityType==="decision"),actionItems:K.filter((V)=>V.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=jW8.parse(B);return new Cx(Q,$,w).projectConversation(X.conversationId)})}function w4Q(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 sjA(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 vW8(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 CW8(A){let Q=QV(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 B4Q(A,Q){let $=Q.map(hW8),w=$.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??As(B)}));return{...A,entityService:{...A.entityService,search:async()=>w,listEntities:async({entityType:B})=>$.filter((X)=>X.entityType===B)}}}function hW8(A){if(A.entityType==="summary")return EW8(A);if(A.entityType==="decision")return TW8(A);return yW8(A)}function tjA(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 EW8(A){return{...tjA(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 TW8(A){return{...tjA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:QV(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 yW8(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...tjA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:QV(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 H4Q={name:"@brains/conversation-memory",version:"0.2.0-alpha.206",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 SW8=new hz,mW8=new ro,uW8=new oo,cW8=W.object({conversationId:W.string()});class ejA extends c6{entityType=c9;schema=J40;adapter=SW8;constructor(A={}){super(fR0,H4Q,A,ijA)}getConfig(){return this.config}getTemplates(){return{"summary-list":h7Q,"summary-detail":E7Q,"ai-response":T7Q}}getDataSources(){return[new rjA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:c9,job:{type:b7Q,handler:new ER0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await xC(A,c9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:ujA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:fR0}}},sourceChange:{sourceKind:VA0,sourceTypes:[VA0],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[ru],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:ujA,deduplication:"skip",deduplicationKey:`conversation-memory:${$}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${$}`,pluginId:fR0}}}}}]}parseConversationMessagePayload(A){return cW8.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:$}=this.parseConversationMessagePayload(Q),w=await A.conversations.get($);if(!w)return!1;return Ug({conversation:w,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(ND,V40,mW8),A.entities.register(Cz,F40,uW8),S7Q({context:A,pluginId:this.id}),u7Q({context:A,pluginId:this.id}),s7Q({context:A,pluginId:this.id}),e7Q({context:A,pluginId:this.id,config:this.config}),ojA(A),W4Q({context:A,logger:this.logger,config:this.config})}}function AMA(A={}){return new ejA(A)}zA();v0();v0();b9();var K4Q=W.object({label:W.string(),href:W.string()}),U4Q=W.object({label:W.string(),title:W.string(),detail:W.string()}),pW8=W.object({eyebrow:W.string(),name:W.string(),sub:W.string()}),lW8=W.object({tone:W.enum(["capture","synthesis","share"]),title:W.string(),text:W.string()}),QMA=W.object({captures:W.number(),links:W.number(),topics:W.number(),summaries:W.number(),peers:W.number()}),$s=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:K4Q,secondaryCta:K4Q,inputs:W.array(U4Q).min(1),outputs:W.array(U4Q).min(1),core:pW8,legend:W.array(lW8).min(1)}),$MA=$s.extend({counts:QMA}),G4Q={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."}]},D4Q=new P$($s,{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 cR0(A){return D4Q.parse(A)}function q4Q(A){return D4Q.format(A)}v0();var iW8=W.looseObject({query:W.object({routeId:W.string().default("home"),sectionId:W.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),dW8={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class wMA{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=iW8.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 G4Q;return $s.parse(cR0(w.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(dW8).map(async([$,w])=>[$,await this.countOrZero(A,w)]));return QMA.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 z4Q=W.object({label:W.string(),href:W.string()}),nW8=W.object({label:W.string(),value:W.string(),note:W.string()}),rW8=W.object({eyebrow:W.string(),headline:W.string(),intro:W.string(),primaryCta:z4Q,secondaryCta:z4Q,signals:W.array(nW8)}),oW8=W.object({phase:W.string(),title:W.string(),text:W.string()}),sW8=W.object({eyebrow:W.string(),title:W.string(),intro:W.string(),steps:W.array(oW8)}),aW8=W.object({label:W.string(),title:W.string(),text:W.string()}),tW8=W.object({title:W.string(),intro:W.string(),cards:W.array(aW8)}),eW8=W.object({title:W.string(),intro:W.string(),points:W.array(W.string())}),AH8={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."]},QH8="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function J4Q({href:A,label:Q}){return C1("a",{href:A,className:QH8,children:Q},void 0,!1,void 0,this)}function $H8({siteInfo:A,children:Q}){let $=[...A.navigation.primary,...A.navigation.secondary],w=A.cta??{buttonText:"Start here",buttonLink:"/about"};return C1(xPA,{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(J4Q,{...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(J4Q,{...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 wH8=({sections:A,siteInfo:Q})=>C1($H8,{siteInfo:Q,children:A},void 0,!1,void 0,this);function BH8({eyebrow:A,headline:Q,intro:$,primaryCta:w,secondaryCta:B,signals:X}){return C1(co,{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(m70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(m70,{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 XH8({eyebrow:A,title:Q,intro:$,steps:w}){return C1(co,{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 YH8({title:A,intro:Q,cards:$}){return C1(co,{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 ZH8({title:A,intro:Q,points:$}){return C1(co,{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 WH8=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},HH8=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),N40=(A,Q,$=`${Q}s`)=>`${HH8(A)} ${A===1?Q:$}`;function KH8({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:N40(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:N40(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:N40(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:N40(K.summaries,"summary","summaries")}];return C1(co,{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(m70,{href:w.href,size:"lg",variant:"primary-strong",children:w.label},void 0,!1,void 0,this),C1(m70,{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:[N40(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 ${WH8(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 UH8=W2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:$MA,formatter:{parse:(A)=>$MA.parse({...cR0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>q4Q($s.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:KH8}}),GH8=(A)=>BH8(rW8.parse(A)),DH8=(A)=>XH8(sW8.parse(A)),qH8=(A)=>YH8(tW8.parse(A)),zH8=(A)=>ZH8(eW8.parse(A)),V4Q={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},F4Q={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:GH8,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...V4Q,label:"Primary CTA"},secondaryCta:{...V4Q,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:DH8,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:qH8,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:zH8,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},JH8=[{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:AH8}]}],L4Q=N7Q({packageName:"@brains/relay/site",themeProfile:"studio",layout:wH8,routes:JH8,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":UH8},dataSources:[new wMA]}});var I4Q={name:"@brains/relay",version:"0.2.0-alpha.206",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 N4Q=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],_4Q=[...N4Q,"image","site-info","site-content","site-builder"],LH8=[..._4Q,"docs","decks"],IH8=["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."],NH8=mk({name:"relay",version:I4Q.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:L4Q,theme:io,presets:{core:N4Q,default:_4Q,full:LH8},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:IH8,capabilities:[["prompt",sy,void 0],["note",Ry,{}],["link",Cy,{}],["image",_Q0,void 0],["topics",lO0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",AMA,{memoryVisibility:"shared"}],["docs",U90,void 0],["decks",W90,void 0],["agents",$x0,void 0],["assessment",Gx0,void 0],["auth-service",G$0,void 0],["notifications",If0,void 0],["email-resend",_b0,void 0],["cms",uy,{}],["dashboard",Ix,void 0],["directory-sync",CT,{seedContent:!0,seedContentPath:FH8(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",Fy,{definitions:F4Q}],["rizom-ecosystem",ay,void 0],["site-info",Ly,void 0],["site-builder",Vy,{}]],interfaces:[["mcp",jO,()=>({})],["discord",Kf,()=>({captureUrls:!0})],["a2a",Gn,()=>({})],["webserver",Nf,()=>({})],["web-chat",Un,()=>({})]],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"}}}),P4Q=NH8;import{readFileSync as $D8}from"fs";import{join as wD8}from"path";import{execSync as BD8}from"child_process";import{parseArgs as bH8}from"util";var jH8={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 $V(A,Q){let $=A[Q];return typeof $==="string"?$:void 0}function Ex(A,Q){let $=A[Q];return typeof $==="boolean"?$:void 0}function b4Q(A){let{values:Q,positionals:$}=bH8({args:A,options:jH8,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:$V(Q,"model"),domain:$V(Q,"domain"),"content-repo":$V(Q,"content-repo"),backend:$V(Q,"backend"),"push-to":$V(Q,"push-to"),"ai-api-key":$V(Q,"ai-api-key"),"no-interactive":Ex(Q,"no-interactive"),preview:Ex(Q,"preview"),deploy:Ex(Q,"deploy"),regen:Ex(Q,"regen"),all:Ex(Q,"all"),only:$V(Q,"only"),"dry-run":Ex(Q,"dry-run"),"startup-check":Ex(Q,"startup-check"),"storage-dir":$V(Q,"storage-dir"),yes:Ex(Q,"yes"),remote:$V(Q,"remote"),token:$V(Q,"token"),outputDir:$V(Q,"outputDir")}}}_40();import{mkdirSync as dG8}from"fs";import{join as nG8}from"path";import{execSync as rG8}from"child_process";var lR0={name:"@rizom/brain",version:"0.2.0-alpha.206",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 S4Q,writeFileSync as b40,chmodSync as j40,existsSync as DMA,readFileSync as qMA}from"fs";import{basename as zMA,dirname as JMA,join as pB,resolve as XK8}from"path";import{fileURLToPath as YK8}from"url";var j4Q=`ARG BUN_VERSION=1.3.10
15012
15012
  FROM oven/bun:\${BUN_VERSION}-slim AS runtime
15013
15013
 
15014
15014
  WORKDIR /app