@rizom/brain 0.2.0-alpha.163 → 0.2.0-alpha.164
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 +34 -34
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/site.js +4 -4
- package/dist/site.js.map +1 -1
- package/package.json +1 -1
package/dist/brain.js
CHANGED
|
@@ -430,7 +430,7 @@ ${f}`:"")}function s_0(A,Q,w,B){return async($,f)=>{if(B){let Y={toolName:A,args
|
|
|
430
430
|
hash text NOT NULL,
|
|
431
431
|
created_at numeric
|
|
432
432
|
)
|
|
433
|
-
`;await A.session.run($);let Y=(await A.values(d0`SELECT id, hash, created_at FROM ${d0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let H of w)if(!Y||Number(Y[2])<H.folderMillis){for(let W of H.sql)X.push(A.run(d0.raw(W)));X.push(A.run(d0`INSERT INTO ${d0.identifier(B)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(X)}var uu=i(()=>{_LA();$9()});async function NLA(A,Q){let w=Q?.child("entity-migrate")??_Q.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=QA0(A);w.debug("Running entity database migrations...");try{await wA0($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),await BA0($),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{$.close()}}var PLA=i(()=>{uu();PJ0();S9()});async function jLA(A,Q){let w=Q?.child("job-queue-migrate")??_Q.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=o00(A);w.debug("Running job queue migrations...");try{await s00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{$.close()}}var MLA=i(()=>{uu();WJ0();S9()});async function xLA(A,Q){let w=Q?.child("conversation-migrate")??_Q.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=a00(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var OLA=i(()=>{uu();qJ0();S9()});async function vLA(A,Q){let w=Q?.child("runtime-state-migrate")??_Q.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=L20(A);w.debug("Running runtime state migrations...");try{await _20($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{$.close()}}var RLA=i(()=>{uu();S9();HN0()});import{mkdir as MN0}from"fs/promises";function R20(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function h20(A=process.env){return pV(R20(A))}async function C20(A=process.env){let Q=R20(A);try{await MN0(Q.dataDir,{recursive:!0}),await MN0(Q.cacheDir,{recursive:!0}),await MN0(Q.distDir,{recursive:!0})}catch(w){let B=w instanceof Error&&w.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: ${w instanceof Error?w.message:String(w)}`;throw Error(B,{cause:w})}return pV(Q)}var g20=i(()=>{O20()});class cu{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>C20(),migrateEntities:NLA,migrateJobQueue:jLA,migrateConversations:xLA,migrateRuntimeState:vLA}}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 xN0=i(()=>{PLA();MLA();OLA();RLA();g20()});function Ty2(){return process.env[Ey2]}function hLA(){return Ty2()!=="production"}var Ey2="NODE_ENV";var y20;var ON0=i(()=>{L0();y20=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var gLA;var CLA=i(()=>{gLA={name:"@brains/chat-repl",version:"0.2.0-alpha.163",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 Qw=x((my2,E20)=>{(function(){function A($0,k0){Object.defineProperty(B.prototype,$0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",k0[0],k0[1])}})}function Q($0){if($0===null||typeof $0!=="object")return null;return $0=_0&&$0[_0]||$0["@@iterator"],typeof $0==="function"?$0:null}function w($0,k0){$0=($0=$0.constructor)&&($0.displayName||$0.name)||"ReactClass";var R0=$0+"."+k0;N0[R0]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",k0,$0),N0[R0]=!0)}function B($0,k0,R0){this.props=$0,this.context=k0,this.refs=T0,this.updater=R0||j0}function $(){}function f($0,k0,R0){this.props=$0,this.context=k0,this.refs=T0,this.updater=R0||j0}function Y(){}function X($0){return""+$0}function H($0){try{X($0);var k0=!1}catch(O0){k0=!0}if(k0){k0=console;var R0=k0.error,m0=typeof Symbol==="function"&&Symbol.toStringTag&&$0[Symbol.toStringTag]||$0.constructor.name||"Object";return R0.call(k0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",m0),X($0)}}function W($0){if($0==null)return null;if(typeof $0==="function")return $0.$$typeof===XA?null:$0.displayName||$0.name||null;if(typeof $0==="string")return $0;switch($0){case K0:return"Fragment";case X0:return"Profiler";case c:return"StrictMode";case S0:return"Suspense";case V0:return"SuspenseList";case C0:return"Activity"}if(typeof $0==="object")switch(typeof $0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),$0.$$typeof){case o:return"Portal";case w0:return $0.displayName||"Context";case b0:return($0._context.displayName||"Context")+".Consumer";case h0:var k0=$0.render;return $0=$0.displayName,$0||($0=k0.displayName||k0.name||"",$0=$0!==""?"ForwardRef("+$0+")":"ForwardRef"),$0;case J0:return k0=$0.displayName||null,k0!==null?k0:W($0.type)||"Memo";case P0:k0=$0._payload,$0=$0._init;try{return W($0(k0))}catch(R0){}}return null}function K($0){if($0===K0)return"<>";if(typeof $0==="object"&&$0!==null&&$0.$$typeof===P0)return"<...>";try{var k0=W($0);return k0?"<"+k0+">":"<...>"}catch(R0){return"<...>"}}function U(){var $0=YA.A;return $0===null?null:$0.getOwner()}function G(){return Error("react-stack-top-frame")}function q($0){if(u0.call($0,"key")){var k0=Object.getOwnPropertyDescriptor($0,"key").get;if(k0&&k0.isReactWarning)return!1}return $0.key!==void 0}function b($0,k0){function R0(){UA||(UA=!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)",k0))}R0.isReactWarning=!0,Object.defineProperty($0,"key",{get:R0,configurable:!0})}function J(){var $0=W(this.type);return RA[$0]||(RA[$0]=!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.")),$0=this.props.ref,$0!==void 0?$0:null}function V($0,k0,R0,m0,O0,e0){var n0=R0.ref;return $0={$$typeof:n,type:$0,key:k0,props:R0,_owner:m0},(n0!==void 0?n0:null)!==null?Object.defineProperty($0,"ref",{enumerable:!1,get:J}):Object.defineProperty($0,"ref",{enumerable:!1,value:null}),$0._store={},Object.defineProperty($0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty($0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty($0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:O0}),Object.defineProperty($0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:e0}),Object.freeze&&(Object.freeze($0.props),Object.freeze($0)),$0}function k($0,k0){return k0=V($0.type,k0,$0.props,$0._owner,$0._debugStack,$0._debugTask),$0._store&&(k0._store.validated=$0._store.validated),k0}function N($0){L($0)?$0._store&&($0._store.validated=1):typeof $0==="object"&&$0!==null&&$0.$$typeof===P0&&($0._payload.status==="fulfilled"?L($0._payload.value)&&$0._payload.value._store&&($0._payload.value._store.validated=1):$0._store&&($0._store.validated=1))}function L($0){return typeof $0==="object"&&$0!==null&&$0.$$typeof===n}function O($0){var k0={"=":"=0",":":"=2"};return"$"+$0.replace(/[=:]/g,function(R0){return k0[R0]})}function v($0,k0){return typeof $0==="object"&&$0!==null&&$0.key!=null?(H($0.key),O(""+$0.key)):k0.toString(36)}function h($0){switch($0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason;default:switch(typeof $0.status==="string"?$0.then(Y,Y):($0.status="pending",$0.then(function(k0){$0.status==="pending"&&($0.status="fulfilled",$0.value=k0)},function(k0){$0.status==="pending"&&($0.status="rejected",$0.reason=k0)})),$0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason}}throw $0}function j($0,k0,R0,m0,O0){var e0=typeof $0;if(e0==="undefined"||e0==="boolean")$0=null;var n0=!1;if($0===null)n0=!0;else switch(e0){case"bigint":case"string":case"number":n0=!0;break;case"object":switch($0.$$typeof){case n:case o:n0=!0;break;case P0:return n0=$0._init,j(n0($0._payload),k0,R0,m0,O0)}}if(n0){n0=$0,O0=O0(n0);var kA=m0===""?"."+v(n0,0):m0;return zA(O0)?(R0="",kA!=null&&(R0=kA.replace(o0,"$&/")+"/"),j(O0,k0,R0,"",function(sA){return sA})):O0!=null&&(L(O0)&&(O0.key!=null&&(n0&&n0.key===O0.key||H(O0.key)),R0=k(O0,R0+(O0.key==null||n0&&n0.key===O0.key?"":(""+O0.key).replace(o0,"$&/")+"/")+kA),m0!==""&&n0!=null&&L(n0)&&n0.key==null&&n0._store&&!n0._store.validated&&(R0._store.validated=2),O0=R0),k0.push(O0)),1}if(n0=0,kA=m0===""?".":m0+":",zA($0))for(var LA=0;LA<$0.length;LA++)m0=$0[LA],e0=kA+v(m0,LA),n0+=j(m0,k0,R0,e0,O0);else if(LA=Q($0),typeof LA==="function")for(LA===$0.entries&&(QA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),QA=!0),$0=LA.call($0),LA=0;!(m0=$0.next()).done;)m0=m0.value,e0=kA+v(m0,LA++),n0+=j(m0,k0,R0,e0,O0);else if(e0==="object"){if(typeof $0.then==="function")return j(h($0),k0,R0,m0,O0);throw k0=String($0),Error("Objects are not valid as a React child (found: "+(k0==="[object Object]"?"object with keys {"+Object.keys($0).join(", ")+"}":k0)+"). If you meant to render a collection of children, use an array instead.")}return n0}function E($0,k0,R0){if($0==null)return $0;var m0=[],O0=0;return j($0,m0,"","",function(e0){return k0.call(R0,e0,O0++)}),m0}function S($0){if($0._status===-1){var k0=$0._ioInfo;k0!=null&&(k0.start=k0.end=performance.now()),k0=$0._result;var R0=k0();if(R0.then(function(O0){if($0._status===0||$0._status===-1){$0._status=1,$0._result=O0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),R0.status===void 0&&(R0.status="fulfilled",R0.value=O0)}},function(O0){if($0._status===0||$0._status===-1){$0._status=2,$0._result=O0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),R0.status===void 0&&(R0.status="rejected",R0.reason=O0)}}),k0=$0._ioInfo,k0!=null){k0.value=R0;var m0=R0.displayName;typeof m0==="string"&&(k0.name=m0)}$0._status===-1&&($0._status=0,$0._result=R0)}if($0._status===1)return k0=$0._result,k0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
433
|
+
`;await A.session.run($);let Y=(await A.values(d0`SELECT id, hash, created_at FROM ${d0.identifier(B)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,X=[];for(let H of w)if(!Y||Number(Y[2])<H.folderMillis){for(let W of H.sql)X.push(A.run(d0.raw(W)));X.push(A.run(d0`INSERT INTO ${d0.identifier(B)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(X)}var uu=i(()=>{_LA();$9()});async function NLA(A,Q){let w=Q?.child("entity-migrate")??_Q.getInstance().child("entity-migrate"),{db:B,client:$,url:f}=QA0(A);w.debug("Running entity database migrations...");try{await wA0($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),await BA0($),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{$.close()}}var PLA=i(()=>{uu();PJ0();S9()});async function jLA(A,Q){let w=Q?.child("job-queue-migrate")??_Q.getInstance().child("job-queue-migrate"),{db:B,client:$,url:f}=o00(A);w.debug("Running job queue migrations...");try{await s00($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{$.close()}}var MLA=i(()=>{uu();WJ0();S9()});async function xLA(A,Q){let w=Q?.child("conversation-migrate")??_Q.getInstance().child("conversation-migrate"),{db:B,client:$,url:f}=a00(A);w.debug("Running conversation database migrations...");try{if(f.startsWith("file:"))await $.execute("PRAGMA journal_mode = WAL");let X=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{$.close()}}var OLA=i(()=>{uu();qJ0();S9()});async function vLA(A,Q){let w=Q?.child("runtime-state-migrate")??_Q.getInstance().child("runtime-state-migrate"),{db:B,client:$,url:f}=L20(A);w.debug("Running runtime state migrations...");try{await _20($,f);let X=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await wJ(B,{migrationsFolder:X}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{$.close()}}var RLA=i(()=>{uu();S9();HN0()});import{mkdir as MN0}from"fs/promises";function R20(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function h20(A=process.env){return pV(R20(A))}async function C20(A=process.env){let Q=R20(A);try{await MN0(Q.dataDir,{recursive:!0}),await MN0(Q.cacheDir,{recursive:!0}),await MN0(Q.distDir,{recursive:!0})}catch(w){let B=w instanceof Error&&w.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: ${w instanceof Error?w.message:String(w)}`;throw Error(B,{cause:w})}return pV(Q)}var g20=i(()=>{O20()});class cu{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>C20(),migrateEntities:NLA,migrateJobQueue:jLA,migrateConversations:xLA,migrateRuntimeState:vLA}}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 xN0=i(()=>{PLA();MLA();OLA();RLA();g20()});function Ty2(){return process.env[Ey2]}function hLA(){return Ty2()!=="production"}var Ey2="NODE_ENV";var y20;var ON0=i(()=>{L0();y20=Z.object({theme:Z.object({primaryColor:Z.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:Z.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var gLA;var CLA=i(()=>{gLA={name:"@brains/chat-repl",version:"0.2.0-alpha.164",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 Qw=x((my2,E20)=>{(function(){function A($0,k0){Object.defineProperty(B.prototype,$0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",k0[0],k0[1])}})}function Q($0){if($0===null||typeof $0!=="object")return null;return $0=_0&&$0[_0]||$0["@@iterator"],typeof $0==="function"?$0:null}function w($0,k0){$0=($0=$0.constructor)&&($0.displayName||$0.name)||"ReactClass";var R0=$0+"."+k0;N0[R0]||(console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.",k0,$0),N0[R0]=!0)}function B($0,k0,R0){this.props=$0,this.context=k0,this.refs=T0,this.updater=R0||j0}function $(){}function f($0,k0,R0){this.props=$0,this.context=k0,this.refs=T0,this.updater=R0||j0}function Y(){}function X($0){return""+$0}function H($0){try{X($0);var k0=!1}catch(O0){k0=!0}if(k0){k0=console;var R0=k0.error,m0=typeof Symbol==="function"&&Symbol.toStringTag&&$0[Symbol.toStringTag]||$0.constructor.name||"Object";return R0.call(k0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",m0),X($0)}}function W($0){if($0==null)return null;if(typeof $0==="function")return $0.$$typeof===XA?null:$0.displayName||$0.name||null;if(typeof $0==="string")return $0;switch($0){case K0:return"Fragment";case X0:return"Profiler";case c:return"StrictMode";case S0:return"Suspense";case V0:return"SuspenseList";case C0:return"Activity"}if(typeof $0==="object")switch(typeof $0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),$0.$$typeof){case o:return"Portal";case w0:return $0.displayName||"Context";case b0:return($0._context.displayName||"Context")+".Consumer";case h0:var k0=$0.render;return $0=$0.displayName,$0||($0=k0.displayName||k0.name||"",$0=$0!==""?"ForwardRef("+$0+")":"ForwardRef"),$0;case J0:return k0=$0.displayName||null,k0!==null?k0:W($0.type)||"Memo";case P0:k0=$0._payload,$0=$0._init;try{return W($0(k0))}catch(R0){}}return null}function K($0){if($0===K0)return"<>";if(typeof $0==="object"&&$0!==null&&$0.$$typeof===P0)return"<...>";try{var k0=W($0);return k0?"<"+k0+">":"<...>"}catch(R0){return"<...>"}}function U(){var $0=YA.A;return $0===null?null:$0.getOwner()}function G(){return Error("react-stack-top-frame")}function q($0){if(u0.call($0,"key")){var k0=Object.getOwnPropertyDescriptor($0,"key").get;if(k0&&k0.isReactWarning)return!1}return $0.key!==void 0}function b($0,k0){function R0(){UA||(UA=!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)",k0))}R0.isReactWarning=!0,Object.defineProperty($0,"key",{get:R0,configurable:!0})}function J(){var $0=W(this.type);return RA[$0]||(RA[$0]=!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.")),$0=this.props.ref,$0!==void 0?$0:null}function V($0,k0,R0,m0,O0,e0){var n0=R0.ref;return $0={$$typeof:n,type:$0,key:k0,props:R0,_owner:m0},(n0!==void 0?n0:null)!==null?Object.defineProperty($0,"ref",{enumerable:!1,get:J}):Object.defineProperty($0,"ref",{enumerable:!1,value:null}),$0._store={},Object.defineProperty($0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty($0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty($0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:O0}),Object.defineProperty($0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:e0}),Object.freeze&&(Object.freeze($0.props),Object.freeze($0)),$0}function k($0,k0){return k0=V($0.type,k0,$0.props,$0._owner,$0._debugStack,$0._debugTask),$0._store&&(k0._store.validated=$0._store.validated),k0}function N($0){L($0)?$0._store&&($0._store.validated=1):typeof $0==="object"&&$0!==null&&$0.$$typeof===P0&&($0._payload.status==="fulfilled"?L($0._payload.value)&&$0._payload.value._store&&($0._payload.value._store.validated=1):$0._store&&($0._store.validated=1))}function L($0){return typeof $0==="object"&&$0!==null&&$0.$$typeof===n}function O($0){var k0={"=":"=0",":":"=2"};return"$"+$0.replace(/[=:]/g,function(R0){return k0[R0]})}function v($0,k0){return typeof $0==="object"&&$0!==null&&$0.key!=null?(H($0.key),O(""+$0.key)):k0.toString(36)}function h($0){switch($0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason;default:switch(typeof $0.status==="string"?$0.then(Y,Y):($0.status="pending",$0.then(function(k0){$0.status==="pending"&&($0.status="fulfilled",$0.value=k0)},function(k0){$0.status==="pending"&&($0.status="rejected",$0.reason=k0)})),$0.status){case"fulfilled":return $0.value;case"rejected":throw $0.reason}}throw $0}function j($0,k0,R0,m0,O0){var e0=typeof $0;if(e0==="undefined"||e0==="boolean")$0=null;var n0=!1;if($0===null)n0=!0;else switch(e0){case"bigint":case"string":case"number":n0=!0;break;case"object":switch($0.$$typeof){case n:case o:n0=!0;break;case P0:return n0=$0._init,j(n0($0._payload),k0,R0,m0,O0)}}if(n0){n0=$0,O0=O0(n0);var kA=m0===""?"."+v(n0,0):m0;return zA(O0)?(R0="",kA!=null&&(R0=kA.replace(o0,"$&/")+"/"),j(O0,k0,R0,"",function(sA){return sA})):O0!=null&&(L(O0)&&(O0.key!=null&&(n0&&n0.key===O0.key||H(O0.key)),R0=k(O0,R0+(O0.key==null||n0&&n0.key===O0.key?"":(""+O0.key).replace(o0,"$&/")+"/")+kA),m0!==""&&n0!=null&&L(n0)&&n0.key==null&&n0._store&&!n0._store.validated&&(R0._store.validated=2),O0=R0),k0.push(O0)),1}if(n0=0,kA=m0===""?".":m0+":",zA($0))for(var LA=0;LA<$0.length;LA++)m0=$0[LA],e0=kA+v(m0,LA),n0+=j(m0,k0,R0,e0,O0);else if(LA=Q($0),typeof LA==="function")for(LA===$0.entries&&(QA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),QA=!0),$0=LA.call($0),LA=0;!(m0=$0.next()).done;)m0=m0.value,e0=kA+v(m0,LA++),n0+=j(m0,k0,R0,e0,O0);else if(e0==="object"){if(typeof $0.then==="function")return j(h($0),k0,R0,m0,O0);throw k0=String($0),Error("Objects are not valid as a React child (found: "+(k0==="[object Object]"?"object with keys {"+Object.keys($0).join(", ")+"}":k0)+"). If you meant to render a collection of children, use an array instead.")}return n0}function E($0,k0,R0){if($0==null)return $0;var m0=[],O0=0;return j($0,m0,"","",function(e0){return k0.call(R0,e0,O0++)}),m0}function S($0){if($0._status===-1){var k0=$0._ioInfo;k0!=null&&(k0.start=k0.end=performance.now()),k0=$0._result;var R0=k0();if(R0.then(function(O0){if($0._status===0||$0._status===-1){$0._status=1,$0._result=O0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),R0.status===void 0&&(R0.status="fulfilled",R0.value=O0)}},function(O0){if($0._status===0||$0._status===-1){$0._status=2,$0._result=O0;var e0=$0._ioInfo;e0!=null&&(e0.end=performance.now()),R0.status===void 0&&(R0.status="rejected",R0.reason=O0)}}),k0=$0._ioInfo,k0!=null){k0.value=R0;var m0=R0.displayName;typeof m0==="string"&&(k0.name=m0)}$0._status===-1&&($0._status=0,$0._result=R0)}if($0._status===1)return k0=$0._result,k0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
434
434
|
|
|
435
435
|
Your code should look like:
|
|
436
436
|
const MyComponent = lazy(() => import('./MyComponent'))
|
|
@@ -1717,7 +1717,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
|
|
|
1717
1717
|
Title: "${A.entityTitle??X}"
|
|
1718
1718
|
|
|
1719
1719
|
Content:
|
|
1720
|
-
${K}`,wp2);W=`${B.trim()} ${k.imagePrompt}`}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:SA(k)})}}await this.reportProgress(w,{progress:oQ.PROCESS,message:"Generating image"});let U=this.context.identity.get(),G=this.context.identity.getProfile(),b=WOA(U,G)+W,J;try{J=await this.context.ai.generateImage(b,{...$&&{aspectRatio:$}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:SA(k)}),f$.failure(k)}await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let V=dX.createImageEntity({dataUrl:J.dataUrl,title:X,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}});if(await Lf({entityService:this.context.entityService,entity:{...V,id:H}}),this.logger.debug("Created image entity",{imageId:H}),f&&Y){await this.reportProgress(w,{progress:oQ.SAVE,message:`Updating ${f} with cover image`});let k=await FL(this.context.entityService,f,Y,this.logger);if(!k)return f$.failure(Error(`Target entity not found: ${f}/${Y}`));let N=tL(k,H);await this.context.entities.update(N),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:Y,imageId:H})}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:f,targetEntityId:Y}),{success:!0,imageId:H}}catch(W){let K=SA(W);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await PG({entityService:this.context.entityService,entityType:"image",id:H,error:K}),f$.failure(W)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}wA();L0();T6();_4();var $p2=Z.object({sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),imageId:Z.string().min(1),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional(),targetImageField:Z.enum(["coverImageId","ogImageId"]).optional()});class ej0 extends ew{context;constructor(A,Q){super(Q,{schema:$p2,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,w){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:oQ.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return f$.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return f$.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=dX.createImageEntity({dataUrl:IN0(B.data.toString("base64"),$),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await Lf({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=SA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await PG({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),f$.failure(B)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find((w)=>w.metadata.status!=="pending"&&w.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let w=await FL(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let $=(A.targetImageField??"coverImageId")==="ogImageId"?Su(w,Q):tL(w,Q);await this.context.entities.update($)}}wA();L0();T6();_4();D2();var sv={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function Xw0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function Zw0(A){let Q=fp2(A.title,A.filename),w=H1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function KOA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function fp2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var Yp2=Z.object({uploadId:Z.string().min(1),imageId:Z.string().min(1).optional(),title:Z.string().optional()});class AM0 extends ew{context;constructor(A,Q){super(A,{schema:Yp2,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let B=await this.context.uploads.scoped(sv).read(A.uploadId);if(!Xw0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=Zw0({filename:B.record.filename,...A.title!==void 0?{title:A.title}:{}}),f=A.imageId??$.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),X=dX.createImageEntity({dataUrl:KOA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),H=await Lf({entityService:this.context.entityService,entity:{id:f,...X,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch(B){if(A.imageId)await PG({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:SA(B)});return f$.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var UOA={name:"@brains/image-plugin",version:"0.2.0-alpha.163",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 Zp2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",Hp2=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function CK(A){let Q=A?.trim();if(!Q)return;return Q}function Wp2(A){let Q=CK(A.prompt);if(Q)return Q;let w=CK(A.content);if(w&&!tj0(w))return w;return}function Kp2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return H1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function GOA(A){let Q=CK(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return H1(Q)}async function Up2(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,B=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return B?`${w}:${B.contentHash}`:w}function QM0(A,Q="generated"){let w=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${w}`,downloadUrl:`/api/chat/attachments/image?id=${w}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function Gp2(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 wM0 extends sQ{entityType=dX.entityType;schema=Eu;adapter=dX;constructor(A={}){super("image",UOA,A,Hp2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===sv.refKind)return this.promoteUpload(A,w);let B=Wp2(A),$=CK(A.targetEntityType),f=CK(A.targetEntityId),Y=$===this.entityType?f:void 0,X=A.from;if(X?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:X},w);if(!$||!f||Y){if(!B)return{kind:"continue",input:A};let G=CK(A.title)??Y,q=GOA({prompt:B,...G&&{title:G}});await this.createPendingImage(w,{id:q,title:G??B.slice(0,60).trim(),alt:G??B.slice(0,60).trim(),attachmentType:"generated"});let b=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:b,attachment:QM0(q)}}}}let H=await V4(w.entityService,$,f,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let W=fw0(H.entity.content),K=GOA({prompt:B,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:H.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...W&&{entityContent:W}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:QM0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==sv.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(sv).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!Xw0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=Zw0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:String(X)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:B,imageId:f.id,title:f.title}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:Y,attachment:Gp2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=CK(A.from.sourceEntityType),B=CK(A.from.sourceEntityId),$=CK(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await V4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let Y=CK(A.targetEntityType),X=CK(A.targetEntityId),H;if(Y&&X){let q=await V4(Q.entityService,Y,X,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let W={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},K=await Up2(Q,W),U=Kp2(W);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:W.sourceEntityType,sourceEntityId:W.sourceEntityId,attachmentType:$,dedupKey:K});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...W,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:QM0(U,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=dX.createImageEntity({dataUrl:Zp2,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 LL({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new Yw0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let B=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return B.kind==="handled"?B.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new Yw0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new ej0(A,this.logger)),A.jobs.registerHandler("upload-promote",new AM0(this.logger.child("UploadPromotionJobHandler"),A))}}function uc(A={}){return new wM0(A)}wA();import{StdioServerTransport as zp2}from"@modelcontextprotocol/sdk/server/stdio.js";L0();var Dp2=Z.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 DOA(){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 BM0(){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 Hw0(A){let Q=Dp2.safeParse(A);if(Q.success)return{info:(w,...B)=>Q.data.info(w,...B),debug:(w,...B)=>Q.data.debug(w,...B),error:(w,...B)=>Q.data.error(w,...B),warn:(w,...B)=>Q.data.warn(w,...B)};return BM0()}class gK{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return gK.instance??=new gK(A),gK.instance}static resetInstance(){if(gK.instance)gK.instance.stop(),gK.instance=null}static createFresh(A){return new gK(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?Hw0(this.config.logger):DOA()}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 zp2,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 qp2,timingSafeEqual as bp2}from"crypto";import{WebStandardStreamableHTTPServerTransport as Vp2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as Jp2}from"@modelcontextprotocol/sdk/types.js";L0();var Ip2=1800000,Fp2=60000,kp2={"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"},Lp2=Z.looseObject({code:Z.string().optional()});function _p2(A){let Q=new URL(A.url),B=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),$=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!$)return Q.origin;return`${B??Q.protocol.replace(":","")}://${$}`}class uz{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;evictionTimer=null;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?Hw0(this.config.logger):BM0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??Ip2,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,Fp2)),this.evictionTimer.unref(),!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return uz.instance??=new uz(A),uz.instance}static resetInstance(){uz.instance=null}static createFresh(A){return new uz(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(kp2))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let B=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return B;let $=new Headers(B.headers);return $.set("WWW-Authenticate",w),new Response(B.body,{status:B.status,statusText:B.statusText,headers:$})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${_p2(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([$,f])=>`${$}="${Np2(f)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let w=A.headers.get("authorization");if(!w?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let B=w.substring(7);if(!Pp2(B,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:B,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let B=await this.authConfig.verifyBearerToken?.(A);if(!B)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let $=this.authConfig.requiredScopes??[],f=$.filter((Y)=>!B.scope?.includes(Y));if(f.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${f.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:$.join(" ")}));return this.logger.debug("Authentication successful"),{token:w.substring(7),clientId:B.subject,scopes:B.scope??[],extra:{subject:B.subject}}}catch(B){return this.logger.warn("Authentication failed: Invalid token",B),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}evictIdleSessions(){let A=Date.now();for(let[Q,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${Q}`),this.sessionLastActivity.delete(Q);let B=this.transports[Q];if(B)delete this.transports[Q],B.close().catch(($)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,$)})}}async handleMcpRequest(A,Q){let w=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!w||!this.transports[w])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession(w),this.logger.debug(`GET /mcp - SSE stream for session ${w}`),this.withCors(await this.transports[w].handleRequest(A,{authInfo:Q}))}if(A.method==="DELETE"){if(!w||!this.transports[w])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${w}`),this.withCors(await this.transports[w].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 B;try{B=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: ${w??"new"}`);try{let $;if(w&&this.transports[w])$=this.transports[w],this.touchSession(w);else if(!w&&Jp2(B))$=new Vp2({sessionIdGenerator:()=>qp2(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=$,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($);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await $.handleRequest(A,{parsedBody:B,authInfo:Q}))}catch($){return this.logger.error("MCP transport error:",$),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 w=await this.authenticate(A);if(w instanceof Response)return w;let B=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,B);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:(w)=>this.handleRequest(w)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(w){let B=Lp2.safeParse(w);if(B.success&&B.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){if(this.evictionTimer)clearInterval(this.evictionTimer),this.evictionTimer=null;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 Np2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function Pp2(A,Q){let w=Buffer.from(A),B=Buffer.from(Q);if(w.length!==B.length)return!1;return bp2(w,B)}import{randomUUID as hp2}from"crypto";import{chmod as jp2,mkdir as Mp2,readFile as xp2,rename as zOA,writeFile as Op2}from"fs/promises";import{dirname as vp2}from"path";class vf{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,w)=>{console.error(Q,w)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await xp2(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 Mp2(vp2(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await Op2(Q,`${JSON.stringify(A,null,2)}
|
|
1720
|
+
${K}`,wp2);W=`${B.trim()} ${k.imagePrompt}`}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:SA(k)})}}await this.reportProgress(w,{progress:oQ.PROCESS,message:"Generating image"});let U=this.context.identity.get(),G=this.context.identity.getProfile(),b=WOA(U,G)+W,J;try{J=await this.context.ai.generateImage(b,{...$&&{aspectRatio:$}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:SA(k)}),f$.failure(k)}await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let V=dX.createImageEntity({dataUrl:J.dataUrl,title:X,status:"draft",attachmentType:"generated",...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}});if(await Lf({entityService:this.context.entityService,entity:{...V,id:H}}),this.logger.debug("Created image entity",{imageId:H}),f&&Y){await this.reportProgress(w,{progress:oQ.SAVE,message:`Updating ${f} with cover image`});let k=await FL(this.context.entityService,f,Y,this.logger);if(!k)return f$.failure(Error(`Target entity not found: ${f}/${Y}`));let N=tL(k,H);await this.context.entities.update(N),this.logger.debug("Updated target entity with cover image",{targetEntityType:f,targetEntityId:Y,imageId:H})}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:f,targetEntityId:Y}),{success:!0,imageId:H}}catch(W){let K=SA(W);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await PG({entityService:this.context.entityService,entityType:"image",id:H,error:K}),f$.failure(W)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}wA();L0();T6();_4();var $p2=Z.object({sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),imageId:Z.string().min(1),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional(),targetImageField:Z.enum(["coverImageId","ogImageId"]).optional()});class ej0 extends ew{context;constructor(A,Q){super(Q,{schema:$p2,jobTypeName:"image-render-source"});this.context=A}async process(A,Q,w){this.logger.debug("Starting source image render job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,imageId:A.imageId});try{if(A.replace!==!0&&A.dedupKey){let Y=await this.findImageByDedupKey(A.dedupKey);if(Y)return await this.updateTarget(A,Y.id),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:oQ.PROCESS,message:"Rendering source image"});let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)return f$.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if(B.type!=="image")return f$.failure(Error(`Attachment provider returned ${B.type}; expected image`));await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let $=B.mimeType.split("/")[1]??"png",f=dX.createImageEntity({dataUrl:IN0(B.data.toString("base64"),$),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await Lf({entityService:this.context.entityService,entity:{...f,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch(B){let $=SA(B);return this.logger.error("Source image render job failed",{jobId:Q,error:$}),await PG({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:$}),f$.failure(B)}}async findImageByDedupKey(A){return(await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{dedupKey:A}}}})).find((w)=>w.metadata.status!=="pending"&&w.metadata.status!=="failed")}async updateTarget(A,Q){if(!A.targetEntityType||!A.targetEntityId)return;let w=await FL(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let $=(A.targetImageField??"coverImageId")==="ogImageId"?Su(w,Q):tL(w,Q);await this.context.entities.update($)}}wA();L0();T6();_4();D2();var sv={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function Xw0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function Zw0(A){let Q=fp2(A.title,A.filename),w=H1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function KOA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function fp2(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var Yp2=Z.object({uploadId:Z.string().min(1),imageId:Z.string().min(1).optional(),title:Z.string().optional()});class AM0 extends ew{context;constructor(A,Q){super(A,{schema:Yp2,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let B=await this.context.uploads.scoped(sv).read(A.uploadId);if(!Xw0(B.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let $=Zw0({filename:B.record.filename,...A.title!==void 0?{title:A.title}:{}}),f=A.imageId??$.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),X=dX.createImageEntity({dataUrl:KOA(B.record.mediaType,B.content),title:$.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded"}),H=await Lf({entityService:this.context.entityService,entity:{id:f,...X,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch(B){if(A.imageId)await PG({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:SA(B)});return f$.failure(B)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var UOA={name:"@brains/image-plugin",version:"0.2.0-alpha.164",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 Zp2="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",Hp2=Z.object({defaultAspectRatio:Z.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function CK(A){let Q=A?.trim();if(!Q)return;return Q}function Wp2(A){let Q=CK(A.prompt);if(Q)return Q;let w=CK(A.content);if(w&&!tj0(w))return w;return}function Kp2(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return H1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function GOA(A){let Q=CK(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return H1(Q)}async function Up2(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,B=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return B?`${w}:${B.contentHash}`:w}function QM0(A,Q="generated"){let w=encodeURIComponent(A);return{mediaType:"image/png",url:`/api/chat/attachments/image?id=${w}`,downloadUrl:`/api/chat/attachments/image?id=${w}&download=1`,filename:`${A}.png`,source:{entityType:"image",entityId:A,attachmentType:Q}}}function Gp2(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 wM0 extends sQ{entityType=dX.entityType;schema=Eu;adapter=dX;constructor(A={}){super("image",UOA,A,Hp2)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===sv.refKind)return this.promoteUpload(A,w);let B=Wp2(A),$=CK(A.targetEntityType),f=CK(A.targetEntityId),Y=$===this.entityType?f:void 0,X=A.from;if(X?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:X},w);if(!$||!f||Y){if(!B)return{kind:"continue",input:A};let G=CK(A.title)??Y,q=GOA({prompt:B,...G&&{title:G}});await this.createPendingImage(w,{id:q,title:G??B.slice(0,60).trim(),alt:G??B.slice(0,60).trim(),attachmentType:"generated"});let b=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:b,attachment:QM0(q)}}}}let H=await V4(w.entityService,$,f,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!B)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let W=fw0(H.entity.content),K=GOA({prompt:B,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:$,sourceEntityId:H.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:B,...A.title&&{title:A.title},targetEntityType:$,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...W&&{entityContent:W}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:QM0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==sv.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B=w.id,$;try{$=await Q.uploads.scoped(sv).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!Xw0($.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let f;try{f=Zw0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}})}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:String(X)}}}await this.createPendingImage(Q,{id:f.id,title:f.title,alt:f.title,sourceUploadId:B,sourceFilename:$.filename,sourceMediaType:$.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:B,imageId:f.id,title:f.title}});return{kind:"handled",result:{success:!0,data:{entityId:f.id,status:"generating",jobId:Y,attachment:Gp2({mediaType:$.mediaType,entityId:f.id,filename:$.filename})}}}}async enqueueSourceImageRender(A,Q){let w=CK(A.from.sourceEntityType),B=CK(A.from.sourceEntityId),$=CK(A.from.attachmentType);if(!w||!B||!$)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let f=await V4(Q.entityService,w,B,this.logger,"Source entity");if(!f.ok)return{kind:"handled",result:{success:!1,error:f.error}};let Y=CK(A.targetEntityType),X=CK(A.targetEntityId),H;if(Y&&X){let q=await V4(Q.entityService,Y,X,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let W={sourceEntityType:w,sourceEntityId:f.entity.id,attachmentType:$},K=await Up2(Q,W),U=Kp2(W);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:W.sourceEntityType,sourceEntityId:W.sourceEntityId,attachmentType:$,dedupKey:K});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...W,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...$==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:QM0(U,$)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),B=dX.createImageEntity({dataUrl:Zp2,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 LL({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getInstructions(){return"Image entities store durable images. Standalone generated images are valid system_generate image calls with a prompt source and no target fields. A prompt source creates a new image; never use it to describe, analyze, or discuss an existing uploaded image. For uploaded-image discussion, answer directly from the attachment/context; if the user later asks to save that discussion as a note, create entityType note from prior-response or exact text. targetEntityType and targetEntityId are only for attaching the result to an existing entity as coverImageId. Cover images and OG/social preview images are distinct domain concepts: cover-image fields use coverImageId, while OG/Open Graph/social preview fields use ogImageId. Rendered OG/social preview images are deterministic attachment-source images with attachmentType og-image."}createGenerationHandler(A){return new Yw0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let B=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return B.kind==="handled"?B.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new Yw0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new ej0(A,this.logger)),A.jobs.registerHandler("upload-promote",new AM0(this.logger.child("UploadPromotionJobHandler"),A))}}function uc(A={}){return new wM0(A)}wA();import{StdioServerTransport as zp2}from"@modelcontextprotocol/sdk/server/stdio.js";L0();var Dp2=Z.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 DOA(){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 BM0(){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 Hw0(A){let Q=Dp2.safeParse(A);if(Q.success)return{info:(w,...B)=>Q.data.info(w,...B),debug:(w,...B)=>Q.data.debug(w,...B),error:(w,...B)=>Q.data.error(w,...B),warn:(w,...B)=>Q.data.warn(w,...B)};return BM0()}class gK{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return gK.instance??=new gK(A),gK.instance}static resetInstance(){if(gK.instance)gK.instance.stop(),gK.instance=null}static createFresh(A){return new gK(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?Hw0(this.config.logger):DOA()}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 zp2,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 qp2,timingSafeEqual as bp2}from"crypto";import{WebStandardStreamableHTTPServerTransport as Vp2}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as Jp2}from"@modelcontextprotocol/sdk/types.js";L0();var Ip2=1800000,Fp2=60000,kp2={"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"},Lp2=Z.looseObject({code:Z.string().optional()});function _p2(A){let Q=new URL(A.url),B=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),$=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!$)return Q.origin;return`${B??Q.protocol.replace(":","")}://${$}`}class uz{static instance=null;transports={};sessionLastActivity=new Map;mcpServer=null;mcpTransport=null;server=null;boundPort=null;evictionTimer=null;config;logger;authConfig;sessionIdleTtlMs;constructor(A={}){if(this.config=A,this.logger=this.config.logger?Hw0(this.config.logger):BM0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??Ip2,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,Fp2)),this.evictionTimer.unref(),!this.authConfig.disabled&&!this.authConfig.token&&!this.authConfig.verifyBearerToken)throw Error("MCP HTTP transport requires an auth token or bearer token verifier. Set MCP_AUTH_TOKEN, configure OAuth verification, or pass auth: { disabled: true } for local dev.")}static getInstance(A){return uz.instance??=new uz(A),uz.instance}static resetInstance(){uz.instance=null}static createFresh(A){return new uz(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(kp2))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let B=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return B;let $=new Headers(B.headers);return $.set("WWW-Authenticate",w),new Response(B.body,{status:B.status,statusText:B.statusText,headers:$})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${_p2(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([$,f])=>`${$}="${Np2(f)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let w=A.headers.get("authorization");if(!w?.startsWith("Bearer "))return this.logger.warn("Authentication failed: Missing Bearer token"),this.getAuthErrorResponse("Unauthorized: Bearer token required",401,this.getBearerChallenge(A,{realm:"mcp"}));if(this.authConfig.token){let B=w.substring(7);if(!Pp2(B,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:B,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let B=await this.authConfig.verifyBearerToken?.(A);if(!B)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let $=this.authConfig.requiredScopes??[],f=$.filter((Y)=>!B.scope?.includes(Y));if(f.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${f.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:$.join(" ")}));return this.logger.debug("Authentication successful"),{token:w.substring(7),clientId:B.subject,scopes:B.scope??[],extra:{subject:B.subject}}}catch(B){return this.logger.warn("Authentication failed: Invalid token",B),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}))}}touchSession(A){this.sessionLastActivity.set(A,Date.now())}evictIdleSessions(){let A=Date.now();for(let[Q,w]of this.sessionLastActivity){if(A-w<this.sessionIdleTtlMs)continue;this.logger.info(`Evicting idle session ${Q}`),this.sessionLastActivity.delete(Q);let B=this.transports[Q];if(B)delete this.transports[Q],B.close().catch(($)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,$)})}}async handleMcpRequest(A,Q){let w=A.headers.get("mcp-session-id")??void 0;if(A.method==="GET"){if(!w||!this.transports[w])return this.createTextResponse("Invalid or missing session ID",400);return this.touchSession(w),this.logger.debug(`GET /mcp - SSE stream for session ${w}`),this.withCors(await this.transports[w].handleRequest(A,{authInfo:Q}))}if(A.method==="DELETE"){if(!w||!this.transports[w])return this.createTextResponse("Invalid or missing session ID",400);return this.logger.info(`DELETE /mcp - Terminating session ${w}`),this.withCors(await this.transports[w].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 B;try{B=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: ${w??"new"}`);try{let $;if(w&&this.transports[w])$=this.transports[w],this.touchSession(w);else if(!w&&Jp2(B))$=new Vp2({sessionIdGenerator:()=>qp2(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=$,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($);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await $.handleRequest(A,{parsedBody:B,authInfo:Q}))}catch($){return this.logger.error("MCP transport error:",$),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 w=await this.authenticate(A);if(w instanceof Response)return w;let B=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,B);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:(w)=>this.handleRequest(w)}),this.boundPort=this.server.port??A,this.logger.info(`StreamableHTTP server listening on http://${Q}:${this.boundPort}/mcp`)}catch(w){let B=Lp2.safeParse(w);if(B.success&&B.data.code==="EADDRINUSE")this.logger.error(`Port ${A} is already in use`);throw w}}async stop(){if(this.evictionTimer)clearInterval(this.evictionTimer),this.evictionTimer=null;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 Np2(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function Pp2(A,Q){let w=Buffer.from(A),B=Buffer.from(Q);if(w.length!==B.length)return!1;return bp2(w,B)}import{randomUUID as hp2}from"crypto";import{chmod as jp2,mkdir as Mp2,readFile as xp2,rename as zOA,writeFile as Op2}from"fs/promises";import{dirname as vp2}from"path";class vf{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,w)=>{console.error(Q,w)})}async enqueueWrite(A){return this.writeQueue=this.writeQueue.then(A,A),this.writeQueue}async read(){let A;try{A=await xp2(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 Mp2(vp2(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await Op2(Q,`${JSON.stringify(A,null,2)}
|
|
1721
1721
|
`,{mode:384}),await jp2(Q,384),await zOA(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 zOA(this.filePath,Q)}catch(w){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,w)}}}function av(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function Ww0(){let A=new Date;return A.setDate(A.getDate()-1),A}function qOA(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function K9(){return Math.floor(Date.now()/1000)}L0();import{join as Cp2}from"path";function bOA(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function VOA(A){try{return new URL(A)}catch{return}}function $M0(A,Q){if(A===Q)return!0;let w=VOA(A),B=VOA(Q);if(!w||!B)return!1;if(!bOA(w.hostname)||!bOA(B.hostname))return!1;return w.protocol===B.protocol&&w.port===B.port&&Rp2(w.pathname,B.pathname)&&w.search===B.search&&w.hash===B.hash}function Rp2(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function fM0(A,Q){return A.some((w)=>$M0(w,Q))}var gp2="oauth-auth-codes.json",yp2=600,Ep2=Z.looseObject({code:Z.string(),client_id:Z.string(),redirect_uri:Z.string(),code_challenge:Z.string(),code_challenge_method:Z.literal("S256"),scope:Z.string().optional(),subject:Z.string(),created_at:Z.number(),expires_at:Z.number(),consumed_at:Z.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}:{}})),Tp2=Z.looseObject({codes:Z.array(Z.unknown()).optional()});function Sp2(A){let Q=Tp2.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap(mp2)??[]}}function mp2(A){let Q=Ep2.safeParse(A);return Q.success?[Q.data]:[]}async function up2(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class Kw0{store;constructor(A){this.store=new vf({filePath:Cp2(A.storageDir,A.storeFile??gp2),parse:Sp2,empty:()=>({codes:[]})})}async createCode(A){let Q=K9(),w={code:`ocd_${hp2()}`,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+yp2};return await this.store.enqueueWrite(async()=>{let B=await this.store.read();B.codes=B.codes.filter(($)=>$.expires_at>Q),B.codes.push(w),await this.store.write(B)}),w}async consumeCode(A){let Q=K9(),w;if(await this.store.enqueueWrite(async()=>{let B=await this.store.read(),$=B.codes.findIndex((X)=>X.code===A.code),f=$>=0?B.codes[$]:void 0;if(!f)throw new yK("Authorization code not found");if(f.consumed_at!==void 0)throw new yK("Authorization code already consumed");if(f.expires_at<=Q)throw new yK("Authorization code expired");if(f.client_id!==A.clientId)throw new yK("Authorization code client mismatch");if(!$M0(f.redirect_uri,A.redirectUri))throw new yK("Authorization code redirect URI mismatch");let Y=await up2(A.codeVerifier);if(f.code_challenge!==Y)throw new yK("PKCE verification failed");w={...f,consumed_at:Q},B.codes[$]=w,await this.store.write(B)}),!w)throw new yK("Authorization code not consumed");return w}}class yK extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as JOA}from"crypto";L0();import{join as cp2}from"path";var lp2="oauth-clients.json",pp2=Z.enum(["none","client_secret_basic","client_secret_post"]),ip2=Z.object({redirect_uris:Z.array(Z.url()).min(1),token_endpoint_auth_method:pp2.default("none"),grant_types:Z.array(Z.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:Z.array(Z.literal("code")).default(["code"]),scope:Z.string().optional(),client_name:Z.string().optional(),client_uri:Z.url().optional(),logo_uri:Z.url().optional(),contacts:Z.array(Z.string()).optional()}),dp2=Z.looseObject({client_id:Z.string(),client_id_issued_at:Z.number(),redirect_uris:Z.array(Z.string()),token_endpoint_auth_method:Z.string().optional(),grant_types:Z.array(Z.string()).optional(),response_types:Z.array(Z.string()).optional(),scope:Z.string().optional(),client_name:Z.string().optional(),client_uri:Z.string().optional(),logo_uri:Z.string().optional(),contacts:Z.array(Z.string()).optional(),client_secret:Z.string().optional(),client_secret_expires_at:Z.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}:{}})),np2=Z.looseObject({clients:Z.array(Z.unknown()).optional()});function rp2(){return`ocs_${JOA().replaceAll("-","")}`}function op2(A){let Q=np2.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(sp2)??[]}}function sp2(A){let Q=dp2.safeParse(A);return Q.success?[Q.data]:[]}class Uw0{store;constructor(A){this.store=new vf({filePath:cp2(A.storageDir,A.storeFile??lp2),parse:op2,empty:()=>({clients:[]})})}async registerClient(A){let Q=ip2.safeParse(A);if(!Q.success)throw new cc(Q.error.message);let w=Q.data,B=K9(),$=`oc_${JOA()}`,f=w.token_endpoint_auth_method==="none",Y={client_id:$,client_id_issued_at:B,redirect_uris:w.redirect_uris,token_endpoint_auth_method:w.token_endpoint_auth_method,grant_types:w.grant_types,response_types:w.response_types,...w.scope?{scope:w.scope}:{},...w.client_name?{client_name:w.client_name}:{},...w.client_uri?{client_uri:w.client_uri}:{},...w.logo_uri?{logo_uri:w.logo_uri}:{},...w.contacts?{contacts:w.contacts}:{},...!f?{client_secret:rp2(),client_secret_expires_at:0}:{}};return await this.store.enqueueWrite(async()=>{let X=await this.store.read();X.clients.push(Y),await this.store.write(X)}),Y}async getClient(A){return(await this.store.read()).clients.find((w)=>w.client_id===A)}}class cc extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}L0();import{createHash as IOA,generateKeyPairSync as ap2}from"crypto";import{mkdir as tp2,readFile as FOA,writeFile as ep2,chmod as Ai2}from"fs/promises";import{dirname as Qi2,join as kOA}from"path";var wi2="oauth-signing-key.jwk",Bi2="a2a-signing-key.jwk",LOA=Z.object({kty:Z.literal("EC"),crv:Z.literal("P-256"),x:Z.string(),y:Z.string(),d:Z.string(),kid:Z.string().optional()}),_OA=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),d:Z.string(),kid:Z.string().optional()});function $i2(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return IOA("sha256").update(Q).digest("base64url")}function fi2(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return IOA("sha256").update(Q).digest("base64url")}function Yi2(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function Xi2(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function Zi2(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=LOA.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 NOA(Q.data)}function Hi2(){let{privateKey:A}=ap2("ed25519"),Q=_OA.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return POA(Q.data)}function NOA(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??$i2(A),use:"sig",alg:"ES256"}}function POA(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??fi2(A),use:"sig",alg:"EdDSA"}}class Gw0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=kOA(A.storageDir,A.keyFile??wi2)}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 Zi2();return await jOA(this.keyFile,Q),Q}async getPublicJwk(){return Yi2(await this.getPrivateJwk())}async readExistingKey(){try{let A=LOA.safeParse(JSON.parse(await FOA(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return NOA(A.data)}catch(A){if(MOA(A))return;throw A}}}class YM0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=kOA(A.storageDir,A.keyFile??Bi2)}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=Hi2();return await jOA(this.keyFile,Q),Q}async getPublicJwk(){return Xi2(await this.getPrivateJwk())}async readExistingKey(){try{let A=_OA.safeParse(JSON.parse(await FOA(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return POA(A.data)}catch(A){if(MOA(A))return;throw A}}}async function jOA(A,Q){await tp2(Qi2(A),{recursive:!0,mode:448}),await ep2(A,`${JSON.stringify(Q,null,2)}
|
|
1722
1722
|
`,{mode:384}),await Ai2(A,384)}function MOA(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var xQ={};q6(xQ,{trimPadding:()=>OOA,toUTF8String:()=>Vi2,toBuffer:()=>Di2,toBase64:()=>qi2,isBase64URL:()=>Ii2,isBase64:()=>Ji2,fromUTF8String:()=>bi2,fromBuffer:()=>zi2});var xOA=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),w=64;for(let B=0;B<64;B++)Q[A.charCodeAt(B)]=B;return Q},Wi2=xOA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),Ki2=xOA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),Ui2=/^[-A-Za-z0-9\-_]*$/,Gi2=/^[-A-Za-z0-9+/]*={0,3}$/,lG={};lG.toArrayBuffer=(A,Q)=>{let w=A.length,B=A.length*0.75,$,f=0,Y,X,H,W;if(A[A.length-1]==="="){if(B--,A[A.length-2]==="=")B--}let K=new ArrayBuffer(B),U=new Uint8Array(K),G=Q?Ki2:Wi2;for($=0;$<w;$+=4)Y=G[A.charCodeAt($)],X=G[A.charCodeAt($+1)],H=G[A.charCodeAt($+2)],W=G[A.charCodeAt($+3)],U[f++]=Y<<2|X>>4,U[f++]=(X&15)<<4|H>>2,U[f++]=(H&3)<<6|W&63;return K};lG.fromArrayBuffer=(A,Q)=>{let w=new Uint8Array(A),B,$="",f=w.length,Y=Q?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(B=0;B<f;B+=3)$+=Y[w[B]>>2],$+=Y[(w[B]&3)<<4|w[B+1]>>4],$+=Y[(w[B+1]&15)<<2|w[B+2]>>6],$+=Y[w[B+2]&63];let X=f%3;if(X===2)$=$.substring(0,$.length-1)+(Q?"":"=");else if(X===1)$=$.substring(0,$.length-2)+(Q?"":"==");return $};lG.toString=(A,Q)=>{return new TextDecoder().decode(lG.toArrayBuffer(A,Q))};lG.fromString=(A,Q)=>{return lG.fromArrayBuffer(new TextEncoder().encode(A),Q)};lG.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?Ui2.test(A):Gi2.test(A)}catch(w){return!1}};lG.base64=lG;var cz=lG;function Di2(A,Q="base64url"){let w=cz.toArrayBuffer(A,Q==="base64url");return new Uint8Array(w)}function zi2(A,Q="base64url"){let w=new Uint8Array(A);return cz.fromArrayBuffer(w.buffer,Q==="base64url")}function qi2(A){let Q=cz.toArrayBuffer(A,!0);return cz.fromArrayBuffer(Q)}function bi2(A){return cz.fromString(A,!0)}function Vi2(A){return cz.toString(A,!0)}function Ji2(A){return cz.validate(A,!1)}function Ii2(A){return A=OOA(A),cz.validate(A,!0)}function OOA(A){return A.replace(/=/g,"")}var Rf={};q6(Rf,{encode:()=>ui2,decodeFirst:()=>mi2});function tv(A,Q,w){if(Q<24)return[Q,1];let B=A.byteLength-w-1,$=new DataView(A.buffer,w+1),f,Y=0;switch(Q){case 24:{if(B>0)f=$.getUint8(0),Y=2;break}case 25:{if(B>1)f=$.getUint16(0,!1),Y=3;break}case 26:{if(B>3)f=$.getUint32(0,!1),Y=5;break}case 27:{if(B>7){let X=$.getBigUint64(0,!1);if(X>=24n&&X<=Number.MAX_SAFE_INTEGER)return[Number(X),9]}break}}if(f&&f>=24)return[f,Y];throw Error("Length not supported or not well formed")}var Dw0=0,lc=1,XM0=2,ZM0=3,HM0=4,WM0=5,KM0=6,vOA=7;function pG(A,Q){let w=A<<5;if(Q<0)throw Error("CBOR Data Item argument must not be negative");let B;if(typeof Q=="number"){if(!Number.isInteger(Q))throw Error("CBOR Data Item argument must be an integer");B=BigInt(Q)}else B=Q;if(A==lc){if(B==0n)throw Error("CBOR Data Item argument cannot be zero when negative");B=B-1n}if(B>18446744073709551615n)throw Error("CBOR number out of range");let $=new Uint8Array(8);if(new DataView($.buffer).setBigUint64(0,B,!1),B<=23)return[w|$[7]];else if(B<=255)return[w|24,$[7]];else if(B<=65535)return[w|25,...$.slice(6)];else if(B<=4294967295)return[w|26,...$.slice(4)];else return[w|27,...$]}class qw0{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 ROA(A,Q,w){return tv(A,Q,w)}function Fi2(A,Q,w){let[B,$]=ROA(A,Q,w);return[-B-1,$]}function hOA(A,Q,w){let[B,$]=tv(A,Q,w),f=w+$;return[new Uint8Array(A.buffer.slice(f,f+B)),$+B]}var ki2=new TextDecoder;function Li2(A,Q,w){let[B,$]=hOA(A,Q,w);return[ki2.decode(B),$]}function _i2(A,Q,w){if(Q===0)return[[],1];let[B,$]=tv(A,Q,w),f=$,Y=[];for(let X=0;X<B;X++){if(A.byteLength-w-f<=0)throw Error("array is not supported or well formed");let[W,K]=V_(A,w+f);Y.push(W),f+=K}return[Y,f]}var zw0="Map is not supported or well formed";function Ni2(A,Q,w){if(Q===0)return[new Map,1];let[B,$]=tv(A,Q,w),f=$,Y=new Map;for(let X=0;X<B;X++){let H=A.byteLength-w-f;if(H<=0)throw Error(zw0);let[W,K]=V_(A,w+f);if(f+=K,H-=K,H<=0)throw Error(zw0);if(typeof W!=="string"&&typeof W!=="number")throw Error(zw0);if(Y.has(W))throw Error(zw0);let[U,G]=V_(A,w+f);f+=G,Y.set(W,U)}return[Y,f]}function Pi2(A,Q){if(Q+3>A.byteLength)throw Error("CBOR stream ended before end of Float 16");let w=A.getUint16(Q+1,!1);if(w==31744)return[1/0,3];else if(w==32256)return[NaN,3];else if(w==64512)return[-1/0,3];throw Error("Float16 data is unsupported")}function ji2(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 Mi2(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 xi2(A,Q,w){let[B,$]=tv(A,Q,w),[f,Y]=V_(A,w+$);return[new qw0(B,f),$+Y]}function V_(A,Q){if(Q>=A.byteLength)throw Error("CBOR stream ended before tag value");let w=A.getUint8(Q),B=w>>5,$=w&31;switch(B){case Dw0:return ROA(A,$,Q);case lc:return Fi2(A,$,Q);case XM0:return hOA(A,$,Q);case ZM0:return Li2(A,$,Q);case HM0:return _i2(A,$,Q);case WM0:return Ni2(A,$,Q);case KM0:return xi2(A,$,Q);case vOA:switch($){case 20:return[!1,1];case 21:return[!0,1];case 22:return[null,1];case 23:return[void 0,1];case 25:return Pi2(A,Q);case 26:return ji2(A,Q);case 27:return Mi2(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function Oi2(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function vi2(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 Ri2(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return pG(lc,Math.abs(A));else return pG(Dw0,A);return[vi2(A)]}else if(A<0n)return pG(lc,A*-1n);else return pG(Dw0,A)}var hi2=new TextEncoder;function Ci2(A,Q){Q.push(...pG(ZM0,A.length)),Q.push(hi2.encode(A))}function gi2(A,Q){Q.push(...pG(XM0,A.length)),Q.push(A)}function yi2(A,Q){Q.push(...pG(HM0,A.length));for(let w of A)pc(w,Q)}function Ei2(A,Q){Q.push(new Uint8Array(pG(WM0,A.size)));for(let[w,B]of A.entries())pc(w,Q),pc(B,Q)}function Ti2(A,Q){Q.push(...pG(KM0,A.tag)),pc(A.value,Q)}function pc(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(Oi2(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...Ri2(A));return}if(typeof A=="string"){Ci2(A,Q);return}if(A instanceof Uint8Array){gi2(A,Q);return}if(Array.isArray(A)){yi2(A,Q);return}if(A instanceof Map){Ei2(A,Q);return}if(A instanceof qw0){Ti2(A,Q);return}throw Error("Not implemented")}function UM0(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return V_(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return V_(new DataView(A),Q);return V_(A,Q)}function GM0(A){let Q=[];pc(A,Q);let w=0;for(let f of Q)if(typeof f=="number")w+=1;else w+=f.length;let B=new Uint8Array(w),$=0;for(let f of Q)if(typeof f=="number")B[$]=f,$+=1;else B.set(f,$),$+=f.length;return B}function mi2(A){let Q=new Uint8Array(A),w=UM0(Q,0),[B]=w;return B}function ui2(A){return GM0(A)}var dG={};q6(dG,{verify:()=>zgA,getRandomValues:()=>TOA,digest:()=>EOA});function COA(A){let Q=A.get(FQ.kty);return DM0(Q)&&Q===rX.OKP}function IJ(A){let Q=A.get(FQ.kty);return DM0(Q)&&Q===rX.EC2}function ev(A){let Q=A.get(FQ.kty);return DM0(Q)&&Q===rX.RSA}var FQ;(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"})(FQ||(FQ={}));var rX;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(rX||(rX={}));function DM0(A){return Object.values(rX).indexOf(A)>=0}var j4;(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"})(j4||(j4={}));function gOA(A){return Object.values(j4).indexOf(A)>=0}var ww;(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"})(ww||(ww={}));function iG(A){return Object.values(ww).indexOf(A)>=0}function FJ(A){if([ww.RS1].indexOf(A)>=0)return"SHA-1";else if([ww.ES256,ww.PS256,ww.RS256].indexOf(A)>=0)return"SHA-256";else if([ww.ES384,ww.PS384,ww.RS384].indexOf(A)>=0)return"SHA-384";else if([ww.ES512,ww.PS512,ww.RS512,ww.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var ic=void 0;function nH(){return new Promise((Q,w)=>{if(ic)return Q(ic);let B=li2.stubThisGlobalThisCrypto();if(B)return ic=B,Q(ic);return w(new yOA)})}class yOA extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var li2={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{ic=A}};async function EOA(A,Q){let w=await nH(),B=FJ(Q),$=await w.subtle.digest(B,A);return new Uint8Array($)}async function TOA(A){return(await nH()).getRandomValues(A),A}async function AR(A){let Q=await nH(),{keyData:w,algorithm:B}=A;return Q.subtle.importKey("jwk",w,B,!1,["verify"])}async function bw0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await nH(),Y=Q.get(FQ.alg),X=Q.get(FQ.crv),H=Q.get(FQ.x),W=Q.get(FQ.y);if(!Y)throw Error("Public key was missing alg (EC2)");if(!X)throw Error("Public key was missing crv (EC2)");if(!H)throw Error("Public key was missing x (EC2)");if(!W)throw Error("Public key was missing y (EC2)");let K;if(X===j4.P256)K="P-256";else if(X===j4.P384)K="P-384";else if(X===j4.P521)K="P-521";else throw Error(`Unexpected COSE crv value of ${X} (EC2)`);let U={kty:"EC",crv:K,x:xQ.fromBuffer(H),y:xQ.fromBuffer(W),ext:!1},q=await AR({keyData:U,algorithm:{name:"ECDSA",namedCurve:K}}),b=FJ(Y);if($)b=FJ($);let J={name:"ECDSA",hash:{name:b}};return f.subtle.verify(J,q,w,B)}function zM0(A){if([ww.EdDSA].indexOf(A)>=0)return"Ed25519";else if([ww.ES256,ww.ES384,ww.ES512,ww.ES256K].indexOf(A)>=0)return"ECDSA";else if([ww.RS256,ww.RS384,ww.RS512,ww.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([ww.PS256,ww.PS384,ww.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 Vw0(A){let{cosePublicKey:Q,signature:w,data:B,shaHashOverride:$}=A,f=await nH(),Y=Q.get(FQ.alg),X=Q.get(FQ.n),H=Q.get(FQ.e);if(!Y)throw Error("Public key was missing alg (RSA)");if(!iG(Y))throw Error(`Public key had invalid alg ${Y} (RSA)`);if(!X)throw Error("Public key was missing n (RSA)");if(!H)throw Error("Public key was missing e (RSA)");let W={kty:"RSA",alg:"",n:xQ.fromBuffer(X),e:xQ.fromBuffer(H),ext:!1},K={name:zM0(Y),hash:{name:FJ(Y)}},U={name:zM0(Y)};if($)K.hash.name=FJ($);if(K.name==="RSASSA-PKCS1-v1_5"){if(K.hash.name==="SHA-256")W.alg="RS256";else if(K.hash.name==="SHA-384")W.alg="RS384";else if(K.hash.name==="SHA-512")W.alg="RS512";else if(K.hash.name==="SHA-1")W.alg="RS1"}else if(K.name==="RSA-PSS"){let q=0;if(K.hash.name==="SHA-256")W.alg="PS256",q=32;else if(K.hash.name==="SHA-384")W.alg="PS384",q=48;else if(K.hash.name==="SHA-512")W.alg="PS512",q=64;U.saltLength=q}else throw Error(`Unexpected RSA key algorithm ${Y} (${K.name})`);let G=await AR({keyData:W,algorithm:K});return f.subtle.verify(U,G,w,B)}function Jw0(A){let Q=C2.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 j5(A){let Q;if(typeof A==="string")if(xQ.isBase64URL(A))Q=xQ.toBase64(A);else if(xQ.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=xQ.fromBuffer(A,"base64");let w="";for(let B=0;B<Math.ceil(Q.length/64);B+=1){let $=64*B;w+=`${Q.substr($,64)}
|
|
1723
1723
|
`}return w=`-----BEGIN CERTIFICATE-----
|
|
@@ -2289,14 +2289,14 @@ ${k}`)}if(B!==void 0&&f?.algorithms!==void 0){let V=f.algorithms.map((k)=>k.alg)
|
|
|
2289
2289
|
</form>
|
|
2290
2290
|
</main>
|
|
2291
2291
|
</body>
|
|
2292
|
-
</html>`}function xp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(Ov0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function XD(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as qo2}from"crypto";function MyA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function zo2(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let w=2;if(Q[1]&&Q[1]>128)w+=Q[1]-128;if(Q[w]!==2)throw Error("Invalid DER ECDSA signature");let B=Q[w+1];if(B===void 0)throw Error("Invalid DER ECDSA signature");let $=w+2,f=Q.slice($,$+B);if(w=$+B,Q[w]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[w+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let X=w+2,H=Q.slice(X,X+Y);return new Uint8Array([...xyA(f),...xyA(H)])}function xyA(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let w=new Uint8Array(32);return w.set(Q,32-Q.length),w}async function Rv0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${MyA(w)}.${MyA(Q)}`,$=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),f=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},$,new TextEncoder().encode(B));return`${B}.${Buffer.from(zo2(f)).toString("base64url")}`}var bo2=600;class hv0{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 xp(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let B=this.createAuthorizationApprovalToken(Q,w.params);return bh(jyA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return xp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(Pv0(w)));if(!B.success)return new Response(B.error,{status:400});let $=w.get("approval_token"),f=typeof $==="string"?$:void 0;if(!f||!this.consumeAuthorizationApprovalToken(f,Q,B.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:B.params.clientId,redirectUri:B.params.redirectUri,codeChallenge:B.params.codeChallenge,...B.params.scope?{scope:B.params.scope}:{},subject:Q.subject}),X=new URL(B.params.redirectUri);if(X.searchParams.set("code",Y.code),B.params.state)X.searchParams.set("state",B.params.state);return Response.redirect(X.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${qo2()}`;return this.authorizationApprovalTokens.set(w,{token:w,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+bo2}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let B=this.authorizationApprovalTokens.get(A);if(!B)return!1;return this.authorizationApprovalTokens.delete(A),B.sessionId===Q.id&&B.clientId===w.clientId&&B.redirectUri===w.redirectUri&&B.codeChallenge===w.codeChallenge&&B.scope===w.scope&&B.state===w.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,w]of this.authorizationApprovalTokens.entries())if(w.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),w=A.get("client_id"),B=A.get("redirect_uri"),$=A.get("code_challenge"),f=A.get("code_challenge_method"),Y=A.get("scope")??void 0,X=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!B)return{success:!1,error:"Missing redirect_uri"};if(!$)return{success:!1,error:"Missing code_challenge"};if(f!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let H=await this.clientStore.getClient(w);if(!H)return{success:!1,error:"Unknown client_id"};if(!fM0(H.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let W=Y??H.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...W?{scope:W}:{},...X?{state:X}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return a$("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return BZ(w,201)}catch(w){if(w instanceof cc)return a$("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await Nv0(A),B=w.get("grant_type"),$=Mv0(A,w),f=$.clientId??w.get("client_id");if($.error)return a$("invalid_client",$.error);if(!f)return a$("invalid_request","client_id is required");let Y=await this.clientStore.getClient(f),X=jv0(Y,$);if(X)return a$("invalid_client",X);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return a$("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let B=A.get("code"),$=A.get("redirect_uri"),f=A.get("code_verifier");if(!B||!$||!f)return a$("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!fM0(Y.redirect_uris,$))return a$("invalid_grant","Unregistered redirect_uri");try{let X=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:X.subject,...X.scope?{scope:X.scope}:{}})}catch(X){if(X instanceof yK)return a$("invalid_grant",X.message);throw X}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return a$("invalid_request","refresh_token is required");try{let $=await this.refreshTokenStore.rotateToken(B,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:$.consumed.subject,...$.consumed.scope?{scope:$.consumed.scope}:{},refreshToken:$.replacement.token})}catch($){if($ instanceof Kq)return a$("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await Rv0(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),$=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return BZ({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await Nv0(A),w=Mv0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return a$("invalid_client",w.error);if(!$)return a$("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),Y=jv0(f,w);if(Y)return a$("invalid_client",Y)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class Cv0{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 a$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return a$("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(t60(A));return BZ(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return a$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return a$("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),t60(A));if(!Q.verified)return a$("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Np(A)});return BZ({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return a$("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(t60(A));return BZ(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),t60(A));if(!Q.verified)return a$("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Np(A)});return BZ({verified:!0},200,{"Set-Cookie":w.cookie})}}function t60(A){let Q=oJ(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as Vo2}from"crypto";var Op=86400;class gv0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??Op}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_${Vo2()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let w=new URL(A.url);return(w.searchParams.get("setup_token")??w.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return nK(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:nK(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:fv0(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 bh(NyA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class e60{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=dK(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>dK(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??rJ(this.issuer),this.keyStore=new Gw0({storageDir:A.storageDir}),this.a2aKeyStore=new YM0({storageDir:A.storageDir}),this.clientStore=new Uw0({storageDir:A.storageDir}),this.authCodeStore=new Kw0({storageDir:A.storageDir}),this.sessionStore=new n60({storageDir:A.storageDir}),this.peerTrustStore=new l60({storageDir:A.storageDir}),this.passkeyService=new c60({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new gv0({setupStateStore:new Yv0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Op}),this.oauthEndpoints=new hv0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new p60({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new Cv0({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(rJ(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:nK(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=dK(A);return{issuer:Q,authorization_endpoint:nK(Q,"/authorize"),token_endpoint:nK(Q,"/token"),registration_endpoint:nK(Q,"/register"),revocation_endpoint:nK(Q,"/revoke"),jwks_uri:nK(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:[dK(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 xp(A)}async verifyBearerToken(A,Q={}){let w=_v0(A);if(!w)return;let B=Q.issuer?dK(Q.issuer):this.resolveRequestIssuer(A);return Lv0(w,await this.getJwks(),{issuer:B,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,w)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(B){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:B instanceof Error?B.message:String(B)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&kyA(w))return LyA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return eJ(BZ(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return eJ(BZ(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return eJ(BZ(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&w==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&w==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&w==="/logout")return this.handleLogout(A);if(A.method==="POST"&&w==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&w==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&w==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&w==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&w==="/register")return eJ(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return eJ(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return eJ(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=oJ(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&rJ(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=xv0(new URL(A.url).searchParams.get("return_to"));return bh(Ov0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=xv0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":Zv0(Np(A)),"Cache-Control":"no-store"}})}}L0();var AB0="email:send",OyA=Z.strictObject({to:Z.string().email(),subject:Z.string().min(1),text:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")});wA();L0();var vyA={name:"@brains/notifications",version:"0.2.0-alpha.163",description:"Generic notification routing for transactional and administrative messages",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"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var yv0="notifications:send",Io2=Z.looseObject({}),Fo2=Z.discriminatedUnion("type",[Z.strictObject({type:Z.literal("email"),address:Z.email()})]),ko2=Z.strictObject({recipient:Fo2,title:Z.string().min(1),body:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")}),RyA=Z.discriminatedUnion("status",[Z.strictObject({status:Z.literal("sent"),deliveryId:Z.string().optional()}),Z.strictObject({status:Z.literal("failed")})]);class hyA extends Aw{constructor(A={}){super("notifications",vyA,A,Io2)}async onRegister(A){A.messaging.subscribe(yv0,async(Q)=>{let w=ko2.parse(Q.payload),B={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},$=await A.messaging.send({type:AB0,payload:B});if(!("success"in $)||!$.success||!$.data)return{success:!1,error:"Notification delivery failed"};let f=$.data;if(f.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:f.id?{status:"sent",deliveryId:f.id}:{status:"sent"}}})}}function QB0(A={}){return new hyA(A)}wA();L0();var CyA={name:"@brains/auth-service",version:"0.2.0-alpha.163",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"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 _o2=Z.union([Z.string().email(),Z.object({to:Z.string().email(),subject:Z.string().min(1),body:Z.string().min(1)}).strict()]),No2=Z.object({issuer:Z.string().optional(),trustedIssuers:Z.array(Z.string()).default([]),allowLocalhostIssuers:Z.boolean().optional(),storageDir:Z.string().default("./data/auth"),setupTokenTtlSeconds:Z.number().int().positive().default(Op),setupEmail:_o2.optional()}),wB0;function v7(){return wB0}class Ev0 extends Aw{service;constructor(A={}){super("auth-service",CyA,A,No2)}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 e60({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(),wB0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(wB0===this.service)wB0=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 w=await Q.getOperatorSetupRequired();if(!w)return;let B=Po2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:yv0,payload:{recipient:{type:"email",address:B.to},title:B.subject,body:B.body,sensitivity:"secret"}});if(!("success"in $)||!$.success||!$.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let f=RyA.safeParse($.data);if(!f.success||f.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,B.to,f.data.deliveryId?{deliveryId:f.data.deliveryId}:{})}}function Po2(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${w}.`,`Dashboard: ${B}/`,`MCP endpoint: ${B}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
|
|
2293
|
-
`)}}return{to:A.to,subject:gyA(A.subject,Q),body:gyA(A.body,Q)}}function gyA(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",B)}function vp(A={}){return new Ev0(A)}L0();var Tv0=Z.object({transport:Z.enum(["stdio","http"]).default("http"),mode:Z.enum(["basic","debug"]).default("basic"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:Z.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});L0();import{createHash as Oo2,randomUUID as vo2}from"crypto";function jo2(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Rp(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Mo2(A){let Q=jo2(A.data)?A.data:void 0,w=A.args,B=Rp(Q,"entityId")??Rp(Q,"id"),$=A.jobId??Rp(Q,"jobId"),f=Rp(w,"entityType")??Rp(w,"type");if(!B&&!$)return;return{toolName:A.toolName,...f?{entityType:f}:{},...B?{entityId:B}:{},...$?{jobId:$}:{}}}function xo2(A){return A?.map(Mo2).filter((Q)=>Q!==void 0)??[]}function Sv0(A,Q={}){let w=A.pendingConfirmations?.[0];if(w)return{needsConfirmation:!0,toolName:w.toolName,summary:w.summary,...w.completionSummary?{completionSummary:w.completionSummary}:{},...w.preview?{preview:w.preview}:{},args:{approvalId:w.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...w.toolCallId?{toolCallId:w.toolCallId}:{},originalArgs:w.args}};let B=xo2(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...B.length>0?{readYourWrites:B}:{}}}}var yyA=Z.object({message:Z.string().min(1),conversationId:Z.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),EyA=Z.object({approvalId:Z.string().min(1),confirmed:Z.boolean(),conversationId:Z.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function TyA(A,Q,w,B){let $=A.conversationId??w??B??`conversation-${vo2()}`,f=Oo2("sha256").update(Q).digest("hex").slice(0,16);return{handle:$,internalId:`mcp:${f}:${$}`}}function SyA(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 myA(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:yyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=yyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP chat tool is not initialized."};let Y=TyA($,B.userId,B.conversationId,B.channelId),X=await f.agent.chat($.message,Y.internalId,{...SyA(B)});return Sv0(X,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:EyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=EyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=TyA($,B.userId,B.conversationId,B.channelId),X=await f.agent.confirmPendingAction(Y.internalId,$.confirmed,$.approvalId,SyA(B));return Sv0(X,{conversationId:Y.handle})}}]}wA();function mv0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=xx.safeParse(w.payload);if(!B.success)return Q.warn("Received invalid job-progress message",{error:B.error.message}),{success:!1};let $=B.data,f=$.type,Y=$.status,X=$.id;if(Q.debug(`${f} ${X} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var uyA={name:"@brains/mcp",version:"0.2.0-alpha.
|
|
2292
|
+
</html>`}function xp(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(Ov0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function XD(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as qo2}from"crypto";function MyA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function zo2(A){let Q=new Uint8Array(A);if(Q.length===64)return Q;if(Q[0]!==48)return Q;let w=2;if(Q[1]&&Q[1]>128)w+=Q[1]-128;if(Q[w]!==2)throw Error("Invalid DER ECDSA signature");let B=Q[w+1];if(B===void 0)throw Error("Invalid DER ECDSA signature");let $=w+2,f=Q.slice($,$+B);if(w=$+B,Q[w]!==2)throw Error("Invalid DER ECDSA signature");let Y=Q[w+1];if(Y===void 0)throw Error("Invalid DER ECDSA signature");let X=w+2,H=Q.slice(X,X+Y);return new Uint8Array([...xyA(f),...xyA(H)])}function xyA(A){let Q=A;while(Q.length>32&&Q[0]===0)Q=Q.slice(1);if(Q.length>32)throw Error("Invalid P-256 signature component length");if(Q.length===32)return Q;let w=new Uint8Array(32);return w.set(Q,32-Q.length),w}async function Rv0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},B=`${MyA(w)}.${MyA(Q)}`,$=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),f=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},$,new TextEncoder().encode(B));return`${B}.${Buffer.from(zo2(f)).toString("base64url")}`}var bo2=600;class hv0{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 xp(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let B=this.createAuthorizationApprovalToken(Q,w.params);return bh(jyA(w.params,B))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return xp(A);let w=await A.formData(),B=await this.validateAuthorizationRequest(new URLSearchParams(Pv0(w)));if(!B.success)return new Response(B.error,{status:400});let $=w.get("approval_token"),f=typeof $==="string"?$:void 0;if(!f||!this.consumeAuthorizationApprovalToken(f,Q,B.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:B.params.clientId,redirectUri:B.params.redirectUri,codeChallenge:B.params.codeChallenge,...B.params.scope?{scope:B.params.scope}:{},subject:Q.subject}),X=new URL(B.params.redirectUri);if(X.searchParams.set("code",Y.code),B.params.state)X.searchParams.set("state",B.params.state);return Response.redirect(X.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${qo2()}`;return this.authorizationApprovalTokens.set(w,{token:w,sessionId:A.id,clientId:Q.clientId,redirectUri:Q.redirectUri,codeChallenge:Q.codeChallenge,...Q.scope?{scope:Q.scope}:{},...Q.state?{state:Q.state}:{},expiresAt:Math.floor(Date.now()/1000)+bo2}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let B=this.authorizationApprovalTokens.get(A);if(!B)return!1;return this.authorizationApprovalTokens.delete(A),B.sessionId===Q.id&&B.clientId===w.clientId&&B.redirectUri===w.redirectUri&&B.codeChallenge===w.codeChallenge&&B.scope===w.scope&&B.state===w.state}pruneExpiredAuthorizationApprovalTokens(){let A=Math.floor(Date.now()/1000);for(let[Q,w]of this.authorizationApprovalTokens.entries())if(w.expiresAt<=A)this.authorizationApprovalTokens.delete(Q)}async validateAuthorizationRequest(A){let Q=A.get("response_type"),w=A.get("client_id"),B=A.get("redirect_uri"),$=A.get("code_challenge"),f=A.get("code_challenge_method"),Y=A.get("scope")??void 0,X=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!B)return{success:!1,error:"Missing redirect_uri"};if(!$)return{success:!1,error:"Missing code_challenge"};if(f!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let H=await this.clientStore.getClient(w);if(!H)return{success:!1,error:"Unknown client_id"};if(!fM0(H.redirect_uris,B))return{success:!1,error:"Unregistered redirect_uri"};let W=Y??H.scope;return{success:!0,params:{clientId:w,redirectUri:B,codeChallenge:$,...W?{scope:W}:{},...X?{state:X}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return a$("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return BZ(w,201)}catch(w){if(w instanceof cc)return a$("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await Nv0(A),B=w.get("grant_type"),$=Mv0(A,w),f=$.clientId??w.get("client_id");if($.error)return a$("invalid_client",$.error);if(!f)return a$("invalid_request","client_id is required");let Y=await this.clientStore.getClient(f),X=jv0(Y,$);if(X)return a$("invalid_client",X);if(B==="authorization_code")return this.handleAuthorizationCodeGrant(w,f,Q);if(B==="refresh_token")return this.handleRefreshTokenGrant(w,f,Q);return a$("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let B=A.get("code"),$=A.get("redirect_uri"),f=A.get("code_verifier");if(!B||!$||!f)return a$("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!fM0(Y.redirect_uris,$))return a$("invalid_grant","Unregistered redirect_uri");try{let X=await this.authCodeStore.consumeCode({code:B,clientId:Q,redirectUri:$,codeVerifier:f});return await this.createTokenResponse({issuer:w,clientId:Q,subject:X.subject,...X.scope?{scope:X.scope}:{}})}catch(X){if(X instanceof yK)return a$("invalid_grant",X.message);throw X}}async handleRefreshTokenGrant(A,Q,w){let B=A.get("refresh_token");if(!B)return a$("invalid_request","refresh_token is required");try{let $=await this.refreshTokenStore.rotateToken(B,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:$.consumed.subject,...$.consumed.scope?{scope:$.consumed.scope}:{},refreshToken:$.replacement.token})}catch($){if($ instanceof Kq)return a$("invalid_grant",$.message);throw $}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,B=await Rv0(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),$=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return BZ({access_token:B,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:$})}async handleRevokeRequest(A){let Q=await Nv0(A),w=Mv0(A,Q),B=w.clientId??Q.get("client_id")??void 0,$=Q.get("token");if(w.error)return a$("invalid_client",w.error);if(!$)return a$("invalid_request","token is required");if(B){let f=await this.clientStore.getClient(B),Y=jv0(f,w);if(Y)return a$("invalid_client",Y)}return await this.refreshTokenStore.revokeToken($,B),new Response(null,{status:200})}}class Cv0{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 a$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return a$("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(t60(A));return BZ(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return a$("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return a$("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),t60(A));if(!Q.verified)return a$("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Np(A)});return BZ({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return a$("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(t60(A));return BZ(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),t60(A));if(!Q.verified)return a$("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:Np(A)});return BZ({verified:!0},200,{"Set-Cookie":w.cookie})}}function t60(A){let Q=oJ(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as Vo2}from"crypto";var Op=86400;class gv0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??Op}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_${Vo2()}`,expiresAt:Math.floor(Date.now()/1000)+this.setupTokenTtlSeconds},await this.setupStateStore.saveSetupToken(this.setupToken),this.setupToken}getValidSetupToken(){if(!this.setupToken)return;if(this.setupToken.expiresAt<=Math.floor(Date.now()/1000)){this.setupToken=void 0;return}return this.setupToken}hasValidSetupToken(A){let Q=this.getValidSetupToken();if(!Q)return!1;let w=new URL(A.url);return(w.searchParams.get("setup_token")??w.searchParams.get("token"))===Q.token}async clearSetupState(){this.setupToken=void 0,await this.setupStateStore.clearSetupState()}getSetupUrl(A){let Q=this.getValidSetupToken();if(!Q)return;return nK(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:nK(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:fv0(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 bh(NyA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class e60{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=dK(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>dK(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??rJ(this.issuer),this.keyStore=new Gw0({storageDir:A.storageDir}),this.a2aKeyStore=new YM0({storageDir:A.storageDir}),this.clientStore=new Uw0({storageDir:A.storageDir}),this.authCodeStore=new Kw0({storageDir:A.storageDir}),this.sessionStore=new n60({storageDir:A.storageDir}),this.peerTrustStore=new l60({storageDir:A.storageDir}),this.passkeyService=new c60({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new gv0({setupStateStore:new Yv0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??Op}),this.oauthEndpoints=new hv0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new p60({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new Cv0({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(rJ(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:nK(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=dK(A);return{issuer:Q,authorization_endpoint:nK(Q,"/authorize"),token_endpoint:nK(Q,"/token"),registration_endpoint:nK(Q,"/register"),revocation_endpoint:nK(Q,"/revoke"),jwks_uri:nK(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:[dK(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 xp(A)}async verifyBearerToken(A,Q={}){let w=_v0(A);if(!w)return;let B=Q.issuer?dK(Q.issuer):this.resolveRequestIssuer(A);return Lv0(w,await this.getJwks(),{issuer:B,...Q.audience?{audience:Q.audience}:{}})}getSetupUrl(A=this.issuer){return this.setupFlow.getSetupUrl(A)}async getOperatorSetupRequired(A=this.issuer){return this.setupFlow.getOperatorSetupRequired(A)}async hasSetupEmailDelivery(A,Q){return this.setupFlow.hasSetupEmailDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupFlow.recordSetupEmailDelivery(A,Q,w)}async handleRequest(A){let Q;try{Q=this.resolveRequestIssuer(A)}catch(B){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:B instanceof Error?B.message:String(B)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&kyA(w))return LyA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return eJ(BZ(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return eJ(BZ(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return eJ(BZ(this.getProtectedResourceMetadata(Q,Q)))}if(A.method==="GET"&&w==="/setup")return this.setupFlow.handleSetupPage(A);if(A.method==="GET"&&w==="/login")return this.handleLoginPage(A);if((A.method==="GET"||A.method==="POST")&&w==="/logout")return this.handleLogout(A);if(A.method==="POST"&&w==="/webauthn/register/options")return this.webauthnEndpoints.handleRegistrationOptions(A);if(A.method==="POST"&&w==="/webauthn/register/verify")return this.webauthnEndpoints.handleRegistrationVerify(A);if(A.method==="POST"&&w==="/webauthn/auth/options")return this.webauthnEndpoints.handleAuthenticationOptions(A);if(A.method==="POST"&&w==="/webauthn/auth/verify")return this.webauthnEndpoints.handleAuthenticationVerify(A);if(A.method==="GET"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizePage(A);if(A.method==="POST"&&w==="/authorize")return this.oauthEndpoints.handleAuthorizeApproval(A);if(A.method==="POST"&&w==="/register")return eJ(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return eJ(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return eJ(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=oJ(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&rJ(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=xv0(new URL(A.url).searchParams.get("return_to"));return bh(Ov0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=xv0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":Zv0(Np(A)),"Cache-Control":"no-store"}})}}L0();var AB0="email:send",OyA=Z.strictObject({to:Z.string().email(),subject:Z.string().min(1),text:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")});wA();L0();var vyA={name:"@brains/notifications",version:"0.2.0-alpha.164",description:"Generic notification routing for transactional and administrative messages",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"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var yv0="notifications:send",Io2=Z.looseObject({}),Fo2=Z.discriminatedUnion("type",[Z.strictObject({type:Z.literal("email"),address:Z.email()})]),ko2=Z.strictObject({recipient:Fo2,title:Z.string().min(1),body:Z.string().min(1),html:Z.string().min(1).optional(),sensitivity:Z.enum(["normal","secret"]).default("normal")}),RyA=Z.discriminatedUnion("status",[Z.strictObject({status:Z.literal("sent"),deliveryId:Z.string().optional()}),Z.strictObject({status:Z.literal("failed")})]);class hyA extends Aw{constructor(A={}){super("notifications",vyA,A,Io2)}async onRegister(A){A.messaging.subscribe(yv0,async(Q)=>{let w=ko2.parse(Q.payload),B={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},$=await A.messaging.send({type:AB0,payload:B});if(!("success"in $)||!$.success||!$.data)return{success:!1,error:"Notification delivery failed"};let f=$.data;if(f.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:f.id?{status:"sent",deliveryId:f.id}:{status:"sent"}}})}}function QB0(A={}){return new hyA(A)}wA();L0();var CyA={name:"@brains/auth-service",version:"0.2.0-alpha.164",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"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 _o2=Z.union([Z.string().email(),Z.object({to:Z.string().email(),subject:Z.string().min(1),body:Z.string().min(1)}).strict()]),No2=Z.object({issuer:Z.string().optional(),trustedIssuers:Z.array(Z.string()).default([]),allowLocalhostIssuers:Z.boolean().optional(),storageDir:Z.string().default("./data/auth"),setupTokenTtlSeconds:Z.number().int().positive().default(Op),setupEmail:_o2.optional()}),wB0;function v7(){return wB0}class Ev0 extends Aw{service;constructor(A={}){super("auth-service",CyA,A,No2)}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 e60({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(),wB0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(wB0===this.service)wB0=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 w=await Q.getOperatorSetupRequired();if(!w)return;let B=Po2(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,B.to))return;let $=await A.messaging.send({type:yv0,payload:{recipient:{type:"email",address:B.to},title:B.subject,body:B.body,sensitivity:"secret"}});if(!("success"in $)||!$.success||!$.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let f=RyA.safeParse($.data);if(!f.success||f.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,B.to,f.data.deliveryId?{deliveryId:f.data.deliveryId}:{})}}function Po2(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return{to:A,subject:"Set up your brain passkey",body:["Set up your brain passkey using this single-use link:","",Q.setupUrl,"",`This link expires at ${w}.`,`Dashboard: ${B}/`,`MCP endpoint: ${B}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
|
|
2293
|
+
`)}}return{to:A.to,subject:gyA(A.subject,Q),body:gyA(A.body,Q)}}function gyA(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),B=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",B)}function vp(A={}){return new Ev0(A)}L0();var Tv0=Z.object({transport:Z.enum(["stdio","http"]).default("http"),mode:Z.enum(["basic","debug"]).default("basic"),httpPort:Z.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:Z.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:Z.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});L0();import{createHash as Oo2,randomUUID as vo2}from"crypto";function jo2(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Rp(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Mo2(A){let Q=jo2(A.data)?A.data:void 0,w=A.args,B=Rp(Q,"entityId")??Rp(Q,"id"),$=A.jobId??Rp(Q,"jobId"),f=Rp(w,"entityType")??Rp(w,"type");if(!B&&!$)return;return{toolName:A.toolName,...f?{entityType:f}:{},...B?{entityId:B}:{},...$?{jobId:$}:{}}}function xo2(A){return A?.map(Mo2).filter((Q)=>Q!==void 0)??[]}function Sv0(A,Q={}){let w=A.pendingConfirmations?.[0];if(w)return{needsConfirmation:!0,toolName:w.toolName,summary:w.summary,...w.completionSummary?{completionSummary:w.completionSummary}:{},...w.preview?{preview:w.preview}:{},args:{approvalId:w.id,...Q.conversationId?{conversationId:Q.conversationId}:{},...w.toolCallId?{toolCallId:w.toolCallId}:{},originalArgs:w.args}};let B=xo2(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...B.length>0?{readYourWrites:B}:{}}}}var yyA=Z.object({message:Z.string().min(1),conversationId:Z.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),EyA=Z.object({approvalId:Z.string().min(1),confirmed:Z.boolean(),conversationId:Z.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function TyA(A,Q,w,B){let $=A.conversationId??w??B??`conversation-${vo2()}`,f=Oo2("sha256").update(Q).digest("hex").slice(0,16);return{handle:$,internalId:`mcp:${f}:${$}`}}function SyA(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 myA(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:yyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=yyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP chat tool is not initialized."};let Y=TyA($,B.userId,B.conversationId,B.channelId),X=await f.agent.chat($.message,Y.internalId,{...SyA(B)});return Sv0(X,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:EyA.shape,visibility:"public",sideEffects:"writes",handler:async(w,B)=>{let $=EyA.parse(w),f=Q();if(!f)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=TyA($,B.userId,B.conversationId,B.channelId),X=await f.agent.confirmPendingAction(Y.internalId,$.confirmed,$.approvalId,SyA(B));return Sv0(X,{conversationId:Y.handle})}}]}wA();function mv0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let B=xx.safeParse(w.payload);if(!B.success)return Q.warn("Received invalid job-progress message",{error:B.error.message}),{success:!1};let $=B.data,f=$.type,Y=$.status,X=$.id;if(Q.debug(`${f} ${X} - ${Y}:`,{id:$.id,message:$.message,progress:$.progress,metadata:$.metadata}),$.batchDetails)Q.debug(`Batch details for ${X}:`,{totalOperations:$.batchDetails.totalOperations,completedOperations:$.batchDetails.completedOperations,failedOperations:$.batchDetails.failedOperations,currentOperation:$.batchDetails.currentOperation,errors:$.batchDetails.errors});if($.jobDetails)Q.debug(`Job details for ${X}:`,{jobType:$.jobDetails.jobType,priority:$.jobDetails.priority,retryCount:$.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var uyA={name:"@brains/mcp",version:"0.2.0-alpha.164",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 AI extends jG{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",uyA,Q,Tv0)}async getTools(){return myA(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"});mv0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=v7();return this.httpServer=uz.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",w=this.context.permissions.getUserLevel("mcp",Q),B=v7(),$=this.config.transport==="http"&&(this.config.authToken?!0:B!==void 0);if($)w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!$)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if(w!=="anchor")throw Error("MCP debug mode requires anchor permissions.")}if(this.mcpTransport.setProtocolMode(this.config.mode),this.mcpTransport.setPermissionLevel(w),this.logger.debug(`Starting MCP ${this.config.transport} transport in ${this.config.mode} mode with ${w} permissions`),this.config.transport==="stdio"){this.stdioServer=gK.createFresh();let f=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(f),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let f=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(f,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(){gK.resetInstance(),uz.resetInstance()}}wA();function hp(A,Q=2000){if(A.length<=Q)return[A];let w=go2(A),B=[],$="";for(let f of w){let Y=$?`
|
|
2294
2294
|
|
|
2295
2295
|
`:"";if($.length+Y.length+f.length<=Q){$+=Y+f;continue}if($)B.push($),$="";if(f.length<=Q){$=f;continue}ho2(f,Q,B,(X)=>{$=X})}if($)B.push($);return B}function ho2(A,Q,w,B){let $="",f=A.split(`
|
|
2296
2296
|
`);for(let Y of f){let X=$?`
|
|
2297
2297
|
`:"";if($.length+X.length+Y.length<=Q){$+=X+Y;continue}if($)w.push($),$="";if(Y.length<=Q){$=Y;continue}Co2(Y,Q,w,(H)=>{$=H})}B($)}function Co2(A,Q,w,B){let $="",f=A.split(" ");for(let Y of f){let X=$?" ":"";if($.length+X.length+Y.length<=Q){$+=X+Y;continue}if($)w.push($);if(Y.length>Q)for(let H=0;H<Y.length;H+=Q){let W=Y.slice(H,H+Q);if(H+Q>=Y.length)$=W;else w.push(W)}else $=Y}B($)}function go2(A){let Q=[],w=A.split(`
|
|
2298
2298
|
`),B="",$=!1;for(let f of w){if(f.startsWith("```"))$=!$;if(!$&&f===""&&B){Q.push(B),B="";continue}B+=(B?`
|
|
2299
|
-
`:"")+f}if(B)Q.push(B);return Q}D2();var UZ=Z1(wS0(),1);wA();L0();var BS0=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...Gm.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var ez1={name:"@brains/discord",version:"0.2.0-alpha.
|
|
2299
|
+
`:"")+f}if(B)Q.push(B);return Q}D2();var UZ=Z1(wS0(),1);wA();L0();var BS0=Z.object({botToken:Z.string().min(1).describe("Discord bot token"),allowedChannels:Z.array(Z.string()).default([]),requireMention:Z.boolean().default(!0),allowDMs:Z.boolean().default(!0),showTypingIndicator:Z.boolean().default(!0),statusMessage:Z.string().default("Mention me to chat"),useThreads:Z.boolean().default(!0),threadAutoArchive:Z.union([Z.literal(60),Z.literal(1440),Z.literal(4320),Z.literal(10080)]).default(1440),...Gm.shape,captureUrlEmoji:Z.string().default("\uD83D\uDD16")});var ez1={name:"@brains/discord",version:"0.2.0-alpha.164",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 Vd=2000,WxQ={completed:"Action completed",declined:"Action declined",failed:"Action failed"},KxQ={completed:2278750,declined:9741240,failed:15680580},UxQ=8388608,GxQ=8000,DxQ=100;function k50(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class SI extends GK{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",ez1,A,BS0);this.fetchText=Q.fetchText??ckA}async onRegister(A){await super.onRegister(A),this.client=new UZ.Client({intents:[UZ.GatewayIntentBits.Guilds,UZ.GatewayIntentBits.GuildMessages,UZ.GatewayIntentBits.MessageContent,UZ.GatewayIntentBits.DirectMessages],partials:[UZ.Partials.Channel]}),this.client.on(UZ.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(UZ.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(UZ.Events.ClientReady,()=>{this.logger.info("Discord bot connected",{tag:this.client?.user?.tag})})}createDaemon(){return{start:async()=>{if(!this.client)throw Error("Discord client not initialized");await this.client.login(this.config.botToken)},stop:async()=>{for(let A of this.typingIntervals.values())clearInterval(A);if(this.typingIntervals.clear(),this.client)await this.client.destroy(),this.client=null},healthCheck:async()=>({status:this.client?.user?"healthy":"error",message:this.client?.user?`Connected as ${this.client.user.tag}`:"Not connected",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!k50(w))return;let B=hp(Q,Vd);for(let $ of B)w.send($).catch((f)=>this.logger.error("Failed to send message",{error:f}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:w,approvalCards:B}){let $=B??(w?[w]:[]),f=$.length>0?this.buildApprovalMessagePayload(Q,$):Q;return this.sendPayloadWithId(A,f)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!k50(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let B=hp(Q,Vd),$;for(let f of B)$=(await w.send(f)).id;return $}async editMessage({channelId:A,messageId:Q,newMessage:w}){if(!A||!this.client)return!1;let B=this.client.channels.cache.get(A);if(!k50(B))return!1;try{return await(await B.messages.fetch(Q)).edit(w.slice(0,Vd)),!0}catch{return!1}}supportsMessageEditing(){return!0}async handleMessage(A){if(A.author.id===this.client?.user?.id)return;if(!this.context)return;let Q=!A.guild,w=A.channel.isThread();if(Q&&!this.config.allowDMs)return;let B=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!B)return;let $=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,f=this.getSpaceChannelId(A),Y=!Q&&this.isConfiguredSpace(f),X={channelId:f,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,f))return;let H=Q||$||!this.config.requireMention||B;if(Y&&(!H||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,f).catch((U)=>this.logger.error("Passive Discord space capture failed",{error:U,channelId:f}));if(!H){if(this.config.captureUrls){let U=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(U.length>0){await A.react(this.config.captureUrlEmoji).catch((G)=>this.logger.debug("React failed",{error:G}));for(let G of U)await this.captureUrlViaAgent(G,A.channel.id,A.author.id,"discord",X).catch((q)=>this.logger.error("URL capture failed",{error:q,url:G}))}}return}let W=this.stripMention(A.content);if(A.attachments.size>0){let U=this.context.permissions.getUserLevel("discord",A.author.id,X);if(U==="anchor"||U==="trusted")for(let q of A.attachments.values()){let b=q.name,J=q.contentType??void 0,V=q.size;if(!this.isUploadableTextFile(b,J))continue;if(!this.isFileSizeAllowed(V))continue;try{let k=await this.fetchText(q.url);W+=`
|
|
2300
2300
|
|
|
2301
2301
|
`+this.formatFileUploadMessage(b,k)}catch(k){this.logger.error("Failed to download attachment",{error:k,filename:b})}}}if(W=W.trim(),!W)return;let K=A.channel.id;await this.routeToAgent(W,K,A,X)}async handleInteraction(A){if(!this.context||!A.isButton())return;let Q=this.parseApprovalButtonCustomId(A.customId);if(!Q)return;let w=`discord-${A.channelId}`;if(!this.pendingConfirmations.get(w)?.has(Q.approvalId)){await A.reply({content:"This approval is no longer pending or has changed.",ephemeral:!0}).catch((Y)=>this.logger.debug("Failed to reply to stale approval button",{error:Y}));return}await A.deferUpdate().catch((Y)=>this.logger.debug("Failed to defer approval button",{error:Y})),await this.clearApprovalInteractionComponents(A);let $=this.buildInteractionConfirmationContext(A),f=await this.context.agent.confirmPendingAction(w,Q.confirmed,Q.approvalId,$);await this.handleAgentResponseToolStatuses(f,w),this.syncPendingApprovalsAfterResolution(w,Q.approvalId,f),await this.sendApprovalResultMessage({channelId:A.channelId,response:f,userPermissionLevel:$.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 w=this.stripMention(A.content).trim();if(!w)return;let B=`discord-${Q}`,$=this.getChannelName(A);await this.context.conversations.start({sessionId:B,interfaceType:"discord",channelId:Q,metadata:{channelName:$,interfaceType:"discord",channelId:Q}}),await this.context.conversations.addMessage({conversationId:B,role:"user",content:w,metadata:this.buildUserMessageMetadata(A,Q,$,{threadId:A.channel.isThread()?A.channel.id:void 0})})}async routeToAgent(A,Q,w,B){if(!this.context)return;let $=this.context.agent,f=Q;if(this.config.useThreads&&w.guild&&!w.channel.isThread())try{f=(await w.startThread({name:Vf(A,DxQ),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(W){this.logger.error("Failed to create thread",{error:W})}let Y=`discord-${f}`,X=this.context.permissions.getUserLevel("discord",w.author.id,B),H=this.getChannelName(w);this.startProcessingInput(f);try{let W=this.client?.channels.cache.get(f);if(k50(W))this.startTypingIndicator(W);if(this.pendingConfirmations.has(Y)){if(await this.handleConfirmationResponse(A,Y,f,w,B))return}let K=await $.chat(A,Y,{userPermissionLevel:X,interfaceType:"discord",channelId:f,channelName:H,...this.buildUserMessageMetadata(w,Q,H,{threadId:f!==Q||w.channel.isThread()?f:void 0})});await this.handleAgentResponseToolStatuses(K,Y);let U=jL(K.cards);if(U.length>0)this.pendingConfirmations.set(Y,new Set(U.map((q)=>q.id)));else if(K.pendingConfirmations)this.pendingConfirmations.set(Y,new Set(K.pendingConfirmations.map((q)=>q.id)));else this.pendingConfirmations.delete(Y);let G=await this.sendMessageWithId({channelId:f,message:UO(K.text,U),approvalCards:U});if(G&&K.toolResults){for(let q of K.toolResults)if(q.jobId)this.trackAgentResponseForJob(q.jobId,G,f)}}catch(W){this.logger.error("Error handling message",{error:W,channelId:f}),this.sendMessageToChannel({channelId:f,message:`**Error:** ${W instanceof Error?W.message:"Unknown error"}`})}finally{this.endProcessingInput(),this.stopTypingIndicator(f)}}buildApprovalMessagePayload(A,Q){let w=Q.length>1;return{content:Vf(A.trim().length>0?`${A}
|
|
2302
2302
|
|
|
@@ -2366,7 +2366,7 @@ ${A.value}
|
|
|
2366
2366
|
`);if(P50(A))return this.renderList(A,0,(Q)=>this.nodeToDiscordMarkdown(Q));if(A.type==="break")return`
|
|
2367
2367
|
`;if(A.type==="thematicBreak")return"---";if(Dm0(A))return`\`\`\`
|
|
2368
2368
|
${zm0(A)}
|
|
2369
|
-
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Jj1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},E50="https://discord.com/api/v10",Ij1=2000,ryQ=/^[0-9a-f]{64}$/,oyQ=/^[0-9a-f]+$/,syQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new nyQ;requestContext=new EyQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new zW("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let B=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!B)throw new zW("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new zW("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??E50,this.botToken=w,this.publicKey=B.trim().toLowerCase(),this.applicationId=$,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((f)=>f.trim()):[]),this.botUserId=$,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new h50("info").child("discord"),this.userName=Q.userName??"bot",!ryQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:oyQ.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let B=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:B.avatar?`https://cdn.discordapp.com/avatars/${B.id}/${B.avatar}.png`:void 0,email:void 0,fullName:B.global_name||B.username,isBot:B.bot??!1,userId:B.id,userName:B.username}}catch{return null}}async handleWebhook(Q,w){let B=await Q.arrayBuffer(),$=new Uint8Array(B),f=new TextDecoder().decode($),Y=Q.headers.get("x-discord-gateway-token");if(Y){if(Y!==this.botToken)return this.logger.warn("Invalid gateway token"),new Response("Invalid gateway token",{status:401});this.logger.info("Discord forwarded Gateway event received");try{let U=JSON.parse(f);return this.handleForwardedGatewayEvent(U,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:f.length,bodyBytesLength:$.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let X=Q.headers.get("x-signature-ed25519"),H=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,X,H))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===RC.Ping,expectedPingType:RC.Ping,id:K.id}),K.type===RC.Ping){let U=JSON.stringify({type:Od.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:Od.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===RC.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Jj1.DeferredUpdateMessage});if(K.type===RC.ApplicationCommand){let U=this.getApplicationCommandContext(K),G=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...G===void 0?{}:{data:{flags:G}},type:Jj1.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,B){if(!(w&&B))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!B}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:B.length,publicKeyLength:this.publicKey.length,timestamp:B,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let $=await Od.verifyKey(Q,w,B,this.publicKey);if(!$){let f=new TextDecoder().decode(Q);this.logger.warn("Discord signature verification failed: invalid signature",{publicKeyLength:this.publicKey.length,signatureLength:w.length,publicKeyPrefix:this.publicKey.slice(0,8),publicKeySuffix:this.publicKey.slice(-8),timestamp:B,bodyLength:Q.length,bodyPrefix:f.slice(0,50)})}return $}catch($){return this.logger.warn("Discord signature verification failed: exception",{error:$}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.custom_id;if(!B){this.logger.warn("No custom_id in component interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in component interaction");return}let f=Q.channel_id,Y=Q.guild_id||"@me",X=Q.message?.id;if(!(f&&X)){this.logger.warn("Missing channel_id or message_id in interaction");return}let H=Q.channel,W=H?.type===11||H?.type===12,K=W&&H?.parent_id?H.parent_id:f,U=W?this.encodeThreadId({guildId:Y,channelId:K,threadId:f}):this.encodeThreadId({guildId:Y,channelId:f}),G=SyQ(B),q={actionId:G.actionId,value:G.value??G.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:X,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:X,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let B=Q.member?.user||Q.user;if(!B)return this.logger.warn("No user in application command interaction"),null;let $=Q.channel_id;if(!$)return this.logger.warn("Missing channel_id in application command interaction"),null;let f=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,H=X&&Y?.parent_id?Y.parent_id:$,W=X?this.encodeThreadId({guildId:f,channelId:H,threadId:$}):this.encodeThreadId({guildId:f,channelId:$}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:W,command:K,interaction:Q,text:U,user:B}}getInteractionFlags(Q){if(!(Q&&this.interactionFlags))return;return this.interactionFlags(Q)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}if(!Q)return;let{channelId:B,command:$,interaction:f,text:Y,user:X}=Q;this.logger.debug("Processing Discord slash command",{command:$,text:Y,userId:X.id,channelId:B}),this.requestContext.run({slashCommand:{channelId:B,interactionToken:f.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:$,text:Y,user:{userId:X.id,userName:X.username,fullName:X.global_name||X.username,isBot:X.bot??!1,isMe:X.id===this.applicationId},adapter:this,raw:f,channelId:B},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(Y)=>{for(let X of Y){if(X.value!==void 0){$.push(String(X.value));continue}if(X.options&&X.options.length>0)B.push(X.name),f(X.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),B=this.getInteractionFlags(w);await Q.deferReply(B===void 0?void 0:{flags:B}),this.handleApplicationCommandInteraction(w);return}if(Q.isMessageComponent())await Q.deferUpdate(),this.handleComponentInteraction(this.normalizeGatewayComponentInteraction(Q))}normalizeGatewaySlashCommandInteraction(Q){return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{name:Q.commandName,options:this.normalizeGatewayCommandOptions(Q.options.data),type:Q.commandType},guild_id:Q.guildId??void 0,id:Q.id,token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayComponentInteraction(Q){let w="values"in Q&&Array.isArray(Q.values)?Q.values:void 0;return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{component_type:Q.componentType,custom_id:Q.customId,values:w},guild_id:Q.guildId??void 0,id:Q.id,message:{id:Q.message.id},token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayChannel(Q){if(!Q.channel)return;let w="parentId"in Q.channel&&typeof Q.channel.parentId==="string"?Q.channel.parentId:void 0;return{id:Q.channel.id,parent_id:w,type:Q.channel.type}}normalizeGatewayCommandOptions(Q){return Q.map((w)=>({name:w.name,options:w.options?this.normalizeGatewayCommandOptions(w.options):void 0,type:w.type,value:w.value}))}normalizeGatewayUser(Q){return{avatar:Q.avatar??void 0,bot:Q.bot,discriminator:Q.discriminator,global_name:Q.globalName??void 0,id:Q.id,username:Q.username}}async handleForwardedGatewayEvent(Q,w){switch(this.logger.info("Processing forwarded Gateway event",{type:Q.type,timestamp:Q.timestamp}),Q.type){case"GATEWAY_MESSAGE_CREATE":await this.handleForwardedMessage(Q.data,w);break;case"GATEWAY_MESSAGE_REACTION_ADD":await this.handleForwardedReaction(Q.data,!0,w);break;case"GATEWAY_MESSAGE_REACTION_REMOVE":await this.handleForwardedReaction(Q.data,!1,w);break;default:this.logger.debug("Forwarded Gateway event (no handler)",{type:Q.type})}return new Response(JSON.stringify({ok:!0}),{status:200,headers:{"Content-Type":"application/json"}})}async handleForwardedMessage(Q,w){if(!this.chat)return;let B=Q.guild_id||"@me",$=Q.channel_id,f,Y=$;if(Q.thread)f=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let q=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(q.parent_id)f=$,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:q.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:$})}let X=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),H=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),W=X||H;if(!f&&W)try{let G=await this.createDiscordThread($,Q.id);f=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let K=this.encodeThreadId({guildId:B,channelId:Y,threadId:f}),U=new d8({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:W});try{await this.chat.handleIncomingMessage(this,K,U)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,Y,X=f;if(Q.channel_type===AP.GuildPublicThread||Q.channel_type===AP.GuildPrivateThread){let q=this.threadParentCache.get(f);if(q&&q.expiresAt>Date.now())Y=f,X=q.parentId;else try{let J=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(J.parent_id)Y=f,X=J.parent_id,this.threadParentCache.set(f,{parentId:J.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(b){this.logger.error("Failed to fetch thread parent for reaction",{error:String(b),channelId:f})}}let H=this.encodeThreadId({guildId:$,channelId:X,threadId:Y}),W=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(W),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:H,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let Y={},X=[],H=[],W=y50(w);if(W){let b=Au0(W);X.push(...b.embeds),H.push(...b.components)}else Y.content=this.truncateContent(sN(this.formatConverter.renderPostable(w),"discord"));if(X.length>0)Y.embeds=X;if(H.length>0)Y.components=H;let K=Rm0(w),U=this.tryPostSlashResponse(f,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,f,Y,K);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:Y.content?.length||0,embedCount:X.length,componentCount:H.length});let q=await(await this.discordFetch(`/channels/${B}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:f,raw:q}}tryPostSlashResponse(Q,w,B){let $=this.requestContext.getStore()?.slashCommand;if(!$||$.channelId!==Q)return;return this.postSlashCommandResponse($,Q,w,B)}async postSlashCommandResponse(Q,w,B,$){let f=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,X=f?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:f,hasFiles:$.length>0});let W=await($.length>0?await this.discordInteractionFetchWithFiles(Y,X,B,$):await this.discordInteractionFetch(Y,X,B)).json();return{id:W.id,threadId:w,raw:W}}async createDiscordThread(Q,w){let B=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:B});try{let f=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:B,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:f.id,threadName:f.name}),f}catch($){if($ instanceof lI&&typeof $.message==="string"&&$.message.includes('"code"')&&$.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:B};throw $}}truncateContent(Q){if(Q.length<=Ij1)return Q;return`${Q.slice(0,Ij1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let H=0;H<$.length;H++){let W=$[H];if(!W)continue;let K=await hm0(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});f.append(`files[${H}]`,U,W.filename)}let Y=await fetch(`${E50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!Y.ok){let H=await Y.text();throw new lI("discord",`Failed to post message: ${Y.status} ${H}`)}let X=await Y.json();return{id:X.id,threadId:w,raw:X}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${E50}${Q}`,{method:w,headers:B?{"Content-Type":"application/json"}:void 0,body:B?JSON.stringify(B):void 0});if(!$.ok){let f=await $.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:$.status,error:f}),new lI("discord",`Discord interaction API error: ${$.status} ${f}`)}return $}async discordInteractionFetchWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let H=$[X];if(!H)continue;let W=await hm0(H.data,{platform:"discord"});if(!W)continue;let K=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${X}]`,K,H.filename)}let Y=await fetch(`${E50}${Q}`,{method:w,body:f});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:X}),new lI("discord",`Discord interaction API error: ${Y.status} ${X}`)}return Y}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X={},H=[],W=[],K=y50(B);if(K){let q=Au0(K);H.push(...q.embeds),W.push(...q.components),X.content=""}else X.content=this.truncateContent(sN(this.formatConverter.renderPostable(B),"discord"));if(H.length>0)X.embeds=H;if(W.length>0)X.components=W;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:X.content?.length||0});let G=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",X)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}async deleteMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: DELETE message",{channelId:f,messageId:w}),await this.discordFetch(`/channels/${f}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=Nd.toDiscord?Nd.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: POST typing",{channelId:f}),await this.discordFetch(`/channels/${f}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B,Y=w.limit||50,X=w.direction??"backward",H=new URLSearchParams;if(H.set("limit",String(Y)),w.cursor)if(X==="backward")H.set("before",w.cursor);else H.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:Y,direction:X,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${f}/messages?${H.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let G=[...K].reverse().map((b)=>this.parseDiscordMessage(b,Q)),q;if(K.length===Y)if(X==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:G,nextCursor:q}}async fetchThread(Q){let{channelId:w,guildId:B}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let f=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:f.name,isDM:f.type===AP.DM||f.type===AP.GroupDM,metadata:{guildId:B,channelType:f.type,raw:f}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let B=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:B.id}),this.encodeThreadId({guildId:"@me",channelId:B.id})}isDM(Q){let{guildId:w}=this.decodeThreadId(Q);return w==="@me"}encodeThreadId(Q){let w=Q.threadId?`:${Q.threadId}`:"";return`discord:${Q.guildId}:${Q.channelId}${w}`}decodeThreadId(Q){let w=Q.split(":");if(w.length<3||w[0]!=="discord")throw new zW("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,B=w.guild_id||"@me",$=this.encodeThreadId({guildId:B,channelId:w.channel_id});return this.parseDiscordMessage(w,$)}parseDiscordMessage(Q,w){let B=Q.type===bk1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,Y=$.id===this.botUserId;return new d8({id:B.id,threadId:w,text:this.formatConverter.extractPlainText(B.content),formatted:this.formatConverter.toAst(B.content),raw:Q,author:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:f,isMe:Y},metadata:{dateSent:new Date(B.timestamp),edited:B.edited_timestamp!==null,editedAt:B.edited_timestamp?new Date(B.edited_timestamp):void 0},attachments:(B.attachments||[]).map((X)=>({type:this.getAttachmentType(X.content_type),url:X.url,name:X.filename,mimeType:X.content_type,size:X.size,width:X.width??void 0,height:X.height??void 0}))})}getAttachmentType(Q){if(!Q)return"file";if(Q.startsWith("image/"))return"image";if(Q.startsWith("video/"))return"video";if(Q.startsWith("audio/"))return"audio";return"file"}rehydrateAttachment(Q){let w=Q.fetchMetadata?.url??Q.url;if(!w)return Q;return{...Q,fetchData:()=>this.downloadAttachment(w)}}async downloadAttachment(Q){let w;try{w=await fetch(Q)}catch(B){throw new lI("discord","Failed to download Discord attachment",B instanceof Error?B:void 0)}if(!w.ok)throw new lI("discord",`Failed to download Discord attachment: ${w.status}`);return Buffer.from(await w.arrayBuffer())}renderFormatted(Q){return this.formatConverter.fromAst(Q)}async discordFetch(Q,w,B){let $=`${this.apiBaseUrl}${Q}`,f={Authorization:`Bot ${this.botToken}`};if(B)f["Content-Type"]="application/json";let Y=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:X}),new lI("discord",`Discord API error: ${Y.status} ${X}`)}return Y}async startGatewayListener(Q,w=180000,B,$){if(!this.chat)return new Response("Chat instance not initialized",{status:500});if(!Q.waitUntil)return new Response("waitUntil not provided",{status:500});this.logger.info("Starting Discord Gateway listener",{durationMs:w,webhookUrl:$?"configured":"not configured"});let f=this.runGatewayListener(w,B,$);return Q.waitUntil(f),new Response(JSON.stringify({status:"listening",durationMs:w,message:`Gateway listener started, will run for ${w/1000} seconds`}),{status:200,headers:{"Content-Type":"application/json"}})}async runGatewayListener(Q,w,B){let $=new $7.Client({intents:[$7.GatewayIntentBits.Guilds,$7.GatewayIntentBits.GuildMessages,$7.GatewayIntentBits.MessageContent,$7.GatewayIntentBits.DirectMessages,$7.GatewayIntentBits.GuildMessageReactions,$7.GatewayIntentBits.DirectMessageReactions],partials:[$7.Partials.Channel]}),f=!1;if(B)$.on("raw",async(Y)=>{if(f)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on($7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on($7.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await $.login(this.botToken),await new Promise((Y)=>{let X=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(X),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(X),Y()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(Y){this.logger.error("Discord Gateway listener error",{error:String(Y)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on($7.Events.MessageCreate,async(B)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if(B.author.bot){this.logger.debug("Ignoring message from bot",{authorId:B.author.id,authorName:B.author.username,isMe:B.author.id===Q.user?.id});return}let $=B.mentions.has(Q.user?.id??""),f=this.mentionRoleIds.length>0&&B.mentions.roles.some((X)=>this.mentionRoleIds.includes(X.id)),Y=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:Y,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,Y)}),Q.on($7.Events.InteractionCreate,async(B)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:B.id,type:B.type});try{await this.handleGatewayInteraction(B)}catch($){this.logger.error("Error handling Gateway interaction",{error:String($),interactionId:B.id})}}),Q.on($7.Events.MessageReactionAdd,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!0)}),Q.on($7.Events.MessageReactionRemove,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!1)})}async forwardGatewayEvent(Q,w){try{this.logger.debug("Forwarding Gateway event to webhook",{type:w.type,webhookUrl:Q});let B=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if(B.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let $=await B.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:B.status,error:$})}}catch(B){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String(B)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let B=Q.guildId||"@me",$=Q.channelId,f=Q.channel.isThread(),Y,X=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)Y=$,X=Q.channel.parentId;if(!Y&&w)try{let K=await this.createDiscordThread($,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let H=this.encodeThreadId({guildId:B,channelId:X,threadId:Y}),W=new d8({id:Q.id,threadId:H,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id:$,guild_id:B,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,H,W)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,Y=Q.message.channel?.isThread?.(),X=f,H;if(Y&&Q.message.channel?.parentId)H=f,X=Q.message.channel.parentId;let W=this.encodeThreadId({guildId:$,channelId:X,threadId:H}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G={adapter:this,threadId:W,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:B,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(f)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:Y,cursor:w.cursor});let W=await(await this.discordFetch(`/channels/${$}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:W.length});let U=[...W].reverse().map((q)=>this.parseDiscordMessage(q,Q)),G;if(W.length===f)if(Y==="backward")G=W.at(-1)?.id;else G=W[0]?.id;return{messages:U,nextCursor:G}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new zW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let H=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((V)=>V.parent_id===f),W=[];try{W=(await(await this.discordFetch(`/channels/${f}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let K=[...H,...W],U=new Set,G=K.filter((V)=>{if(U.has(V.id))return!1;return U.add(V.id),!0}),q=w.limit||50,b=G.slice(0,q),J=[];for(let V of b){let k=this.encodeThreadId({guildId:$,channelId:f,threadId:V.id});try{let O=(await(await this.discordFetch(`/channels/${V.id}/messages?limit=1&after=0`,"GET")).json())[0];if(O)J.push({id:k,rootMessage:this.parseDiscordMessage(O,k),replyCount:V.total_message_sent??V.message_count,lastReplyAt:V.thread_metadata?.archive_timestamp?new Date(V.thread_metadata.archive_timestamp):void 0})}catch{J.push({id:k,rootMessage:new d8({id:V.id,threadId:k,text:V.name,formatted:this.formatConverter.toAst(V.name),raw:V,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:V.total_message_sent??V.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:J.length}),{threads:J,nextCursor:G.length>q?String(q):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:B});let f=await(await this.discordFetch(`/channels/${B}`,"GET")).json();return{id:Q,name:f.name,isDM:f.type===AP.DM||f.type===AP.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);let f={},Y=[],X=[],H=y50(w);if(H){let q=Au0(H);Y.push(...q.embeds),X.push(...q.components)}else f.content=this.truncateContent(sN(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)f.embeds=Y;if(X.length>0)f.components=X;let W=Rm0(w),K=this.tryPostSlashResponse(Q,f,W);if(K)return K;if(W.length>0)return this.postMessageWithFiles($,Q,f,W);this.logger.debug("Discord API: POST channel message",{channelId:$,contentLength:f.content?.length||0});let G=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:G.id,threadId:Q,raw:G}}normalizeDiscordEmoji(Q){let B={"\uD83D\uDC4D":"thumbs_up","\uD83D\uDC4E":"thumbs_down","\u2764\uFE0F":"heart","\u2764":"heart","\uD83D\uDD25":"fire","\uD83D\uDE80":"rocket","\uD83D\uDE4C":"raised_hands","\u2705":"check","\u274C":"x","\uD83D\uDC4B":"wave","\uD83E\uDD14":"thinking","\uD83D\uDE0A":"smile","\uD83D\uDE02":"laugh","\uD83C\uDF89":"party","\u2B50":"star","\u2728":"sparkles","\uD83D\uDC40":"eyes","\uD83D\uDCAF":"100"}[Q]||Q;return cI(B)}};function Lj1(A){return new syQ(A??{})}var ayQ=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let w=this.locks.get(A);if(w&&w.expiresAt>Date.now())return null;let B={threadId:A,token:tyQ(),expiresAt:Date.now()+Q};return this.locks.set(A,B),B}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let w=this.locks.get(A.threadId);if(!w||w.token!==A.token)return!1;if(w.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return w.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,w){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null})}async setIfNotExists(A,Q,w){this.ensureConnected();let B=this.cache.get(A);if(B)if(B.expiresAt!==null&&B.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,w){this.ensureConnected();let B=this.cache.get(A),$;if(B&&B.expiresAt!==null&&B.expiresAt<=Date.now())$=[];else if(B&&Array.isArray(B.value))$=B.value;else $=[];if($.push(Q),w?.maxLength&&$.length>w.maxLength)$=$.slice($.length-w.maxLength);this.cache.set(A,{value:$,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let B=this.queues.get(A);if(!B)B=[],this.queues.set(A,B);if(B.push(Q),B.length>w)B.splice(0,B.length-w);return B.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift();if(Q.length===0)this.queues.delete(A);return w??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,w]of this.locks)if(w.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function tyQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function T50(A){return new ayQ}L0();var eyQ=Z.object({subscribedAt:Z.string().datetime(),routingMode:Z.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:Z.boolean().optional()}),AEQ="chat.discord.subscriptions";function Qu0(A){return A.scoped({namespace:AEQ,schema:eyQ})}function _j1(A,Q=T50()){let w=Qu0(A);return new Nj1(Q,w)}class Nj1{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){await this.subscriptions.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){await this.subscriptions.delete(A)}isSubscribed(A){return this.subscriptions.has(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,w){return this.memoryState.appendToList(A,Q,w)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,w){return this.memoryState.enqueue(A,Q,w)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,w){return this.memoryState.set(A,Q,w)}setIfNotExists(A,Q,w){return this.memoryState.setIfNotExists(A,Q,w)}}function Pj1(A){let{discord:Q}=A;if(!Q)return new xm0({userName:A.userName,adapters:{},state:T50()});let w=Lj1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new xm0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:_j1(A.runtimeState)})}class wu0{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;try{await A.subscribe(),await this.deps.getSubscriptions()?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(w){this.deps.logger.debug("Discord thread subscription failed",{error:w,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){if(this.deps.getPlatform(A)!=="discord")return!1;if(A.isDM)return!0;let w=await this.deps.getSubscriptions()?.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let $={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,$);else await this.deps.getSubscriptions()?.set(A.id,$);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.deps.getSubscriptions()?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((B)=>!B.isBot&&!B.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}wA();class Bu0{deps;constructor(A){this.deps=A}async build(A,Q,w,B){let $={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return $;if(!(B==="anchor"||B==="trusted"))return $;let Y=this.deps.getUploadStore();if(!Y)return $;for(let X of w.attachments){let H=X.name;if(!H)continue;let W=Jz(H,"upload"),K=uV(W,X.mimeType),U=X.size??0,G=nA0(W,K);if(!G){$.notices.push(`Unsupported file upload type: ${W}`);continue}if(!rA0(G,U)){$.notices.push(`File upload too large: ${W}`);continue}try{let q=await this.readAttachmentData(X);if(!q)continue;let b=Iz({filename:W,mediaType:K,content:q,fallbackFilename:"upload"});if(!b.ok){$.notices.push(b.message);continue}let J=await Y.save({filename:b.filename,mediaType:b.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(Mj1(J.filename,J.mediaType,q,J.ref,b.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:W}),$.notices.push(`Could not read file upload: ${W}`)}}return $}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let B=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:w.id,uploaderId:w.author.userId,uploaderUsername:w.author.userName,...B.guildId?{guildId:B.guildId}:{},...B.threadId?{threadId:B.threadId}:{}}}}function jj1(A,Q,w,B){return Mj1(A,Q,w,B,cV(A,Q))}function Mj1(A,Q,w,B,$){if($)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:B};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:B}}function vd(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function _D(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 QEQ(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}function xj1(A,Q){if(A.isDM)return!1;let w=_D(A.id);if(!w.threadId)return!1;let B=QEQ(Q);return B!==void 0&&B!==w.threadId}function S50(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=_D(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function $u0(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return S50(A,w)}function fu0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return S50(A,w)}function Yu0(A,Q){return{channelId:_D(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function CC(A){return A.isDM?"DM":A.channelId}var wEQ="https://discord.com/api/v10";async function Oj1(A){let Q=_D(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let B=A.fetchFn??fetch;try{let $=await B(`${wEQ}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!$.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:$.status})}catch($){A.logger.debug("Failed to clear Discord message components",{error:$,messageId:A.messageId,channelId:w})}}var vj1={name:"@brains/chat",version:"0.2.0-alpha.163",description:"Discord Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.29.0","@chat-adapter/state-memory":"^4.29.0",chat:"^4.29.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},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 $EQ=/https?:\/\/\S+/i,fEQ=/[\s\S]+/,YEQ=1000,XEQ=Z.looseObject({type:Z.literal("card"),children:Z.array(Z.looseObject({type:Z.string()})),imageUrl:Z.string().optional(),subtitle:Z.string().optional(),title:Z.string().optional()}),ZEQ=Z.object({card:Z.custom((A)=>XEQ.safeParse(A).success),fallbackText:Z.string().optional()});class m50 extends GK{threadRegistry=new L50;pendingApprovals;uploadContinuity;promptActions=new fS0(YEQ);toolStatusMessenger=new YS0(this.threadRegistry);cardBuilder=new WS0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new US0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new GS0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await Oj1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new wu0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:xj1,logger:this.logger});chatInputBuilder=new Bu0({getUploadStore:()=>this.context?.uploads.scoped(vd()),getThreadIdParts:_D,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",vj1,A,$S0);this.gatewayLoop=new DS0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new zS0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(vd()),buildApp:(Q)=>Pj1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Vm({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,w)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:w})}}),this.uploadContinuity=new _m({sourceKind:"discord-chat-upload",loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},restoreAttachment:async(Q)=>{let w=this.context?.uploads.scoped(vd());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return jj1(B.record.filename,B.record.mediaType,B.content,B.record.ref)},onLoadError:(Q,w)=>{this.logger.debug("Failed to load prior chat uploads",{error:Q,conversationId:w})},onRestoreError:(Q,w)=>{this.logger.debug("Failed to restore prior chat upload",{error:Q,uploadId:w})}})}async onRegister(A){await super.onRegister(A),this.discordSubscriptions=Qu0(A.runtimeState),this.registerChatHandlers(this.discordApp.build(A.runtimeState))}getWebRoutes(){return this.discordApp.getWebRoutes()}createDaemon(){if(!this.config.adapters.discord)return;return{start:async()=>{await this.discordApp.initialize(),this.gatewayLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.clear(),this.toolStatusMessenger.clear(),await this.discordApp.shutdown()},healthCheck:async()=>({status:this.gatewayLoop.isRunning()?"healthy":"error",message:this.gatewayLoop.isRunning()?"Chat gateway loop running":"Chat gateway loop stopped",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){w.post(B).catch(($)=>this.logger.error("Failed to send chat message",{error:$,channelId:A}));return}if(typeof Q!=="string")return;for(let $ of Jd(A,Q))w.post($).catch((f)=>this.logger.error("Failed to send chat message",{error:f,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){let f=await w.post(B);return this.threadRegistry.trackMessage(w.id,f),f.id}if(typeof Q!=="string")return;let $;for(let f of Jd(A,Q))$=await w.post(f),this.threadRegistry.trackMessage(w.id,$);return $?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let B=this.threadRegistry.getMessage(A,Q);if(!B)return!1;try{let $=await B.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,$);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=ZEQ.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:B}=Q.data;if(B===void 0)return{card:w};return{card:w,fallbackText:B}}formatProgressOutput(A){return HS0(A)}formatCompletionOutput(A){return HS0(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let B={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent(B,B.metadata);return}await super.handleProgressEvent(A,Q)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;await this.toolStatusMessenger.handle(A)}isEnabledPlatform(A){return Bq1(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,B,$)=>{await this.handleRoutedMessage(Q,w,$)}),A.onNewMention(async(Q,w,B)=>{let $=this.getPlatformConfig(Q);if($&&$u0(Q,w,$)&&!Q.isDM&&$.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,B)}),A.onSubscribedMessage(async(Q,w,B)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,B)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(fEQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage($EQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([_50,XS0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(ZS0,async(Q)=>{await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=A.thread;if(!fu0(w,Q,this.config.adapters.discord))return;let B=this.promptActions.get(A.value);if(B?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let $=_D(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),X=w.id;await this.runAgentTurn({thread:w,channelId:X,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let H=await this.context.agent.chat(B.prompt,Y,{userPermissionLevel:f,interfaceType:Q,channelId:X,channelName:CC(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:X,conversationId:Y,response:H,userPermissionLevel:f})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=this.getConversationId(Q,A.thread.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await A.thread.post(this.formatNoticePayload("That approval is no longer pending."));return}let $=A.thread;if(!fu0($,Q,this.config.adapters.discord))return;let f=_D($.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:f.channelId??$.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===_50,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let B=this.getPlatform(A);if(B!=="discord")return;let $=this.getPlatformConfig(A);if(!$)return;if(!$u0(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,w){let B=this.formatErrorPayload(w),$=this.toDiscordCardOutput(B);if($){await A.post($);return}let f=typeof B==="string"?B:"Message failed.";for(let Y of Jd(Q,f))await A.post(Y)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,Y=Yu0(Q,w),X=this.context.permissions.getUserLevel(A,w.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,w,X),W=[...H.attachments];if(await this.attachPriorUploads($,H,X),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments($,W),await this.runAgentTurn({thread:Q,channelId:f,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds($);if(K.size>0){if(await this.handleConfirmationResponse(H.message,$,Q,K,X,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(H.message,B),G=await this.context.agent.chat(U.message,$,{userPermissionLevel:X,interfaceType:A,channelId:f,channelName:CC(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:G,userPermissionLevel:X})}})}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),w=ML(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let B=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),$=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:B,files:Q.files}),f=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((H)=>H.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let X=f??$;if(X)for(let H of w.jobIds)this.trackAgentResponseForJob(H,X,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,B,$,f){if(!Dm(A,B))return!1;let Y=CA0({message:A,approvalIds:B});if(Y.kind==="not-confirmation")return this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve.")),!0;if(Y.kind==="notice")return await w.post(this.formatNoticePayload(Y.message)),!0;return await this.confirmApproval({thread:w,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}}),!0}async confirmApproval(A){let Q=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:"discord",channelId:A.thread.id,channelName:CC(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
|
|
2369
|
+
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Jj1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},E50="https://discord.com/api/v10",Ij1=2000,ryQ=/^[0-9a-f]{64}$/,oyQ=/^[0-9a-f]+$/,syQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new nyQ;requestContext=new EyQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new zW("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let B=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!B)throw new zW("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let $=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!$)throw new zW("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??E50,this.botToken=w,this.publicKey=B.trim().toLowerCase(),this.applicationId=$,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((f)=>f.trim()):[]),this.botUserId=$,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new h50("info").child("discord"),this.userName=Q.userName??"bot",!ryQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:oyQ.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let B=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:B.avatar?`https://cdn.discordapp.com/avatars/${B.id}/${B.avatar}.png`:void 0,email:void 0,fullName:B.global_name||B.username,isBot:B.bot??!1,userId:B.id,userName:B.username}}catch{return null}}async handleWebhook(Q,w){let B=await Q.arrayBuffer(),$=new Uint8Array(B),f=new TextDecoder().decode($),Y=Q.headers.get("x-discord-gateway-token");if(Y){if(Y!==this.botToken)return this.logger.warn("Invalid gateway token"),new Response("Invalid gateway token",{status:401});this.logger.info("Discord forwarded Gateway event received");try{let U=JSON.parse(f);return this.handleForwardedGatewayEvent(U,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:f.length,bodyBytesLength:$.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let X=Q.headers.get("x-signature-ed25519"),H=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature($,X,H))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(f)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===RC.Ping,expectedPingType:RC.Ping,id:K.id}),K.type===RC.Ping){let U=JSON.stringify({type:Od.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:Od.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===RC.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Jj1.DeferredUpdateMessage});if(K.type===RC.ApplicationCommand){let U=this.getApplicationCommandContext(K),G=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...G===void 0?{}:{data:{flags:G}},type:Jj1.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,B){if(!(w&&B))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!B}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:B.length,publicKeyLength:this.publicKey.length,timestamp:B,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let $=await Od.verifyKey(Q,w,B,this.publicKey);if(!$){let f=new TextDecoder().decode(Q);this.logger.warn("Discord signature verification failed: invalid signature",{publicKeyLength:this.publicKey.length,signatureLength:w.length,publicKeyPrefix:this.publicKey.slice(0,8),publicKeySuffix:this.publicKey.slice(-8),timestamp:B,bodyLength:Q.length,bodyPrefix:f.slice(0,50)})}return $}catch($){return this.logger.warn("Discord signature verification failed: exception",{error:$}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let B=Q.data?.custom_id;if(!B){this.logger.warn("No custom_id in component interaction");return}let $=Q.member?.user||Q.user;if(!$){this.logger.warn("No user in component interaction");return}let f=Q.channel_id,Y=Q.guild_id||"@me",X=Q.message?.id;if(!(f&&X)){this.logger.warn("Missing channel_id or message_id in interaction");return}let H=Q.channel,W=H?.type===11||H?.type===12,K=W&&H?.parent_id?H.parent_id:f,U=W?this.encodeThreadId({guildId:Y,channelId:K,threadId:f}):this.encodeThreadId({guildId:Y,channelId:f}),G=SyQ(B),q={actionId:G.actionId,value:G.value??G.actionId,user:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:$.bot??!1,isMe:!1},messageId:X,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:B,messageId:X,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let B=Q.member?.user||Q.user;if(!B)return this.logger.warn("No user in application command interaction"),null;let $=Q.channel_id;if(!$)return this.logger.warn("Missing channel_id in application command interaction"),null;let f=Q.guild_id||"@me",Y=Q.channel,X=Y?.type===11||Y?.type===12,H=X&&Y?.parent_id?Y.parent_id:$,W=X?this.encodeThreadId({guildId:f,channelId:H,threadId:$}):this.encodeThreadId({guildId:f,channelId:$}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:W,command:K,interaction:Q,text:U,user:B}}getInteractionFlags(Q){if(!(Q&&this.interactionFlags))return;return this.interactionFlags(Q)}handleApplicationCommandInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}if(!Q)return;let{channelId:B,command:$,interaction:f,text:Y,user:X}=Q;this.logger.debug("Processing Discord slash command",{command:$,text:Y,userId:X.id,channelId:B}),this.requestContext.run({slashCommand:{channelId:B,interactionToken:f.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:$,text:Y,user:{userId:X.id,userName:X.username,fullName:X.global_name||X.username,isBot:X.bot??!1,isMe:X.id===this.applicationId},adapter:this,raw:f,channelId:B},w)})}parseSlashCommand(Q,w){let B=[Q.startsWith("/")?Q:`/${Q}`],$=[],f=(Y)=>{for(let X of Y){if(X.value!==void 0){$.push(String(X.value));continue}if(X.options&&X.options.length>0)B.push(X.name),f(X.options)}};if(w&&w.length>0)f(w);return{command:B.join(" "),text:$.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),B=this.getInteractionFlags(w);await Q.deferReply(B===void 0?void 0:{flags:B}),this.handleApplicationCommandInteraction(w);return}if(Q.isMessageComponent())await Q.deferUpdate(),this.handleComponentInteraction(this.normalizeGatewayComponentInteraction(Q))}normalizeGatewaySlashCommandInteraction(Q){return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{name:Q.commandName,options:this.normalizeGatewayCommandOptions(Q.options.data),type:Q.commandType},guild_id:Q.guildId??void 0,id:Q.id,token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayComponentInteraction(Q){let w="values"in Q&&Array.isArray(Q.values)?Q.values:void 0;return{application_id:Q.applicationId,channel:this.normalizeGatewayChannel(Q),channel_id:Q.channelId??void 0,data:{component_type:Q.componentType,custom_id:Q.customId,values:w},guild_id:Q.guildId??void 0,id:Q.id,message:{id:Q.message.id},token:Q.token,type:Q.type,user:this.normalizeGatewayUser(Q.user),version:Q.version}}normalizeGatewayChannel(Q){if(!Q.channel)return;let w="parentId"in Q.channel&&typeof Q.channel.parentId==="string"?Q.channel.parentId:void 0;return{id:Q.channel.id,parent_id:w,type:Q.channel.type}}normalizeGatewayCommandOptions(Q){return Q.map((w)=>({name:w.name,options:w.options?this.normalizeGatewayCommandOptions(w.options):void 0,type:w.type,value:w.value}))}normalizeGatewayUser(Q){return{avatar:Q.avatar??void 0,bot:Q.bot,discriminator:Q.discriminator,global_name:Q.globalName??void 0,id:Q.id,username:Q.username}}async handleForwardedGatewayEvent(Q,w){switch(this.logger.info("Processing forwarded Gateway event",{type:Q.type,timestamp:Q.timestamp}),Q.type){case"GATEWAY_MESSAGE_CREATE":await this.handleForwardedMessage(Q.data,w);break;case"GATEWAY_MESSAGE_REACTION_ADD":await this.handleForwardedReaction(Q.data,!0,w);break;case"GATEWAY_MESSAGE_REACTION_REMOVE":await this.handleForwardedReaction(Q.data,!1,w);break;default:this.logger.debug("Forwarded Gateway event (no handler)",{type:Q.type})}return new Response(JSON.stringify({ok:!0}),{status:200,headers:{"Content-Type":"application/json"}})}async handleForwardedMessage(Q,w){if(!this.chat)return;let B=Q.guild_id||"@me",$=Q.channel_id,f,Y=$;if(Q.thread)f=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let q=await(await this.discordFetch(`/channels/${$}`,"GET")).json();if(q.parent_id)f=$,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:$,parentId:q.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:$})}let X=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),H=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),W=X||H;if(!f&&W)try{let G=await this.createDiscordThread($,Q.id);f=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:$,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let K=this.encodeThreadId({guildId:B,channelId:Y,threadId:f}),U=new d8({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:W});try{await this.chat.handleIncomingMessage(this,K,U)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,B){if(!this.chat)return;let $=Q.guild_id||"@me",f=Q.channel_id,Y,X=f;if(Q.channel_type===AP.GuildPublicThread||Q.channel_type===AP.GuildPrivateThread){let q=this.threadParentCache.get(f);if(q&&q.expiresAt>Date.now())Y=f,X=q.parentId;else try{let J=await(await this.discordFetch(`/channels/${f}`,"GET")).json();if(J.parent_id)Y=f,X=J.parent_id,this.threadParentCache.set(f,{parentId:J.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(b){this.logger.error("Failed to fetch thread parent for reaction",{error:String(b),channelId:f})}}let H=this.encodeThreadId({guildId:$,channelId:X,threadId:Y}),W=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(W),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:H,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=Q;if($)B=$;let Y={},X=[],H=[],W=y50(w);if(W){let b=Au0(W);X.push(...b.embeds),H.push(...b.components)}else Y.content=this.truncateContent(sN(this.formatConverter.renderPostable(w),"discord"));if(X.length>0)Y.embeds=X;if(H.length>0)Y.components=H;let K=Rm0(w),U=this.tryPostSlashResponse(f,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,f,Y,K);this.logger.debug("Discord API: POST message",{channelId:B,contentLength:Y.content?.length||0,embedCount:X.length,componentCount:H.length});let q=await(await this.discordFetch(`/channels/${B}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:f,raw:q}}tryPostSlashResponse(Q,w,B){let $=this.requestContext.getStore()?.slashCommand;if(!$||$.channelId!==Q)return;return this.postSlashCommandResponse($,Q,w,B)}async postSlashCommandResponse(Q,w,B,$){let f=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=f?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,X=f?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:f,hasFiles:$.length>0});let W=await($.length>0?await this.discordInteractionFetchWithFiles(Y,X,B,$):await this.discordInteractionFetch(Y,X,B)).json();return{id:W.id,threadId:w,raw:W}}async createDiscordThread(Q,w){let B=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:B});try{let f=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:B,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:f.id,threadName:f.name}),f}catch($){if($ instanceof lI&&typeof $.message==="string"&&$.message.includes('"code"')&&$.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:B};throw $}}truncateContent(Q){if(Q.length<=Ij1)return Q;return`${Q.slice(0,Ij1-3)}...`}async postMessageWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let H=0;H<$.length;H++){let W=$[H];if(!W)continue;let K=await hm0(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});f.append(`files[${H}]`,U,W.filename)}let Y=await fetch(`${E50}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:f});if(!Y.ok){let H=await Y.text();throw new lI("discord",`Failed to post message: ${Y.status} ${H}`)}let X=await Y.json();return{id:X.id,threadId:w,raw:X}}async discordInteractionFetch(Q,w,B){let $=await fetch(`${E50}${Q}`,{method:w,headers:B?{"Content-Type":"application/json"}:void 0,body:B?JSON.stringify(B):void 0});if(!$.ok){let f=await $.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:$.status,error:f}),new lI("discord",`Discord interaction API error: ${$.status} ${f}`)}return $}async discordInteractionFetchWithFiles(Q,w,B,$){let f=new FormData;f.append("payload_json",JSON.stringify(B));for(let X=0;X<$.length;X++){let H=$[X];if(!H)continue;let W=await hm0(H.data,{platform:"discord"});if(!W)continue;let K=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});f.append(`files[${X}]`,K,H.filename)}let Y=await fetch(`${E50}${Q}`,{method:w,body:f});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:X}),new lI("discord",`Discord interaction API error: ${Y.status} ${X}`)}return Y}async editMessage(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X={},H=[],W=[],K=y50(B);if(K){let q=Au0(K);H.push(...q.embeds),W.push(...q.components),X.content=""}else X.content=this.truncateContent(sN(this.formatConverter.renderPostable(B),"discord"));if(H.length>0)X.embeds=H;if(W.length>0)X.components=W;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:X.content?.length||0});let G=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",X)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}async deleteMessage(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: DELETE message",{channelId:f,messageId:w}),await this.discordFetch(`/channels/${f}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,B){let{channelId:$,threadId:f}=this.decodeThreadId(Q),Y=f||$,X=this.encodeEmoji(B);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:X}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${X}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=Nd.toDiscord?Nd.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B;this.logger.debug("Discord API: POST typing",{channelId:f}),await this.discordFetch(`/channels/${f}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:B,threadId:$}=this.decodeThreadId(Q),f=$||B,Y=w.limit||50,X=w.direction??"backward",H=new URLSearchParams;if(H.set("limit",String(Y)),w.cursor)if(X==="backward")H.set("before",w.cursor);else H.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:f,limit:Y,direction:X,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${f}/messages?${H.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let G=[...K].reverse().map((b)=>this.parseDiscordMessage(b,Q)),q;if(K.length===Y)if(X==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:G,nextCursor:q}}async fetchThread(Q){let{channelId:w,guildId:B}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let f=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:f.name,isDM:f.type===AP.DM||f.type===AP.GroupDM,metadata:{guildId:B,channelType:f.type,raw:f}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let B=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:B.id}),this.encodeThreadId({guildId:"@me",channelId:B.id})}isDM(Q){let{guildId:w}=this.decodeThreadId(Q);return w==="@me"}encodeThreadId(Q){let w=Q.threadId?`:${Q.threadId}`:"";return`discord:${Q.guildId}:${Q.channelId}${w}`}decodeThreadId(Q){let w=Q.split(":");if(w.length<3||w[0]!=="discord")throw new zW("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,B=w.guild_id||"@me",$=this.encodeThreadId({guildId:B,channelId:w.channel_id});return this.parseDiscordMessage(w,$)}parseDiscordMessage(Q,w){let B=Q.type===bk1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,$=B.author,f=$.bot??!1,Y=$.id===this.botUserId;return new d8({id:B.id,threadId:w,text:this.formatConverter.extractPlainText(B.content),formatted:this.formatConverter.toAst(B.content),raw:Q,author:{userId:$.id,userName:$.username,fullName:$.global_name||$.username,isBot:f,isMe:Y},metadata:{dateSent:new Date(B.timestamp),edited:B.edited_timestamp!==null,editedAt:B.edited_timestamp?new Date(B.edited_timestamp):void 0},attachments:(B.attachments||[]).map((X)=>({type:this.getAttachmentType(X.content_type),url:X.url,name:X.filename,mimeType:X.content_type,size:X.size,width:X.width??void 0,height:X.height??void 0}))})}getAttachmentType(Q){if(!Q)return"file";if(Q.startsWith("image/"))return"image";if(Q.startsWith("video/"))return"video";if(Q.startsWith("audio/"))return"audio";return"file"}rehydrateAttachment(Q){let w=Q.fetchMetadata?.url??Q.url;if(!w)return Q;return{...Q,fetchData:()=>this.downloadAttachment(w)}}async downloadAttachment(Q){let w;try{w=await fetch(Q)}catch(B){throw new lI("discord","Failed to download Discord attachment",B instanceof Error?B:void 0)}if(!w.ok)throw new lI("discord",`Failed to download Discord attachment: ${w.status}`);return Buffer.from(await w.arrayBuffer())}renderFormatted(Q){return this.formatConverter.fromAst(Q)}async discordFetch(Q,w,B){let $=`${this.apiBaseUrl}${Q}`,f={Authorization:`Bot ${this.botToken}`};if(B)f["Content-Type"]="application/json";let Y=await fetch($,{method:w,headers:f,body:B?JSON.stringify(B):void 0});if(!Y.ok){let X=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:X}),new lI("discord",`Discord API error: ${Y.status} ${X}`)}return Y}async startGatewayListener(Q,w=180000,B,$){if(!this.chat)return new Response("Chat instance not initialized",{status:500});if(!Q.waitUntil)return new Response("waitUntil not provided",{status:500});this.logger.info("Starting Discord Gateway listener",{durationMs:w,webhookUrl:$?"configured":"not configured"});let f=this.runGatewayListener(w,B,$);return Q.waitUntil(f),new Response(JSON.stringify({status:"listening",durationMs:w,message:`Gateway listener started, will run for ${w/1000} seconds`}),{status:200,headers:{"Content-Type":"application/json"}})}async runGatewayListener(Q,w,B){let $=new $7.Client({intents:[$7.GatewayIntentBits.Guilds,$7.GatewayIntentBits.GuildMessages,$7.GatewayIntentBits.MessageContent,$7.GatewayIntentBits.DirectMessages,$7.GatewayIntentBits.GuildMessageReactions,$7.GatewayIntentBits.DirectMessageReactions],partials:[$7.Partials.Channel]}),f=!1;if(B)$.on("raw",async(Y)=>{if(f)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent(B,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers($,()=>f);$.on($7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:$.user?.username,id:$.user?.id})}),$.on($7.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await $.login(this.botToken),await new Promise((Y)=>{let X=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(X),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(X),Y()},{once:!0})}}),this.logger.info("Discord Gateway listener duration elapsed, disconnecting")}catch(Y){this.logger.error("Discord Gateway listener error",{error:String(Y)})}finally{f=!0,$.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on($7.Events.MessageCreate,async(B)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if(B.author.bot){this.logger.debug("Ignoring message from bot",{authorId:B.author.id,authorName:B.author.username,isMe:B.author.id===Q.user?.id});return}let $=B.mentions.has(Q.user?.id??""),f=this.mentionRoleIds.length>0&&B.mentions.roles.some((X)=>this.mentionRoleIds.includes(X.id)),Y=$||f;this.logger.info("Discord Gateway message received",{channelId:B.channelId,guildId:B.guildId,authorId:B.author.id,isMentioned:Y,isUserMentioned:$,isRoleMentioned:f,content:B.content.slice(0,100)}),await this.handleGatewayMessage(B,Y)}),Q.on($7.Events.InteractionCreate,async(B)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:B.id,type:B.type});try{await this.handleGatewayInteraction(B)}catch($){this.logger.error("Error handling Gateway interaction",{error:String($),interactionId:B.id})}}),Q.on($7.Events.MessageReactionAdd,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!0)}),Q.on($7.Events.MessageReactionRemove,async(B,$)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if($.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:$.id,isMe:$.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:B.emoji.name,messageId:B.message.id,channelId:B.message.channelId,userId:$.id}),$.username)await this.handleGatewayReaction(B,$,!1)})}async forwardGatewayEvent(Q,w){try{this.logger.debug("Forwarding Gateway event to webhook",{type:w.type,webhookUrl:Q});let B=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if(B.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let $=await B.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:B.status,error:$})}}catch(B){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String(B)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let B=Q.guildId||"@me",$=Q.channelId,f=Q.channel.isThread(),Y,X=$;if(f&&"parentId"in Q.channel&&Q.channel.parentId)Y=$,X=Q.channel.parentId;if(!Y&&w)try{let K=await this.createDiscordThread($,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:$,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let H=this.encodeThreadId({guildId:B,channelId:X,threadId:Y}),W=new d8({id:Q.id,threadId:H,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id:$,guild_id:B,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,H,W)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),messageId:Q.id})}}async handleGatewayReaction(Q,w,B){if(!this.chat)return;let $=Q.message.guildId||"@me",f=Q.message.channelId,Y=Q.message.channel?.isThread?.(),X=f,H;if(Y&&Q.message.channel?.parentId)H=f,X=Q.message.channel.parentId;let W=this.encodeThreadId({guildId:$,channelId:X,threadId:H}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G={adapter:this,threadId:W,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:B,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let $=Q.split(":")[2];if(!$)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);let f=w.limit||50,Y=w.direction??"backward",X=new URLSearchParams;if(X.set("limit",String(f)),w.cursor)if(Y==="backward")X.set("before",w.cursor);else X.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:$,limit:f,direction:Y,cursor:w.cursor});let W=await(await this.discordFetch(`/channels/${$}/messages?${X.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:W.length});let U=[...W].reverse().map((q)=>this.parseDiscordMessage(q,Q)),G;if(W.length===f)if(Y==="backward")G=W.at(-1)?.id;else G=W[0]?.id;return{messages:U,nextCursor:G}}async listThreads(Q,w={}){let B=Q.split(":"),$=B[1],f=B[2];if(!($&&f))throw new zW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:$,channelId:f});let H=((await(await this.discordFetch(`/guilds/${$}/threads/active`,"GET")).json()).threads||[]).filter((V)=>V.parent_id===f),W=[];try{W=(await(await this.discordFetch(`/channels/${f}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let K=[...H,...W],U=new Set,G=K.filter((V)=>{if(U.has(V.id))return!1;return U.add(V.id),!0}),q=w.limit||50,b=G.slice(0,q),J=[];for(let V of b){let k=this.encodeThreadId({guildId:$,channelId:f,threadId:V.id});try{let O=(await(await this.discordFetch(`/channels/${V.id}/messages?limit=1&after=0`,"GET")).json())[0];if(O)J.push({id:k,rootMessage:this.parseDiscordMessage(O,k),replyCount:V.total_message_sent??V.message_count,lastReplyAt:V.thread_metadata?.archive_timestamp?new Date(V.thread_metadata.archive_timestamp):void 0})}catch{J.push({id:k,rootMessage:new d8({id:V.id,threadId:k,text:V.name,formatted:this.formatConverter.toAst(V.name),raw:V,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:V.total_message_sent??V.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:J.length}),{threads:J,nextCursor:G.length>q?String(q):void 0}}async fetchChannelInfo(Q){let B=Q.split(":")[2];if(!B)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:B});let f=await(await this.discordFetch(`/channels/${B}`,"GET")).json();return{id:Q,name:f.name,isDM:f.type===AP.DM||f.type===AP.GroupDM,memberCount:f.member_count,metadata:{channelType:f.type,raw:f}}}async postChannelMessage(Q,w){let $=Q.split(":")[2];if(!$)throw new zW("discord",`Invalid Discord channel ID: ${Q}`);let f={},Y=[],X=[],H=y50(w);if(H){let q=Au0(H);Y.push(...q.embeds),X.push(...q.components)}else f.content=this.truncateContent(sN(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)f.embeds=Y;if(X.length>0)f.components=X;let W=Rm0(w),K=this.tryPostSlashResponse(Q,f,W);if(K)return K;if(W.length>0)return this.postMessageWithFiles($,Q,f,W);this.logger.debug("Discord API: POST channel message",{channelId:$,contentLength:f.content?.length||0});let G=await(await this.discordFetch(`/channels/${$}/messages`,"POST",f)).json();return{id:G.id,threadId:Q,raw:G}}normalizeDiscordEmoji(Q){let B={"\uD83D\uDC4D":"thumbs_up","\uD83D\uDC4E":"thumbs_down","\u2764\uFE0F":"heart","\u2764":"heart","\uD83D\uDD25":"fire","\uD83D\uDE80":"rocket","\uD83D\uDE4C":"raised_hands","\u2705":"check","\u274C":"x","\uD83D\uDC4B":"wave","\uD83E\uDD14":"thinking","\uD83D\uDE0A":"smile","\uD83D\uDE02":"laugh","\uD83C\uDF89":"party","\u2B50":"star","\u2728":"sparkles","\uD83D\uDC40":"eyes","\uD83D\uDCAF":"100"}[Q]||Q;return cI(B)}};function Lj1(A){return new syQ(A??{})}var ayQ=class{subscriptions=new Set;locks=new Map;cache=new Map;queues=new Map;connected=!1;connectPromise=null;async connect(){if(this.connected)return;if(!this.connectPromise)this.connectPromise=Promise.resolve().then(()=>{this.connected=!0});await this.connectPromise}async disconnect(){this.connected=!1,this.connectPromise=null,this.subscriptions.clear(),this.locks.clear(),this.queues.clear()}async subscribe(A){this.ensureConnected(),this.subscriptions.add(A)}async unsubscribe(A){this.ensureConnected(),this.subscriptions.delete(A)}async isSubscribed(A){return this.ensureConnected(),this.subscriptions.has(A)}async acquireLock(A,Q){this.ensureConnected(),this.cleanExpiredLocks();let w=this.locks.get(A);if(w&&w.expiresAt>Date.now())return null;let B={threadId:A,token:tyQ(),expiresAt:Date.now()+Q};return this.locks.set(A,B),B}async forceReleaseLock(A){this.ensureConnected(),this.locks.delete(A)}async releaseLock(A){this.ensureConnected();let Q=this.locks.get(A.threadId);if(Q&&Q.token===A.token)this.locks.delete(A.threadId)}async extendLock(A,Q){this.ensureConnected();let w=this.locks.get(A.threadId);if(!w||w.token!==A.token)return!1;if(w.expiresAt<Date.now())return this.locks.delete(A.threadId),!1;return w.expiresAt=Date.now()+Q,!0}async get(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return null;if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),null;return Q.value}async set(A,Q,w){this.ensureConnected(),this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null})}async setIfNotExists(A,Q,w){this.ensureConnected();let B=this.cache.get(A);if(B)if(B.expiresAt!==null&&B.expiresAt<=Date.now())this.cache.delete(A);else return!1;return this.cache.set(A,{value:Q,expiresAt:w?Date.now()+w:null}),!0}async delete(A){this.ensureConnected(),this.cache.delete(A)}async appendToList(A,Q,w){this.ensureConnected();let B=this.cache.get(A),$;if(B&&B.expiresAt!==null&&B.expiresAt<=Date.now())$=[];else if(B&&Array.isArray(B.value))$=B.value;else $=[];if($.push(Q),w?.maxLength&&$.length>w.maxLength)$=$.slice($.length-w.maxLength);this.cache.set(A,{value:$,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let B=this.queues.get(A);if(!B)B=[],this.queues.set(A,B);if(B.push(Q),B.length>w)B.splice(0,B.length-w);return B.length}async dequeue(A){this.ensureConnected();let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift();if(Q.length===0)this.queues.delete(A);return w??null}async queueDepth(A){return this.ensureConnected(),this.queues.get(A)?.length??0}async getList(A){this.ensureConnected();let Q=this.cache.get(A);if(!Q)return[];if(Q.expiresAt!==null&&Q.expiresAt<=Date.now())return this.cache.delete(A),[];if(Array.isArray(Q.value))return Q.value;return[]}ensureConnected(){if(!this.connected)throw Error("MemoryStateAdapter is not connected. Call connect() first.")}cleanExpiredLocks(){let A=Date.now();for(let[Q,w]of this.locks)if(w.expiresAt<=A)this.locks.delete(Q)}_getSubscriptionCount(){return this.subscriptions.size}_getLockCount(){return this.cleanExpiredLocks(),this.locks.size}};function tyQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function T50(A){return new ayQ}L0();var eyQ=Z.object({subscribedAt:Z.string().datetime(),routingMode:Z.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:Z.boolean().optional()}),AEQ="chat.discord.subscriptions";function Qu0(A){return A.scoped({namespace:AEQ,schema:eyQ})}function _j1(A,Q=T50()){let w=Qu0(A);return new Nj1(Q,w)}class Nj1{memoryState;subscriptions;constructor(A,Q){this.memoryState=A,this.subscriptions=Q}connect(){return this.memoryState.connect()}disconnect(){return this.memoryState.disconnect()}async subscribe(A){await this.subscriptions.set(A,{subscribedAt:new Date().toISOString()})}async unsubscribe(A){await this.subscriptions.delete(A)}isSubscribed(A){return this.subscriptions.has(A)}acquireLock(A,Q){return this.memoryState.acquireLock(A,Q)}appendToList(A,Q,w){return this.memoryState.appendToList(A,Q,w)}delete(A){return this.memoryState.delete(A)}dequeue(A){return this.memoryState.dequeue(A)}enqueue(A,Q,w){return this.memoryState.enqueue(A,Q,w)}extendLock(A,Q){return this.memoryState.extendLock(A,Q)}forceReleaseLock(A){return this.memoryState.forceReleaseLock(A)}get(A){return this.memoryState.get(A)}getList(A){return this.memoryState.getList(A)}queueDepth(A){return this.memoryState.queueDepth(A)}releaseLock(A){return this.memoryState.releaseLock(A)}set(A,Q,w){return this.memoryState.set(A,Q,w)}setIfNotExists(A,Q,w){return this.memoryState.setIfNotExists(A,Q,w)}}function Pj1(A){let{discord:Q}=A;if(!Q)return new xm0({userName:A.userName,adapters:{},state:T50()});let w=Lj1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new xm0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:_j1(A.runtimeState)})}class wu0{deps;constructor(A){this.deps=A}async subscribeOwnedThread(A,Q){if(!this.deps.isBotCreatedThread(A,Q))return;try{await A.subscribe(),await this.deps.getSubscriptions()?.set(A.id,{subscribedAt:new Date().toISOString()})}catch(w){this.deps.logger.debug("Discord thread subscription failed",{error:w,threadId:A.id})}}async shouldRouteSubscribedMessage(A,Q){if(this.deps.getPlatform(A)!=="discord")return!1;if(A.isDM)return!0;let w=await this.deps.getSubscriptions()?.get(A.id);if(!w)return!1;if(w.routingMode==="mention-required"){if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,w);return Boolean(Q.isMention)}if(!await this.shouldRequireMentionInSubscribedThread(A))return!0;let $={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,$);else await this.deps.getSubscriptions()?.set(A.id,$);return Boolean(Q.isMention)}async postMentionRequiredNotice(A,Q){await A.post("I\u2019ll stop auto-replying now that more people joined. Mention me if you need me."),await this.deps.getSubscriptions()?.set(A.id,{...Q,routingMode:"mention-required",mentionRequiredNoticeSent:!0})}async shouldRequireMentionInSubscribedThread(A){try{return(await A.getParticipants()).filter((B)=>!B.isBot&&!B.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}wA();class Bu0{deps;constructor(A){this.deps=A}async build(A,Q,w,B){let $={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return $;if(!(B==="anchor"||B==="trusted"))return $;let Y=this.deps.getUploadStore();if(!Y)return $;for(let X of w.attachments){let H=X.name;if(!H)continue;let W=Jz(H,"upload"),K=uV(W,X.mimeType),U=X.size??0,G=nA0(W,K);if(!G){$.notices.push(`Unsupported file upload type: ${W}`);continue}if(!rA0(G,U)){$.notices.push(`File upload too large: ${W}`);continue}try{let q=await this.readAttachmentData(X);if(!q)continue;let b=Iz({filename:W,mediaType:K,content:q,fallbackFilename:"upload"});if(!b.ok){$.notices.push(b.message);continue}let J=await Y.save({filename:b.filename,mediaType:b.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});$.attachments.push(Mj1(J.filename,J.mediaType,q,J.ref,b.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:W}),$.notices.push(`Could not read file upload: ${W}`)}}return $}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let B=this.deps.getThreadIdParts(Q.id);return{interfaceType:A,channelId:Q.id,parentChannelId:Q.channelId,messageId:w.id,uploaderId:w.author.userId,uploaderUsername:w.author.userName,...B.guildId?{guildId:B.guildId}:{},...B.threadId?{threadId:B.threadId}:{}}}}function jj1(A,Q,w,B){return Mj1(A,Q,w,B,cV(A,Q))}function Mj1(A,Q,w,B,$){if($)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:B};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:B}}function vd(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function _D(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 QEQ(A){let Q=A.raw;if(typeof Q!=="object"||Q===null)return;let w=Q.channel_id;return typeof w==="string"?w:void 0}function xj1(A,Q){if(A.isDM)return!1;let w=_D(A.id);if(!w.threadId)return!1;let B=QEQ(Q);return B!==void 0&&B!==w.threadId}function S50(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=_D(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some((B)=>typeof B==="string"&&Q.allowedChannels.includes(B))}function $u0(A,Q,w){if(A.isDM&&!w.allowDMs)return!1;if(Q.author.isMe)return!1;if(Q.author.isBot&&!Q.isMention)return!1;return S50(A,w)}function fu0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return S50(A,w)}function Yu0(A,Q){return{channelId:_D(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function CC(A){return A.isDM?"DM":A.channelId}var wEQ="https://discord.com/api/v10";async function Oj1(A){let Q=_D(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let B=A.fetchFn??fetch;try{let $=await B(`${wEQ}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!$.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:$.status})}catch($){A.logger.debug("Failed to clear Discord message components",{error:$,messageId:A.messageId,channelId:w})}}var vj1={name:"@brains/chat",version:"0.2.0-alpha.164",description:"Discord Chat SDK interface for Brains",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@chat-adapter/discord":"^4.29.0","@chat-adapter/state-memory":"^4.29.0",chat:"^4.29.0"},devDependencies:{"@brains/core":"workspace:*","@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14"},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 $EQ=/https?:\/\/\S+/i,fEQ=/[\s\S]+/,YEQ=1000,XEQ=Z.looseObject({type:Z.literal("card"),children:Z.array(Z.looseObject({type:Z.string()})),imageUrl:Z.string().optional(),subtitle:Z.string().optional(),title:Z.string().optional()}),ZEQ=Z.object({card:Z.custom((A)=>XEQ.safeParse(A).success),fallbackText:Z.string().optional()});class m50 extends GK{threadRegistry=new L50;pendingApprovals;uploadContinuity;promptActions=new fS0(YEQ);toolStatusMessenger=new YS0(this.threadRegistry);cardBuilder=new WS0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new US0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new GS0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await Oj1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new wu0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:xj1,logger:this.logger});chatInputBuilder=new Bu0({getUploadStore:()=>this.context?.uploads.scoped(vd()),getThreadIdParts:_D,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",vj1,A,$S0);this.gatewayLoop=new DS0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new zS0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(vd()),buildApp:(Q)=>Pj1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Vm({loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},onRestoreError:(Q,w)=>{this.logger.debug("Failed to load pending chat approvals",{error:Q,conversationId:w})}}),this.uploadContinuity=new _m({sourceKind:"discord-chat-upload",loadMessages:async(Q)=>{return await this.context?.conversations.getMessages(Q,{limit:50})??[]},restoreAttachment:async(Q)=>{let w=this.context?.uploads.scoped(vd());if(!w)throw Error("Chat upload store unavailable");let B=await w.read(Q);return jj1(B.record.filename,B.record.mediaType,B.content,B.record.ref)},onLoadError:(Q,w)=>{this.logger.debug("Failed to load prior chat uploads",{error:Q,conversationId:w})},onRestoreError:(Q,w)=>{this.logger.debug("Failed to restore prior chat upload",{error:Q,uploadId:w})}})}async onRegister(A){await super.onRegister(A),this.discordSubscriptions=Qu0(A.runtimeState),this.registerChatHandlers(this.discordApp.build(A.runtimeState))}getWebRoutes(){return this.discordApp.getWebRoutes()}createDaemon(){if(!this.config.adapters.discord)return;return{start:async()=>{await this.discordApp.initialize(),this.gatewayLoop.start()},stop:async()=>{await this.gatewayLoop.stop(),this.threadRegistry.clear(),this.uploadContinuity.clear(),this.toolStatusMessenger.clear(),await this.discordApp.shutdown()},healthCheck:async()=>({status:this.gatewayLoop.isRunning()?"healthy":"error",message:this.gatewayLoop.isRunning()?"Chat gateway loop running":"Chat gateway loop stopped",lastCheck:new Date})}}sendMessageToChannel({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){w.post(B).catch(($)=>this.logger.error("Failed to send chat message",{error:$,channelId:A}));return}if(typeof Q!=="string")return;for(let $ of Jd(A,Q))w.post($).catch((f)=>this.logger.error("Failed to send chat message",{error:f,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let B=this.toDiscordCardOutput(Q);if(B){let f=await w.post(B);return this.threadRegistry.trackMessage(w.id,f),f.id}if(typeof Q!=="string")return;let $;for(let f of Jd(A,Q))$=await w.post(f),this.threadRegistry.trackMessage(w.id,$);return $?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let B=this.threadRegistry.getMessage(A,Q);if(!B)return!1;try{let $=await B.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,$);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=ZEQ.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:B}=Q.data;if(B===void 0)return{card:w};return{card:w,fallbackText:B}}formatProgressOutput(A){return HS0(A)}formatCompletionOutput(A){return HS0(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let B={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent(B,B.metadata);return}await super.handleProgressEvent(A,Q)}async handleToolActivityEvent(A){if(A.interfaceType===this.id){await super.handleToolActivityEvent(A);return}if(!this.isEnabledPlatform(A.interfaceType))return;await super.handleToolActivityEvent({...A,interfaceType:this.id})}async handleToolStatusUpdate(A){if(A.interfaceType!==this.id||!A.channelId)return;await this.toolStatusMessenger.handle(A)}isEnabledPlatform(A){return Bq1(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,B,$)=>{await this.handleRoutedMessage(Q,w,$)}),A.onNewMention(async(Q,w,B)=>{let $=this.getPlatformConfig(Q);if($&&$u0(Q,w,$)&&!Q.isDM&&$.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,B)}),A.onSubscribedMessage(async(Q,w,B)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,B)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(fEQ,async(Q,w,B)=>{await this.handleRoutedMessage(Q,w,B)});A.onNewMessage($EQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([_50,XS0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(ZS0,async(Q)=>{await this.handlePromptAction(Q)})}async handlePromptAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=A.thread;if(!fu0(w,Q,this.config.adapters.discord))return;let B=this.promptActions.get(A.value);if(B?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let $=_D(w.id),f=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:$.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),X=w.id;await this.runAgentTurn({thread:w,channelId:X,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let H=await this.context.agent.chat(B.prompt,Y,{userPermissionLevel:f,interfaceType:Q,channelId:X,channelName:CC(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:X,conversationId:Y,response:H,userPermissionLevel:f})}})}async handleApprovalAction(A){if(!this.context||!A.thread||!A.value)return;let Q=A.adapter.name;if(!this.isEnabledPlatform(Q))return;let w=this.getConversationId(Q,A.thread.id);if(!(await this.getPendingApprovalIds(w)).has(A.value)){await A.thread.post(this.formatNoticePayload("That approval is no longer pending."));return}let $=A.thread;if(!fu0($,Q,this.config.adapters.discord))return;let f=_D($.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:f.channelId??$.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:$,conversationId:w,approvalId:A.value,confirmed:A.actionId===_50,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,$,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let B=this.getPlatform(A);if(B!=="discord")return;let $=this.getPlatformConfig(A);if(!$)return;if(!$u0(A,Q,$))return;await this.routeToAgent(B,A,Q,w)}async runAgentTurn(A){this.startProcessingInput(A.channelId);try{if(this.getPlatformConfig(A.thread)?.showTypingIndicator)await A.thread.startTyping().catch((Q)=>this.logger.debug("Typing indicator failed",{error:Q,channelId:A.channelId}));await A.body()}catch(Q){this.logger.error(A.logLabel,{error:Q,channelId:A.channelId}),await this.postTurnError(A.thread,A.channelId,Q)}finally{this.endProcessingInput()}}async postTurnError(A,Q,w){let B=this.formatErrorPayload(w),$=this.toDiscordCardOutput(B);if($){await A.post($);return}let f=typeof B==="string"?B:"Message failed.";for(let Y of Jd(Q,f))await A.post(Y)}async routeToAgent(A,Q,w,B){if(!this.context)return;this.threadRegistry.set(Q);let $=this.getConversationId(A,Q.id),f=Q.id,Y=Yu0(Q,w),X=this.context.permissions.getUserLevel(A,w.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,w,X),W=[...H.attachments];if(await this.attachPriorUploads($,H,X),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments($,W),await this.runAgentTurn({thread:Q,channelId:f,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds($);if(K.size>0){if(await this.handleConfirmationResponse(H.message,$,Q,K,X,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(H.message,B),G=await this.context.agent.chat(U.message,$,{userPermissionLevel:X,interfaceType:A,channelId:f,channelName:CC(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:f,conversationId:$,response:G,userPermissionLevel:X})}})}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),w=ML(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let B=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),$=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:B,files:Q.files}),f=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((H)=>H.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let X=f??$;if(X)for(let H of w.jobIds)this.trackAgentResponseForJob(H,X,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,B,$,f){if(!Dm(A,B))return!1;let Y=CA0({message:A,approvalIds:B});if(Y.kind==="not-confirmation")return this.pendingApprovals.deleteConversation(Q),await w.post(this.formatNoticePayload("No pending approval to resolve.")),!0;if(Y.kind==="notice")return await w.post(this.formatNoticePayload(Y.message)),!0;return await this.confirmApproval({thread:w,conversationId:Q,approvalId:Y.approvalId,confirmed:Y.confirmed,userPermissionLevel:$,...f?{metadata:f}:{}}),!0}async confirmApproval(A){let Q=await this.context?.agent.confirmPendingAction(A.conversationId,A.confirmed,A.approvalId,{userPermissionLevel:A.userPermissionLevel,interfaceType:"discord",channelId:A.thread.id,channelName:CC(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
|
|
2370
2370
|
|
|
2371
2371
|
`)}formatConfirmationResponsePayload(A,Q,w,B){let $=lA0({response:A,confirmed:Q,remainingApprovalHelp:w,deniedCardIds:B,formatCard:(f)=>this.cardBuilder.formatStructuredCard(f,B),formatPendingConfirmationHelp:zO});return{card:{type:"card",title:uA0($.variant),children:$.parts.map((f)=>({type:"text",content:f}))},fallbackText:$.parts.join(`
|
|
2372
2372
|
|
|
@@ -2438,7 +2438,7 @@ ${zm0(A)}
|
|
|
2438
2438
|
<p>Once built, this page will be replaced with your actual website.</p>
|
|
2439
2439
|
</div>
|
|
2440
2440
|
</body>
|
|
2441
|
-
</html>`;var DM1={name:"@brains/webserver",version:"0.2.0-alpha.163",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 iI extends jG{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",DM1,A,_u0)}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 t50({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,w=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,B=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,$=[];if(Q){if($.push(`Production: ${w}`),A?.previewUrl)$.push(`Preview: ${B}`)}return{status:Q?"healthy":"error",message:Q?$.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?B:void 0,productionUrl:Q?w:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!zM1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(qM1(this.config.previewDistDir,"index.html"),Nu0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!zM1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(qM1(this.config.productionDistDir,"index.html"),Nu0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}T6();wA();L0();pL();var bM1={name:"@brains/web-chat",version:"0.2.0-alpha.163",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",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/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",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"};wA();async function VM1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing document id",{status:400});let f=await IM1({entityType:"document",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Document not found",{status:404});if(typeof f.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=zz("document",f.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let X=qz(f.metadata,$,"document",Y.mimeType);return FM1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function JM1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing image id",{status:400});let f=await IM1({entityType:"image",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Image not found",{status:404});if(typeof f.content!=="string")return new Response("Image content is not an image",{status:415});let Y=zz("image",f.content);if(!Y)return new Response("Image content is not an image",{status:415});let X=qz(f.metadata,$,"image",Y.mimeType);return FM1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function IM1(A){let Q={entityType:A.entityType,id:A.id},w=await bz({entityRef:Q,userLevel:A.permissionLevel,getEntity:(B)=>A.entityService.getEntity(B),getVisibleEntity:(B,$)=>A.entityService.getEntity({...B,visibilityScope:$})});return w.status==="visible"?w.entity:void 0}function FM1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":SV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}L0();wA();var Td="upload",kM1=fO;var BTQ={namespace:"upload",refKind:Td,routePath:"/api/chat/uploads"};function e50(){return BTQ}wA();bF0();var LM1=iA0;var _M1=dA0;var $TQ="file",fTQ=16384;async function NM1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=Number(A.headers.get("content-length"));if(Number.isFinite(w)&&w>_M1+fTQ)return new Response("File upload too large",{status:400});let B;try{B=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let $=B.get($TQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),Y=Iz({filename:$.name,mediaType:$.type,content:f});if(!Y.ok)return new Response(Y.message,{status:400});let X=Q.getUploadStore(),H=await X.save({filename:Y.filename,mediaType:Y.mediaType,content:f});return Response.json(X.toResponseBody(H),{status:201})}async function PM1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=new URL(A.url).searchParams.get("id")?.trim();if(!w)return new Response("Missing upload id",{status:400});let B=await xM1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,Y=OM1($,f);if(Y instanceof Response)return Y;let X=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(f).buffer;return new Response(H,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":SV({disposition:X,filename:$.filename})}})}function jM1(A){let Q=Jz(A.filename??LM1),w=XTQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=Iz({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return vM1(B,w.buffer)}async function MM1(A,Q){let w=await xM1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=OM1(B,$);if(f instanceof Response)return f;return vM1(f,$,{kind:Td,id:A})}async function xM1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof MG)return YTQ(w);throw w}}function OM1(A,Q){let w=Iz({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function vM1(A,Q,w){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}}}function YTQ(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 XTQ(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let B=A.slice(5,A.indexOf(",")).split(";").some(($)=>$.toLowerCase()==="base64");try{let $=B?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:$,byteLength:$.byteLength}}catch{return null}}var ZTQ=Z.object({type:Z.literal("text"),text:Z.string()}),HTQ=Z.object({type:Z.literal("file"),mediaType:Z.string().optional(),filename:Z.string().optional(),url:Z.string()}),WTQ=Z.looseObject({state:Z.literal("approval-responded"),approval:Z.object({id:Z.string(),approved:Z.boolean()})}),KTQ=Z.object({id:Z.string().optional(),role:Z.string(),parts:Z.array(Z.unknown()).optional(),content:Z.string().optional()}),RM1=Z.object({id:Z.string().optional(),messages:Z.array(KTQ).min(1),trigger:Z.string().optional()}),UTQ=Z.object({kind:Z.literal(Td),id:Z.string().regex(kM1)}),GTQ=Z.object({type:Z.literal("data-upload"),data:Z.object({ref:UTQ})});async function hM1(A,Q){let w=DTQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let Y of w.parts??[]){let X=ZTQ.safeParse(Y);if(X.success){if(X.data.text.length>0)B.push(X.data.text);continue}let H=HTQ.safeParse(Y);if(H.success){let K=jM1(H.data);if(K instanceof Response)return K;$.push(K);continue}let W=GTQ.safeParse(Y);if(W.success){let K=await MM1(W.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;$.push(K);continue}if(zTQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
|
|
2441
|
+
</html>`;var DM1={name:"@brains/webserver",version:"0.2.0-alpha.164",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 iI extends jG{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",DM1,A,_u0)}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 t50({logger:A.logger,productionDistDir:this.config.productionDistDir,sharedImagesDir:this.config.sharedImagesDir,productionPort:this.config.productionPort,...this.config.enablePreview&&this.config.previewDistDir&&{previewDistDir:this.config.previewDistDir},...this.config.enablePreview&&this.config.previewPort&&{previewPort:this.config.previewPort},getHealthData:()=>A.appInfo(),getWebRoutes:()=>A.webRoutes.getRoutes(),getApiRoutes:()=>A.apiRoutes.getRoutes(),messageBus:A.apiRoutes.getMessageBus()})}getServerManager(){if(!this.serverManager)throw Error("ServerManager not initialized \u2014 onRegister not called");return this.serverManager}requiresDaemonStartup(){return!0}createDaemon(){return{start:async()=>{await this.ensureDistDirectories(),await this.getServerManager().start()},stop:async()=>{await this.serverManager?.stop()},healthCheck:async()=>{let A=this.serverManager?.getStatus(),Q=A?.running??!1,w=this.siteUrl??A?.productionUrl??`http://localhost:${this.config.productionPort}`,B=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,$=[];if(Q){if($.push(`Production: ${w}`),A?.previewUrl)$.push(`Preview: ${B}`)}return{status:Q?"healthy":"error",message:Q?$.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?B:void 0,productionUrl:Q?w:void 0}}}}}async handleProgressEvent(A,Q){}async ensureDistDirectories(){let{mkdir:A,writeFile:Q}=await import("fs/promises");if(this.config.enablePreview&&this.config.previewDistDir&&!zM1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(qM1(this.config.previewDistDir,"index.html"),Nu0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!zM1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(qM1(this.config.productionDistDir,"index.html"),Nu0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}T6();wA();L0();pL();var bM1={name:"@brains/web-chat",version:"0.2.0-alpha.164",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",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/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",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"};wA();async function VM1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing document id",{status:400});let f=await IM1({entityType:"document",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Document not found",{status:404});if(typeof f.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=zz("document",f.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let X=qz(f.metadata,$,"document",Y.mimeType);return FM1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function JM1(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let B=new URL(A.url),$=B.searchParams.get("id")?.trim();if(!$)return new Response("Missing image id",{status:400});let f=await IM1({entityType:"image",id:$,permissionLevel:w,entityService:Q.entityService});if(!f)return new Response("Image not found",{status:404});if(typeof f.content!=="string")return new Response("Image content is not an image",{status:415});let Y=zz("image",f.content);if(!Y)return new Response("Image content is not an image",{status:415});let X=qz(f.metadata,$,"image",Y.mimeType);return FM1({requestUrl:B,data:Y.data,mediaType:Y.mimeType,filename:X})}async function IM1(A){let Q={entityType:A.entityType,id:A.id},w=await bz({entityRef:Q,userLevel:A.permissionLevel,getEntity:(B)=>A.entityService.getEntity(B),getVisibleEntity:(B,$)=>A.entityService.getEntity({...B,visibilityScope:$})});return w.status==="visible"?w.entity:void 0}function FM1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":SV({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}L0();wA();var Td="upload",kM1=fO;var BTQ={namespace:"upload",refKind:Td,routePath:"/api/chat/uploads"};function e50(){return BTQ}wA();bF0();var LM1=iA0;var _M1=dA0;var $TQ="file",fTQ=16384;async function NM1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=Number(A.headers.get("content-length"));if(Number.isFinite(w)&&w>_M1+fTQ)return new Response("File upload too large",{status:400});let B;try{B=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let $=B.get($TQ);if(!($ instanceof File))return new Response("Missing upload file",{status:400});let f=Buffer.from(await $.arrayBuffer()),Y=Iz({filename:$.name,mediaType:$.type,content:f});if(!Y.ok)return new Response(Y.message,{status:400});let X=Q.getUploadStore(),H=await X.save({filename:Y.filename,mediaType:Y.mediaType,content:f});return Response.json(X.toResponseBody(H),{status:201})}async function PM1(A,Q){if(!await Q.resolveOperatorSession(A))return new Response("Forbidden",{status:403});let w=new URL(A.url).searchParams.get("id")?.trim();if(!w)return new Response("Missing upload id",{status:400});let B=await xM1(w,Q.getUploadStore());if(B instanceof Response)return B;let{record:$,content:f}=B,Y=OM1($,f);if(Y instanceof Response)return Y;let X=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(f).buffer;return new Response(H,{headers:{"Content-Type":$.mediaType,"Content-Length":String(f.byteLength),"Content-Disposition":SV({disposition:X,filename:$.filename})}})}function jM1(A){let Q=Jz(A.filename??LM1),w=XTQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let B=Iz({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!B.ok)return new Response(B.message,{status:400});return vM1(B,w.buffer)}async function MM1(A,Q){let w=await xM1(A,Q);if(w instanceof Response)return w;let{record:B,content:$}=w,f=OM1(B,$);if(f instanceof Response)return f;return vM1(f,$,{kind:Td,id:A})}async function xM1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof MG)return YTQ(w);throw w}}function OM1(A,Q){let w=Iz({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function vM1(A,Q,w){if(A.kind==="text")return{kind:"text",filename:A.filename,mediaType:A.mediaType,content:A.text,sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}};return{kind:"file",filename:A.filename,mediaType:A.mediaType,data:new Uint8Array(Q),sizeBytes:A.sizeBytes,...w!==void 0?{source:w}:{}}}function YTQ(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 XTQ(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let B=A.slice(5,A.indexOf(",")).split(";").some(($)=>$.toLowerCase()==="base64");try{let $=B?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:$,byteLength:$.byteLength}}catch{return null}}var ZTQ=Z.object({type:Z.literal("text"),text:Z.string()}),HTQ=Z.object({type:Z.literal("file"),mediaType:Z.string().optional(),filename:Z.string().optional(),url:Z.string()}),WTQ=Z.looseObject({state:Z.literal("approval-responded"),approval:Z.object({id:Z.string(),approved:Z.boolean()})}),KTQ=Z.object({id:Z.string().optional(),role:Z.string(),parts:Z.array(Z.unknown()).optional(),content:Z.string().optional()}),RM1=Z.object({id:Z.string().optional(),messages:Z.array(KTQ).min(1),trigger:Z.string().optional()}),UTQ=Z.object({kind:Z.literal(Td),id:Z.string().regex(kM1)}),GTQ=Z.object({type:Z.literal("data-upload"),data:Z.object({ref:UTQ})});async function hM1(A,Q){let w=DTQ(A);if(!w)return{message:"",attachments:[]};let B=[],$=[];for(let Y of w.parts??[]){let X=ZTQ.safeParse(Y);if(X.success){if(X.data.text.length>0)B.push(X.data.text);continue}let H=HTQ.safeParse(Y);if(H.success){let K=jM1(H.data);if(K instanceof Response)return K;$.push(K);continue}let W=GTQ.safeParse(Y);if(W.success){let K=await MM1(W.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;$.push(K);continue}if(zTQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:B.length>0?B.join(`
|
|
2442
2442
|
|
|
2443
2443
|
`):w.content??"",attachments:$,...w.id?{messageId:w.id}:{}}}function CM1(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map((w)=>WTQ.safeParse(w)).filter((w)=>w.success).map((w)=>w.data.approval)}function DTQ(A){for(let Q=A.messages.length-1;Q>=0;Q-=1){let w=A.messages[Q];if(w?.role==="user")return w}return}function zTQ(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}wA();var qTQ=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function A90(A){return A.replace(qTQ,"").trimEnd()}wA();function gM1(A,Q,w){A.write({type:"text-start",id:Q}),A.write({type:"text-delta",id:Q,delta:w}),A.write({type:"text-end",id:Q})}function Pu0(A,Q){let w=Q.directives.flatMap((B)=>{switch(B.kind){case"artifact":case"supplemental":return[B.card];case"approvals":return B.cards;default:return[]}});for(let B of w){let $=tA0(B);if($.kind==="attachment"){A.write({type:"data-attachment",id:$.id,data:$});continue}if($.kind==="sources"){A.write({type:"data-sources",id:$.id,data:$});continue}if($.kind==="actions"){A.write({type:"data-actions",id:$.id,data:$});continue}let f=$.toolCallId??$.id,Y=$.input??{};switch(A.write({type:"tool-input-available",toolCallId:f,toolName:$.toolName,input:Y,dynamic:!0,title:$.preview?`${$.summary}
|
|
2444
2444
|
|
|
@@ -5729,7 +5729,7 @@ ${dM1}</style></head><body>${md(A)}<main id="root" data-web-chat-root>Brain Chat
|
|
|
5729
5729
|
`);$=Y.pop()??"";for(let X of Y){let H=X.split(`
|
|
5730
5730
|
`).find((J)=>J.startsWith("data: "));if(!H)continue;let W;try{let J=YSQ.safeParse(JSON.parse(H.slice(6)));if(!J.success)continue;W=J.data}catch{return w.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let K=W.result;if(!K?.final)continue;w.cancel().catch(()=>{});let U=K.status,G=U?.state??"unknown",b=(U?.message?.parts??[]).filter((J)=>J.kind==="text"&&typeof J.text==="string").map((J)=>J.text).join(`
|
|
5731
5731
|
`)||"No response text";return{success:!0,data:{state:G,response:b}}}f=await Fx1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class ud extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class cd extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function zSQ(A,Q,w,B){let $=new AbortController,f;try{return await Promise.race([A(Q,{...w,signal:$.signal}),new Promise((Y,X)=>{f=setTimeout(()=>{$.abort(),X(new ud(B))},B)})])}catch(Y){if(Y instanceof ud)throw Y;if($.signal.aborted)throw new ud(B);throw Y}finally{if(f)clearTimeout(f)}}async function Fx1(A,Q){let w;try{return await Promise.race([A.read(),new Promise((B,$)=>{w=setTimeout(()=>$(new cd(Q)),Q)})])}catch(B){if(B instanceof cd)A.cancel().catch(()=>{});throw B}finally{if(w)clearTimeout(w)}}function qSQ(A){if(A instanceof ud||A instanceof cd)return!1;return A instanceof Error}function Eu0(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof cd)return`${A.message}${w}`;let B=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${B}`}async function Tu0(A,Q={},w={}){let B=Q.fetch??globalThis.fetch,$={requestTimeoutMs:Q.requestTimeoutMs??XSQ,streamIdleTimeoutMs:Q.streamIdleTimeoutMs??ZSQ,maxNetworkAttempts:Q.maxNetworkAttempts??HSQ},f=USQ(A.agent);if(!f.ok)return{success:!1,error:f.error};let{agentId:Y}=f;if(!Q.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let X=await Q.entityService.getEntity({entityType:"agent",id:Y,visibilityScope:J5("agent_call is anchor-only and resolves saved remote agents at any visibility")});if(!X){if(w.requireSaved)return{success:!1,error:`Agent ${Y} is not saved or approved.`,code:"agent_not_saved"};if(!GSQ(Y))return{success:!1,error:`Agent ${A.agent} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let U=`https://${Y}`,G=await Jx1(U,B);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${Y}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let q=Vx1(G.url,Y);if(!q.ok)return{success:!1,error:q.error};let b=await Ix1(G.url,A.message,B,Q.requestSigner,$);if("success"in b&&b.success===!0){let J=typeof b.data==="object"&&b.data!==null?b.data:{};return{...b,data:{...J,agentCall:{mode:"one-shot",agent:Y},agentContactCandidate:{source:{kind:"url",url:f.sourceUrl??Y}}}}}return b}if(X.metadata.status==="archived")return{success:!1,error:`Agent ${Y} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(X.metadata.status!=="approved")return{success:!1,error:`Agent ${Y} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let H=`https://${Y}`,W=await Jx1(H,B);if(!W)return{success:!1,error:`Could not fetch Agent Card from ${H}`};let K=Vx1(W.url,Y);if(!K.ok)return{success:!1,error:K.error};return Ix1(W.url,A.message,B,Q.requestSigner,$)}function Lx1(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:WSQ,visibility:"trusted",sideEffects:"external",handler:async(Q)=>{let w=KSQ.safeParse(Q);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};return Tu0(w.data,A)}}}wA();L0();var bSQ=Z.object({agent:Z.string().trim().min(1).max(253),instruction:Z.string().trim().min(1).max(2000),selection:Z.string().min(1).max(8000)});function _x1(A,Q){A.messaging.subscribe("a2a:call:request",async(w)=>{let B=bSQ.safeParse(w.payload);if(!B.success)return{success:!1,error:"Invalid A2A call request"};let{agent:$,instruction:f,selection:Y}=B.data,X=await Tu0({agent:$,message:["A CMS author is asking about selected markdown.",`Instruction: ${f}`,"","Selected markdown:",Y].join(`
|
|
5732
|
-
`)},Q,{requireSaved:!0});if("success"in X&&X.success===!0)return{success:!0,data:X.data};return{success:!1,error:"error"in X?X.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:J5("operator CMS lists approved A2A contacts at any visibility")}}})).filter(($)=>$.metadata.status==="approved").map(($)=>{let f=$.metadata.name;return{id:$.id,label:typeof f==="string"&&f.length>0?f:$.id}}).sort(($,f)=>$.label.localeCompare(f.label))}}})}var Su0={name:"@brains/a2a",version:"0.2.0-alpha.163",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 JSQ={"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 uC extends jG{agentCard;taskManager=new yu0;agentService;jwksResolver=new Cu0;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",Su0,A,Hx1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,_x1(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(),w=A.identity.getProfile(),B=A.tools.listForPermissionLevel("public"),$;if(A.entityService.hasEntityType("skill"))try{let f=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(f.length>0)$=f.map((Y)=>Pm.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=Wx1({character:Q,profile:w,version:Su0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:$,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let w=new URL(A.url),B=new URL(`${w.pathname}${w.search}`,oJ(A)),$=await Yx1({method:A.method,url:B.toString(),headers:A.headers,body:Q},this.jwksResolver);if($){let f=await v7()?.getA2APeerTrust($.domain);return{permissionLevel:f?.keyFingerprint===$.keyFingerprint?f.grantedLevel:"public",callerDomain:$.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(JSQ))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new yC;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),B;try{B=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let $;try{$=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let f=Gx1.safeParse($);if(!f.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(f.data.method==="message/stream"){let X=zx1.safeParse(f.data.params??{});if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${X.error.message}`},id:f.data.id}));let H=qx1(f.data.id,X.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:W}=H;return this.withCors(new Response(W,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await Dx1(f.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.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:"/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=v7();if(!A)return;let Q=A.getIssuer();if(rJ(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let B=await A.getA2ASigningKey();await fx1(w,B.privateJwk,B.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[Lx1(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()=>{this.logger.info("A2A server stopped")}}}}wA();L0();var Nx1={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 Px1={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 jx1={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 Mx1={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 xx1={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 Ox1={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 vx1={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 Rx1={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 hx1={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 xSQ=Z.object({type:Z.string()}).catchall(Z.unknown()),OSQ=Z.object({lexicon:Z.literal(1),id:Z.string(),defs:Z.object({main:Z.object({type:Z.literal("record"),key:Z.string().min(1),record:Z.object({type:Z.literal("object"),required:Z.array(Z.string()).optional(),properties:Z.record(Z.string(),xSQ)})})})});function fU(A){return OSQ.parse(A)}var _6={"ai.rizom.brain.card":fU(Nx1),"ai.rizom.brain.deck":fU(Px1),"ai.rizom.brain.link":fU(jx1),"ai.rizom.brain.note":fU(Mx1),"ai.rizom.brain.post":fU(xx1),"ai.rizom.brain.project":fU(Ox1),"ai.rizom.brain.series":fU(vx1),"ai.rizom.brain.socialPost":fU(Rx1),"ai.rizom.brain.topic":fU(hx1)},vSQ="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function Cq(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:vSQ}}var Cx1={"ai.rizom.brain.card":Cq("@brains/atproto"),"ai.rizom.brain.deck":Cq("@brains/decks"),"ai.rizom.brain.link":Cq("@brains/link"),"ai.rizom.brain.note":Cq("@brains/note"),"ai.rizom.brain.post":Cq("@brains/blog"),"ai.rizom.brain.project":Cq("@brains/portfolio"),"ai.rizom.brain.series":Cq("@brains/series"),"ai.rizom.brain.socialPost":Cq("@brains/social-media"),"ai.rizom.brain.topic":Cq("@brains/topics")};function nI(){return Object.values(_6)}function Y90(A){if(!(A in _6))return;return _6[A]}function X90(){return Object.entries(Cx1).map(([A,Q])=>({id:A,...Q}))}L0();function Z90(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var RSQ=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function hSQ(A){let Q=Z.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine((B)=>A.knownValues?.includes(B),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine((B)=>RSQ.test(B)&&!Number.isNaN(Date.parse(B)),{message:"expected datetime"});if(A.format==="uri")w=w.refine((B)=>{try{return new URL(B),!0}catch{return!1}},{message:"expected uri"});return w}function gx1(A){switch(A.type){case"string":return hSQ(A);case"integer":return Z.number().int();case"boolean":return Z.boolean();case"array":{let Q=A.items?gx1(A.items):Z.unknown(),w=Z.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return CSQ(A);case"blob":return Z.custom(Z90,{message:"expected blob"});default:return Z.unknown()}}function yx1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=gx1($);w[B]=Q.has(B)?f:f.optional()}return w}function CSQ(A){return Z.object(yx1(A)).passthrough()}function mu0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:Z.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function gSQ(A,Q){if(mu0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),Z90(A.brain))mu0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(Z90(A.anchor))mu0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function YU(A){let Q=Z.object({...yx1(A.defs.main.record),$type:Z.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(gSQ):Q}var uu0={"ai.rizom.brain.card":YU(_6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":YU(_6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":YU(_6["ai.rizom.brain.link"]),"ai.rizom.brain.note":YU(_6["ai.rizom.brain.note"]),"ai.rizom.brain.post":YU(_6["ai.rizom.brain.post"]),"ai.rizom.brain.project":YU(_6["ai.rizom.brain.project"]),"ai.rizom.brain.series":YU(_6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":YU(_6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":YU(_6["ai.rizom.brain.topic"])};function ySQ(A,Q){let w=A;for(let B of Q){if(typeof B==="symbol")return;if(Array.isArray(w)){w=w[Number(B)];continue}if(!Z90(w))return;w=w[String(B)]}return w}function ESQ(A,Q,w){let B=w.path.join(".");if(B==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&ySQ(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${B}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${B}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${B}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${B}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${B}: ${w.message}`}function gq(A,Q){let w=YU(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(ESQ(A,Q,B))}L0();var ld="atproto:brain-card-discovered",cu0="atproto:brain-discovered",lu0="atproto:brain-card-refreshed",TSQ=Z.custom((A)=>uu0["ai.rizom.brain.card"].safeParse(A).success),pu0=Z.object({repoDid:Z.string().min(1),uri:Z.string().min(1),cid:Z.string().min(1),record:TSQ}).strict(),SSQ=Z.object({agentId:Z.string().min(1),name:Z.string().min(1),url:Z.string().url(),status:Z.enum(["discovered","approved","archived"]),repoDid:Z.string().min(1).optional(),brainDid:Z.string().min(1).optional(),anchorDid:Z.string().min(1).optional(),cardUri:Z.string().min(1).optional(),cardCid:Z.string().min(1).optional()}).strict();class B8{static instance;projections=new Map;static getInstance(){return this.instance??=new B8,this.instance}static createFresh(){return new B8}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 w=this.projections.get(A.entityType)??[];return w.push(A),this.projections.set(A.entityType,w),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 w=this.get(Q);if(w)A.push(w)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let w=!0;return()=>{if(!w)return;w=!1;let B=this.projections.get(A);if(!B)return;let $=B.lastIndexOf(Q);if($!==-1)B.splice($,1);if(B.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}`)}}L0();var Ex1={name:"@brains/atproto-registry",version:"0.2.0-alpha.163",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 Sx1=Z.object({enabled:Z.boolean().default(!0)}),iu0="/atproto/lexicons",uSQ=Z.strictObject({nsid:Z.string(),record:Z.record(Z.string(),Z.unknown())});function Tx1(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5732
|
+
`)},Q,{requireSaved:!0});if("success"in X&&X.success===!0)return{success:!0,data:X.data};return{success:!1,error:"error"in X?X.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:J5("operator CMS lists approved A2A contacts at any visibility")}}})).filter(($)=>$.metadata.status==="approved").map(($)=>{let f=$.metadata.name;return{id:$.id,label:typeof f==="string"&&f.length>0?f:$.id}}).sort(($,f)=>$.label.localeCompare(f.label))}}})}var Su0={name:"@brains/a2a",version:"0.2.0-alpha.164",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 JSQ={"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 uC extends jG{agentCard;taskManager=new yu0;agentService;jwksResolver=new Cu0;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",Su0,A,Hx1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,_x1(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(),w=A.identity.getProfile(),B=A.tools.listForPermissionLevel("public"),$;if(A.entityService.hasEntityType("skill"))try{let f=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(f.length>0)$=f.map((Y)=>Pm.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=Wx1({character:Q,profile:w,version:Su0.version,domain:A.domain,organization:this.config.organization,tools:B,skills:$,authEnabled:!1}),this.logger.debug("Agent Card rebuilt",{skills:this.agentCard.skills.length})}getAgentCard(){return this.agentCard}async resolveCaller(A,Q){let w=new URL(A.url),B=new URL(`${w.pathname}${w.search}`,oJ(A)),$=await Yx1({method:A.method,url:B.toString(),headers:A.headers,body:Q},this.jwksResolver);if($){let f=await v7()?.getA2APeerTrust($.domain);return{permissionLevel:f?.keyFingerprint===$.keyFingerprint?f.grantedLevel:"public",callerDomain:$.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,B]of Object.entries(JSQ))Q.set(w,B);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new yC;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),B;try{B=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let $;try{$=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let f=Gx1.safeParse($);if(!f.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(f.data.method==="message/stream"){let X=zx1.safeParse(f.data.params??{});if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${X.error.message}`},id:f.data.id}));let H=qx1(f.data.id,X.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:W}=H;return this.withCors(new Response(W,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await Dx1(f.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:B.permissionLevel,callerDomain:B.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:"/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=v7();if(!A)return;let Q=A.getIssuer();if(rJ(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let B=await A.getA2ASigningKey();await fx1(w,B.privateJwk,B.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[Lx1(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()=>{this.logger.info("A2A server stopped")}}}}wA();L0();var Nx1={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 Px1={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 jx1={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 Mx1={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 xx1={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 Ox1={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 vx1={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 Rx1={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 hx1={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 xSQ=Z.object({type:Z.string()}).catchall(Z.unknown()),OSQ=Z.object({lexicon:Z.literal(1),id:Z.string(),defs:Z.object({main:Z.object({type:Z.literal("record"),key:Z.string().min(1),record:Z.object({type:Z.literal("object"),required:Z.array(Z.string()).optional(),properties:Z.record(Z.string(),xSQ)})})})});function fU(A){return OSQ.parse(A)}var _6={"ai.rizom.brain.card":fU(Nx1),"ai.rizom.brain.deck":fU(Px1),"ai.rizom.brain.link":fU(jx1),"ai.rizom.brain.note":fU(Mx1),"ai.rizom.brain.post":fU(xx1),"ai.rizom.brain.project":fU(Ox1),"ai.rizom.brain.series":fU(vx1),"ai.rizom.brain.socialPost":fU(Rx1),"ai.rizom.brain.topic":fU(hx1)},vSQ="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function Cq(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:vSQ}}var Cx1={"ai.rizom.brain.card":Cq("@brains/atproto"),"ai.rizom.brain.deck":Cq("@brains/decks"),"ai.rizom.brain.link":Cq("@brains/link"),"ai.rizom.brain.note":Cq("@brains/note"),"ai.rizom.brain.post":Cq("@brains/blog"),"ai.rizom.brain.project":Cq("@brains/portfolio"),"ai.rizom.brain.series":Cq("@brains/series"),"ai.rizom.brain.socialPost":Cq("@brains/social-media"),"ai.rizom.brain.topic":Cq("@brains/topics")};function nI(){return Object.values(_6)}function Y90(A){if(!(A in _6))return;return _6[A]}function X90(){return Object.entries(Cx1).map(([A,Q])=>({id:A,...Q}))}L0();function Z90(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var RSQ=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function hSQ(A){let Q=Z.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine((B)=>A.knownValues?.includes(B),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine((B)=>RSQ.test(B)&&!Number.isNaN(Date.parse(B)),{message:"expected datetime"});if(A.format==="uri")w=w.refine((B)=>{try{return new URL(B),!0}catch{return!1}},{message:"expected uri"});return w}function gx1(A){switch(A.type){case"string":return hSQ(A);case"integer":return Z.number().int();case"boolean":return Z.boolean();case"array":{let Q=A.items?gx1(A.items):Z.unknown(),w=Z.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return CSQ(A);case"blob":return Z.custom(Z90,{message:"expected blob"});default:return Z.unknown()}}function yx1(A){let Q=new Set(A.required??[]),w={};for(let[B,$]of Object.entries(A.properties??{})){let f=gx1($);w[B]=Q.has(B)?f:f.optional()}return w}function CSQ(A){return Z.object(yx1(A)).passthrough()}function mu0(A,Q,w,B=[]){let $=Object.keys(A).filter((f)=>!Q.has(f));if($.length===0)return;w.addIssue({code:Z.ZodIssueCode.custom,path:B,message:`unrecognized field(s): ${$.join(", ")}`})}function gSQ(A,Q){if(mu0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),Z90(A.brain))mu0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(Z90(A.anchor))mu0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function YU(A){let Q=Z.object({...yx1(A.defs.main.record),$type:Z.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(gSQ):Q}var uu0={"ai.rizom.brain.card":YU(_6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":YU(_6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":YU(_6["ai.rizom.brain.link"]),"ai.rizom.brain.note":YU(_6["ai.rizom.brain.note"]),"ai.rizom.brain.post":YU(_6["ai.rizom.brain.post"]),"ai.rizom.brain.project":YU(_6["ai.rizom.brain.project"]),"ai.rizom.brain.series":YU(_6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":YU(_6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":YU(_6["ai.rizom.brain.topic"])};function ySQ(A,Q){let w=A;for(let B of Q){if(typeof B==="symbol")return;if(Array.isArray(w)){w=w[Number(B)];continue}if(!Z90(w))return;w=w[String(B)]}return w}function ESQ(A,Q,w){let B=w.path.join(".");if(B==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&ySQ(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${B}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${B}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${B}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${B}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${B}: ${w.message}`}function gq(A,Q){let w=YU(A).safeParse(Q);if(w.success)return;let B=w.error.issues[0];if(!B)throw w.error;throw Error(ESQ(A,Q,B))}L0();var ld="atproto:brain-card-discovered",cu0="atproto:brain-discovered",lu0="atproto:brain-card-refreshed",TSQ=Z.custom((A)=>uu0["ai.rizom.brain.card"].safeParse(A).success),pu0=Z.object({repoDid:Z.string().min(1),uri:Z.string().min(1),cid:Z.string().min(1),record:TSQ}).strict(),SSQ=Z.object({agentId:Z.string().min(1),name:Z.string().min(1),url:Z.string().url(),status:Z.enum(["discovered","approved","archived"]),repoDid:Z.string().min(1).optional(),brainDid:Z.string().min(1).optional(),anchorDid:Z.string().min(1).optional(),cardUri:Z.string().min(1).optional(),cardCid:Z.string().min(1).optional()}).strict();class B8{static instance;projections=new Map;static getInstance(){return this.instance??=new B8,this.instance}static createFresh(){return new B8}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 w=this.projections.get(A.entityType)??[];return w.push(A),this.projections.set(A.entityType,w),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 w=this.get(Q);if(w)A.push(w)}return A}listLexicons(){return this.list().map((A)=>A.lexicon)}createUnregister(A,Q){let w=!0;return()=>{if(!w)return;w=!1;let B=this.projections.get(A);if(!B)return;let $=B.lastIndexOf(Q);if($!==-1)B.splice($,1);if(B.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}`)}}L0();var Ex1={name:"@brains/atproto-registry",version:"0.2.0-alpha.164",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 Sx1=Z.object({enabled:Z.boolean().default(!0)}),iu0="/atproto/lexicons",uSQ=Z.strictObject({nsid:Z.string(),record:Z.record(Z.string(),Z.unknown())});function Tx1(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5733
5733
|
`,{headers:{"Content-Type":"application/json"}})}class du0 extends Aw{constructor(A={}){super("atproto-registry",Ex1,A,Sx1)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${iu0}/index.json`,method:"GET",public:!0,handler:()=>Tx1(this.getIndex())},...nI().map((A)=>({path:`${iu0}/${A.id}.json`,method:"GET",public:!0,handler:()=>Tx1(A)}))]}getIndex(){return{lexicons:X90().map((A)=>({...A,path:`${iu0}/${A.id}.json`}))}}getLexicon(A){return Y90(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:Z.string().describe("Canonical lexicon NSID"),record:Z.record(Z.string(),Z.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=uSQ.safeParse(A);if(!Q.success)return{success:!1,error:`Invalid input: ${Q.error.message}`};let w=this.getLexicon(Q.data.nsid);if(!w)return{success:!1,error:`Unknown AT Protocol lexicon: ${Q.data.nsid}`};try{return gq(w,Q.data.record),{success:!0,data:{valid:!0}}}catch(B){return{success:!0,data:{valid:!1,error:B instanceof Error?B.message:"Invalid record"}}}}}}createCheckContractsTool(){return{name:`${this.id}_check_contracts`,description:"Check that canonical Rizom AT Protocol lexicon contracts are available.",inputSchema:{},handler:async()=>({success:!0,data:{lexiconCount:nI().length,nsids:nI().map((A)=>A.id),metadata:X90()}})}}}function pd(A={}){return new du0(A)}wA();class nu0{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,w,B,$=!0){if(this.logger=A,this.fileOperations=B,this.deleteOnFileRemoval=$,w)this.handleImport=async(f)=>{let Y=await w({type:"directory-import",data:{paths:[f]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:f})},this.handleDelete=async(f)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:f});return}try{let{entityType:Y,id:X}=this.fileOperations.parseEntityFromPath(f),H=await w({type:"directory-delete",data:{entityId:X,entityType:Y,filePath:f}});this.logger.info("Queued delete job for removed file",{jobId:H,path:f,entityId:X,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:f,error:Y})}};else this.handleImport=async(f)=>{await Q([f])},this.handleDelete=async(f)=>{this.logger.warn("File deleted but no job queue available",{path:f})}}async handleFileChange(A,Q){this.logger.debug("Processing file change",{event:A,path:Q});try{switch(A){case"add":case"change":await this.handleImport(Q);break;case"delete":case"unlink":await this.handleDelete(Q);break;default:this.logger.debug("Unhandled file event",{event:A,path:Q})}}catch(w){this.logger.error("Failed to handle file change",{event:A,path:Q,error:w})}}}import{EventEmitter as bmQ}from"events";import{stat as VmQ,Stats as ExB}from"fs";import{readdir as JmQ,stat as ImQ}from"fs/promises";import*as Q6 from"path";import{lstat as mx1,readdir as cSQ,realpath as lSQ,stat as pSQ}from"fs/promises";import{join as iSQ,relative as dSQ,resolve as ux1,sep as nSQ}from"path";import{Readable as rSQ}from"stream";var IZ={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},ru0={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:IZ.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(ru0);var ix1="READDIRP_RECURSIVE_ERROR",oSQ=new Set(["ENOENT","EPERM","EACCES","ELOOP",ix1]),cx1=[IZ.DIR_TYPE,IZ.EVERYTHING_TYPE,IZ.FILE_DIR_TYPE,IZ.FILE_TYPE],sSQ=new Set([IZ.DIR_TYPE,IZ.EVERYTHING_TYPE,IZ.FILE_DIR_TYPE]),aSQ=new Set([IZ.EVERYTHING_TYPE,IZ.FILE_DIR_TYPE,IZ.FILE_TYPE]),tSQ=(A)=>oSQ.has(A.code),eSQ=process.platform==="win32",lx1=(A)=>!0,px1=(A)=>{if(A===void 0)return lx1;if(typeof A==="function")return A;if(typeof A==="string"){let Q=A.trim();return(w)=>w.basename===Q}if(Array.isArray(A)){let Q=A.map((w)=>w.trim());return(w)=>Q.some((B)=>w.basename===B)}return lx1};class ou0 extends rSQ{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={...ru0,...A},{root:w,type:B}=Q;this._fileFilter=px1(Q.fileFilter),this._directoryFilter=px1(Q.directoryFilter);let $=Q.lstat?mx1:pSQ;if(eSQ)this._stat=(f)=>$(f,{bigint:!0});else this._stat=$;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:ru0.depth,this._wantsDir=B?sSQ.has(B):!1,this._wantsFile=B?aSQ.has(B):!1,this._wantsEverything=B===IZ.EVERYTHING_TYPE,this._root=ux1(w),this._isDirent=!Q.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir(w,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,w=Q&&Q.files;if(w&&w.length>0){let{path:B,depth:$}=Q,f=w.splice(0,A).map((X)=>this._formatEntry(X,B)),Y=await Promise.all(f);for(let X of Y){if(!X)continue;if(this.destroyed)return;let H=await this._getEntryType(X);if(H==="directory"&&this._directoryFilter(X)){if($<=this._maxDepth)this.parents.push(this._exploreDir(X.fullPath,$+1));if(this._wantsDir)this.push(X),A--}else if((H==="file"||this._includeAsFile(X))&&this._fileFilter(X)){if(this._wantsFile)this.push(X),A--}}}else{let B=this.parents.pop();if(!B){this.push(null);break}if(this.parent=await B,this.destroyed)return}}}catch(Q){this.destroy(Q)}finally{this.reading=!1}}async _exploreDir(A,Q){let w;try{w=await cSQ(A,this._rdOptions)}catch(B){this._onError(B)}return{files:w,depth:Q,path:A}}async _formatEntry(A,Q){let w,B=this._isDirent?A.name:A;try{let $=ux1(iSQ(Q,B));w={path:dSQ(this._root,$),fullPath:$,basename:B},w[this._statsProp]=this._isDirent?A:await this._stat($)}catch($){this._onError($);return}return w}_onError(A){if(tSQ(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 w=A.fullPath;try{let B=await lSQ(w),$=await mx1(B);if($.isFile())return"file";if($.isDirectory()){let f=B.length;if(w.startsWith(B)&&w.substr(f,1)===nSQ){let Y=Error(`Circular symlink detected: "${w}" points to "${B}"`);return Y.code=ix1,this._onError(Y)}return"directory"}}catch(B){return this._onError(B),""}}}_includeAsFile(A){let Q=A&&A[this._statsProp];return Q&&this._wantsEverything&&!Q.isDirectory()}}function dx1(A,Q={}){let w=Q.entryType||Q.type;if(w==="both")w=IZ.FILE_DIR_TYPE;if(w)Q.type=w;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(w&&!cx1.includes(w))throw Error(`readdirp: Invalid type passed. Use one of ${cx1.join(", ")}`);return Q.root=A,new ou0(Q)}import{watch as AmQ,unwatchFile as nx1,watchFile as QmQ}from"fs";import{realpath as su0,lstat as wmQ,open as BmQ,stat as ox1}from"fs/promises";import{type as $mQ}from"os";import*as C$ from"path";var fmQ="data",eu0="end",sx1="close",U90=()=>{};var G90=process.platform,Ac0=G90==="win32",YmQ=G90==="darwin",XmQ=G90==="linux",ZmQ=G90==="freebsd",ax1=$mQ()==="OS400",W$={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},XU=W$,HmQ="watch",WmQ={lstat:wmQ,stat:ox1},YP="listeners",H90="errHandlers",cC="rawEmitters",KmQ=[YP,H90,cC],UmQ=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"]),GmQ=(A)=>UmQ.has(C$.extname(A).slice(1).toLowerCase()),tu0=(A,Q)=>{if(A instanceof Set)A.forEach(Q);else Q(A)},id=(A,Q,w)=>{let B=A[Q];if(!(B instanceof Set))A[Q]=B=new Set([B]);B.add(w)},DmQ=(A)=>(Q)=>{let w=A[Q];if(w instanceof Set)w.clear();else delete A[Q]},dd=(A,Q,w)=>{let B=A[Q];if(B instanceof Set)B.delete(w);else if(B===w)delete A[Q]},tx1=(A)=>A instanceof Set?A.size===0:!A,W90=new Map;function rx1(A,Q,w,B,$){let f=(Y,X)=>{if(w(A),$(Y,X,{watchedPath:A}),X&&A!==X)K90(C$.resolve(A,X),YP,C$.join(A,X))};try{return AmQ(A,{persistent:Q.persistent},f)}catch(Y){B(Y);return}}var K90=(A,Q,w,B,$)=>{let f=W90.get(A);if(!f)return;tu0(f[Q],(Y)=>{Y(w,B,$)})},zmQ=(A,Q,w,B)=>{let{listener:$,errHandler:f,rawEmitter:Y}=B,X=W90.get(Q),H;if(!w.persistent){if(H=rx1(A,w,$,f,Y),!H)return;return H.close.bind(H)}if(X)id(X,YP,$),id(X,H90,f),id(X,cC,Y);else{if(H=rx1(A,w,K90.bind(null,Q,YP),f,K90.bind(null,Q,cC)),!H)return;H.on(XU.ERROR,async(W)=>{let K=K90.bind(null,Q,H90);if(X)X.watcherUnusable=!0;if(Ac0&&W.code==="EPERM")try{await(await BmQ(A,"r")).close(),K(W)}catch(U){}else K(W)}),X={listeners:$,errHandlers:f,rawEmitters:Y,watcher:H},W90.set(Q,X)}return()=>{if(dd(X,YP,$),dd(X,H90,f),dd(X,cC,Y),tx1(X.listeners))X.watcher.close(),W90.delete(Q),KmQ.forEach(DmQ(X)),X.watcher=void 0,Object.freeze(X)}},au0=new Map,qmQ=(A,Q,w,B)=>{let{listener:$,rawEmitter:f}=B,Y=au0.get(Q),X=Y&&Y.options;if(X&&(X.persistent<w.persistent||X.interval>w.interval))nx1(Q),Y=void 0;if(Y)id(Y,YP,$),id(Y,cC,f);else Y={listeners:$,rawEmitters:f,options:w,watcher:QmQ(Q,w,(H,W)=>{tu0(Y.rawEmitters,(U)=>{U(XU.CHANGE,Q,{curr:H,prev:W})});let K=H.mtimeMs;if(H.size!==W.size||K>W.mtimeMs||K===0)tu0(Y.listeners,(U)=>U(A,H))})},au0.set(Q,Y);return()=>{if(dd(Y,YP,$),dd(Y,cC,f),tx1(Y.listeners))au0.delete(Q),nx1(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class Qc0{fsw;_boundHandleError;constructor(A){this.fsw=A,this._boundHandleError=(Q)=>A._handleError(Q)}_watchWithNodeFs(A,Q){let w=this.fsw.options,B=C$.dirname(A),$=C$.basename(A);this.fsw._getWatchedDir(B).add($);let Y=C$.resolve(A),X={persistent:w.persistent};if(!Q)Q=U90;let H;if(w.usePolling){let W=w.interval!==w.binaryInterval;X.interval=W&&GmQ($)?w.binaryInterval:w.interval,H=qmQ(A,Y,X,{listener:Q,rawEmitter:this.fsw._emitRaw})}else H=zmQ(A,Y,X,{listener:Q,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return H}_handleFile(A,Q,w){if(this.fsw.closed)return;let B=C$.dirname(A),$=C$.basename(A),f=this.fsw._getWatchedDir(B),Y=Q;if(f.has($))return;let X=async(W,K)=>{if(!this.fsw._throttle(HmQ,A,5))return;if(!K||K.mtimeMs===0)try{let U=await ox1(A);if(this.fsw.closed)return;let{atimeMs:G,mtimeMs:q}=U;if(!G||G<=q||q!==Y.mtimeMs)this.fsw._emit(XU.CHANGE,A,U);if((YmQ||XmQ||ZmQ)&&Y.ino!==U.ino){this.fsw._closeFile(W),Y=U;let b=this._watchWithNodeFs(A,X);if(b)this.fsw._addPathCloser(W,b)}else Y=U}catch(U){this.fsw._remove(B,$)}else if(f.has($)){let{atimeMs:U,mtimeMs:G}=K;if(!U||U<=G||G!==Y.mtimeMs)this.fsw._emit(XU.CHANGE,A,K);Y=K}},H=this._watchWithNodeFs(A,X);if(!(w&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(XU.ADD,A,0))return;this.fsw._emit(XU.ADD,A,Q)}return H}async _handleSymlink(A,Q,w,B){if(this.fsw.closed)return;let $=A.fullPath,f=this.fsw._getWatchedDir(Q);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let Y;try{Y=await su0(w)}catch(X){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(f.has(B)){if(this.fsw._symlinkPaths.get($)!==Y)this.fsw._symlinkPaths.set($,Y),this.fsw._emit(XU.CHANGE,w,A.stats)}else f.add(B),this.fsw._symlinkPaths.set($,Y),this.fsw._emit(XU.ADD,w,A.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has($))return!0;this.fsw._symlinkPaths.set($,!0)}_handleRead(A,Q,w,B,$,f,Y){A=C$.join(A,"");let X=B?`${A}:${B}`:A;if(Y=this.fsw._throttle("readdir",X,1000),!Y)return;let H=this.fsw._getWatchedDir(w.path),W=new Set,K=this.fsw._readdirp(A,{fileFilter:(U)=>w.filterPath(U),directoryFilter:(U)=>w.filterDir(U)});if(!K)return;return K.on(fmQ,async(U)=>{if(this.fsw.closed){K=void 0;return}let G=U.path,q=C$.join(A,G);if(W.add(G),U.stats.isSymbolicLink()&&await this._handleSymlink(U,A,q,G))return;if(this.fsw.closed){K=void 0;return}if(G===B||!B&&!H.has(G))this.fsw._incrReadyCount(),q=C$.join($,C$.relative($,q)),this._addToNodeFs(q,Q,w,f+1)}).on(XU.ERROR,this._boundHandleError),new Promise((U,G)=>{if(!K)return G();K.once(eu0,()=>{if(this.fsw.closed){K=void 0;return}let q=Y?Y.clear():!1;if(U(void 0),H.getChildren().filter((b)=>{return b!==A&&!W.has(b)}).forEach((b)=>{this.fsw._remove(A,b)}),K=void 0,q)this._handleRead(A,!1,w,B,$,f,Y)})})}async _handleDir(A,Q,w,B,$,f,Y){let X=this.fsw._getWatchedDir(C$.dirname(A)),H=X.has(C$.basename(A));if(!(w&&this.fsw.options.ignoreInitial)&&!$&&!H)this.fsw._emit(XU.ADD_DIR,A,Q);X.add(C$.basename(A)),this.fsw._getWatchedDir(A);let W,K,U=this.fsw.options.depth;if((U==null||B<=U)&&!this.fsw._symlinkPaths.has(Y)){if(!$){if(await this._handleRead(A,w,f,$,A,B,W),this.fsw.closed)return}K=this._watchWithNodeFs(A,(G,q)=>{if(q&&q.mtimeMs===0)return;this._handleRead(G,!1,f,$,A,B,W)})}return K}async _addToNodeFs(A,Q,w,B,$){let f=this.fsw._emitReady;if(this.fsw._isIgnored(A)||this.fsw.closed)return f(),!1;let Y=this.fsw._getWatchHelpers(A);if(w)Y.filterPath=(X)=>w.filterPath(X),Y.filterDir=(X)=>w.filterDir(X);try{let X=await WmQ[Y.statMethod](Y.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(Y.watchPath,X))return f(),!1;let H=this.fsw.options.followSymlinks,W;if(X.isDirectory()){let K=C$.resolve(A),U=H?await su0(A):A;if(this.fsw.closed)return;if(W=await this._handleDir(Y.watchPath,X,Q,B,$,Y,U),this.fsw.closed)return;if(K!==U&&U!==void 0)this.fsw._symlinkPaths.set(K,U)}else if(X.isSymbolicLink()){let K=H?await su0(A):A;if(this.fsw.closed)return;let U=C$.dirname(Y.watchPath);if(this.fsw._getWatchedDir(U).add(Y.watchPath),this.fsw._emit(XU.ADD,Y.watchPath,X),W=await this._handleDir(U,X,Q,B,A,Y,K),this.fsw.closed)return;if(K!==void 0)this.fsw._symlinkPaths.set(C$.resolve(A),K)}else W=this._handleFile(Y.watchPath,X,Q);if(f(),W)this.fsw._addPathCloser(A,W);return!1}catch(X){if(this.fsw._handleError(X))return f(),A}}}/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */var wc0="/",FmQ="//",BO1=".",kmQ="..",LmQ="string",_mQ=/\\/g,$O1=/\/\//g,NmQ=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,PmQ=/^\.[/\\]/;function D90(A){return Array.isArray(A)?A:[A]}var Bc0=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function jmQ(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 w=Q6.relative(A.path,Q);if(!w)return!1;return!w.startsWith("..")&&!Q6.isAbsolute(w)}return!1};return()=>!1}function MmQ(A){if(typeof A!=="string")throw Error("string expected");A=Q6.normalize(A),A=A.replace(/\\/g,"/");let Q=!1;if(A.startsWith("//"))Q=!0;if(A=A.replace($O1,"/"),Q)A="/"+A;return A}function ex1(A,Q,w){let B=MmQ(Q);for(let $=0;$<A.length;$++){let f=A[$];if(f(B,w))return!0}return!1}function xmQ(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let B=D90(A).map(($)=>jmQ($));if(Q==null)return($,f)=>{return ex1(B,$,f)};return ex1(B,Q)}var AO1=(A)=>{let Q=D90(A).flat();if(!Q.every((w)=>typeof w===LmQ))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(fO1)},QO1=(A)=>{let Q=A.replace(_mQ,wc0),w=!1;if(Q.startsWith(FmQ))w=!0;if(Q=Q.replace($O1,wc0),w)Q=wc0+Q;return Q},fO1=(A)=>QO1(Q6.normalize(QO1(A))),wO1=(A="")=>(Q)=>{if(typeof Q==="string")return fO1(Q6.isAbsolute(Q)?Q:Q6.join(A,Q));else return Q},OmQ=(A,Q)=>{if(Q6.isAbsolute(A))return A;return Q6.join(Q,A)},vmQ=Object.freeze(new Set);class YO1{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!==BO1&&A!==kmQ)Q.add(A)}async remove(A){let{items:Q}=this;if(!Q)return;if(Q.delete(A),Q.size>0)return;let w=this.path;try{await JmQ(w)}catch(B){if(this._removeWatcher)this._removeWatcher(Q6.dirname(w),Q6.basename(w))}}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=U90,this.items=vmQ,Object.freeze(this)}}var RmQ="stat",hmQ="lstat";class XO1{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,w){this.fsw=w;let B=A;this.path=A=A.replace(PmQ,""),this.watchPath=B,this.fullWatchPath=Q6.resolve(B),this.dirParts=[],this.dirParts.forEach(($)=>{if($.length>1)$.pop()}),this.followSymlinks=Q,this.statMethod=Q?RmQ:hmQ}entryPath(A){return Q6.join(this.watchPath,Q6.relative(this.watchPath,A.fullPath))}filterPath(A){let{stats:Q}=A;if(Q&&Q.isSymbolicLink())return this.filterDir(A);let w=this.entryPath(A);return this.fsw._isntIgnored(w,Q)&&this.fsw._hasReadPermissions(Q)}filterDir(A){return this.fsw._isntIgnored(this.entryPath(A),A.stats)}}class $c0 extends bmQ{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,w={stabilityThreshold:2000,pollInterval:100},B={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...A,ignored:A.ignored?D90(A.ignored):D90([]),awaitWriteFinish:Q===!0?w:typeof Q==="object"?{...w,...Q}:!1};if(ax1)B.usePolling=!0;if(B.atomic===void 0)B.atomic=!B.usePolling;let $=process.env.CHOKIDAR_USEPOLLING;if($!==void 0){let X=$.toLowerCase();if(X==="false"||X==="0")B.usePolling=!1;else if(X==="true"||X==="1")B.usePolling=!0;else B.usePolling=!!X}let f=process.env.CHOKIDAR_INTERVAL;if(f)B.interval=Number.parseInt(f,10);let Y=0;this._emitReady=()=>{if(Y++,Y>=this._readyCount)this._emitReady=U90,this._readyEmitted=!0,process.nextTick(()=>this.emit(W$.READY))},this._emitRaw=(...X)=>this.emit(W$.RAW,...X),this._boundRemove=this._remove.bind(this),this.options=B,this._nodeFsHandler=new Qc0(this),Object.freeze(B)}_addIgnoredPath(A){if(Bc0(A)){for(let Q of this._ignoredPaths)if(Bc0(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(Bc0(Q)&&Q.path===A)this._ignoredPaths.delete(Q)}}add(A,Q,w){let{cwd:B}=this.options;this.closed=!1,this._closePromise=void 0;let $=AO1(A);if(B)$=$.map((f)=>{return OmQ(f,B)});if($.forEach((f)=>{this._removeIgnoredPath(f)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=$.length,Promise.all($.map(async(f)=>{let Y=await this._nodeFsHandler._addToNodeFs(f,!w,void 0,0,Q);if(Y)this._emitReady();return Y})).then((f)=>{if(this.closed)return;f.forEach((Y)=>{if(Y)this.add(Q6.dirname(Y),Q6.basename(Q||Y))})}),this}unwatch(A){if(this.closed)return this;let Q=AO1(A),{cwd:w}=this.options;return Q.forEach((B)=>{if(!Q6.isAbsolute(B)&&!this._closers.has(B)){if(w)B=Q6.join(w,B);B=Q6.resolve(B)}if(this._closePath(B),this._addIgnoredPath(B),this._watched.has(B))this._addIgnoredPath({path:B,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((w)=>{let B=w();if(B instanceof Promise)A.push(B)})),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,w)=>{let $=(this.options.cwd?Q6.relative(this.options.cwd,w):w)||BO1;A[$]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==W$.ERROR)this.emit(W$.ALL,A,...Q)}async _emit(A,Q,w){if(this.closed)return;let B=this.options;if(Ac0)Q=Q6.normalize(Q);if(B.cwd)Q=Q6.relative(B.cwd,Q);let $=[Q];if(w!=null)$.push(w);let f=B.awaitWriteFinish,Y;if(f&&(Y=this._pendingWrites.get(Q)))return Y.lastChange=new Date,this;if(B.atomic){if(A===W$.UNLINK)return this._pendingUnlinks.set(Q,[A,...$]),setTimeout(()=>{this._pendingUnlinks.forEach((X,H)=>{this.emit(...X),this.emit(W$.ALL,...X),this._pendingUnlinks.delete(H)})},typeof B.atomic==="number"?B.atomic:100),this;if(A===W$.ADD&&this._pendingUnlinks.has(Q))A=W$.CHANGE,this._pendingUnlinks.delete(Q)}if(f&&(A===W$.ADD||A===W$.CHANGE)&&this._readyEmitted){let X=(H,W)=>{if(H)A=W$.ERROR,$[0]=H,this.emitWithAll(A,$);else if(W){if($.length>1)$[1]=W;else $.push(W);this.emitWithAll(A,$)}};return this._awaitWriteFinish(Q,f.stabilityThreshold,A,X),this}if(A===W$.CHANGE){if(!this._throttle(W$.CHANGE,Q,50))return this}if(B.alwaysStat&&w===void 0&&(A===W$.ADD||A===W$.ADD_DIR||A===W$.CHANGE)){let X=B.cwd?Q6.join(B.cwd,Q):Q,H;try{H=await ImQ(X)}catch(W){}if(!H||this.closed)return;$.push(H)}return this.emitWithAll(A,$),this}_handleError(A){let Q=A&&A.code;if(A&&Q!=="ENOENT"&&Q!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||Q!=="EPERM"&&Q!=="EACCES"))this.emit(W$.ERROR,A);return A||this.closed}_throttle(A,Q,w){if(!this._throttled.has(A))this._throttled.set(A,new Map);let B=this._throttled.get(A);if(!B)throw Error("invalid throttle");let $=B.get(Q);if($)return $.count++,!1;let f,Y=()=>{let H=B.get(Q),W=H?H.count:0;if(B.delete(Q),clearTimeout(f),H)clearTimeout(H.timeoutObject);return W};f=setTimeout(Y,w);let X={timeoutObject:f,clear:Y,count:0};return B.set(Q,X),X}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(A,Q,w,B){let $=this.options.awaitWriteFinish;if(typeof $!=="object")return;let f=$.pollInterval,Y,X=A;if(this.options.cwd&&!Q6.isAbsolute(A))X=Q6.join(this.options.cwd,A);let H=new Date,W=this._pendingWrites;function K(U){VmQ(X,(G,q)=>{if(G||!W.has(A)){if(G&&G.code!=="ENOENT")B(G);return}let b=Number(new Date);if(U&&q.size!==U.size)W.get(A).lastChange=b;let J=W.get(A);if(b-J.lastChange>=Q)W.delete(A),B(void 0,q);else Y=setTimeout(K,f,q)})}if(!W.has(A))W.set(A,{lastChange:H,cancelWait:()=>{return W.delete(A),clearTimeout(Y),w}}),Y=setTimeout(K,f)}_isIgnored(A,Q){if(this.options.atomic&&NmQ.test(A))return!0;if(!this._userIgnored){let{cwd:w}=this.options,$=(this.options.ignored||[]).map(wO1(w)),Y=[...[...this._ignoredPaths].map(wO1(w)),...$];this._userIgnored=xmQ(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new XO1(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=Q6.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new YO1(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,w){let B=Q6.join(A,Q),$=Q6.resolve(B);if(w=w!=null?w:this._watched.has(B)||this._watched.has($),!this._throttle("remove",B,100))return;if(!w&&this._watched.size===1)this.add(A,Q,!0);this._getWatchedDir(B).getChildren().forEach((U)=>this._remove(B,U));let X=this._getWatchedDir(A),H=X.has(Q);if(X.remove(Q),this._symlinkPaths.has($))this._symlinkPaths.delete($);let W=B;if(this.options.cwd)W=Q6.relative(this.options.cwd,B);if(this.options.awaitWriteFinish&&this._pendingWrites.has(W)){if(this._pendingWrites.get(W).cancelWait()===W$.ADD)return}this._watched.delete(B),this._watched.delete($);let K=w?W$.UNLINK_DIR:W$.UNLINK;if(H&&!this._isIgnored(B))this._emit(K,B);this._closePath(B)}_closePath(A){this._closeFile(A);let Q=Q6.dirname(A);this._getWatchedDir(Q).remove(Q6.basename(A))}_closeFile(A){let Q=this._closers.get(A);if(!Q)return;Q.forEach((w)=>w()),this._closers.delete(A)}_addPathCloser(A,Q){if(!Q)return;let w=this._closers.get(A);if(!w)w=[],this._closers.set(A,w);w.push(Q)}_readdirp(A,Q){if(this.closed)return;let w={type:W$.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},B=dx1(A,w);return this._streams.add(B),B.once(sx1,()=>{B=void 0}),B.once(eu0,()=>{if(B)this._streams.delete(B),B=void 0}),B}}function CmQ(A,Q={}){let w=new $c0(Q);return w.add(A),w}var ZO1={watch:CmQ,FSWatcher:$c0};import{extname as gmQ}from"path";var z90=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function XP(A){let Q=gmQ(A).toLowerCase();return z90.includes(Q)}function HO1(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 fc0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as ymQ,relative as EmQ,sep as WO1,join as TmQ}from"path";function bW(A,Q){return ymQ(Q)?Q:TmQ(A,Q)}function lC(A,Q){let w=bW(A,Q),B=EmQ(A,w);return WO1==="/"?B:B.split(WO1).join("/")}function SmQ(A,Q){if(!lC(Q,A).startsWith("image/"))return!1;return XP(A)}function mmQ(A,Q){if(lC(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return SmQ(A,Q)}class Yc0{watcher;watchCallback;pendingChanges=new Map;batchTimeout;syncPath;watchInterval;logger;onFileChange;constructor(A){this.syncPath=A.syncPath,this.watchInterval=A.watchInterval,this.logger=A.logger,this.onFileChange=A.onFileChange}async start(){if(this.watcher){this.logger.debug("Already watching directory");return}if(this.logger.debug("Starting directory watch",{path:this.syncPath,interval:this.watchInterval}),this.watcher=ZO1.watch(this.syncPath,{ignored:/(^|[/\\])\../,persistent:!0,interval:this.watchInterval,awaitWriteFinish:{stabilityThreshold:2000,pollInterval:100}}),this.watcher.on("add",(A)=>void this.handleFileChange("add",A)).on("change",(A)=>void this.handleFileChange("change",A)).on("unlink",(A)=>void this.handleFileChange("delete",A)).on("error",(A)=>this.logger.error("Watcher error",A)),this.watchCallback)this.watcher.on("all",this.watchCallback)}stop(){if(this.watcher)this.watcher.close(),this.watcher=void 0,this.logger.info("Stopped directory watch");if(this.batchTimeout)clearTimeout(this.batchTimeout),this.batchTimeout=void 0}setCallback(A){if(this.watchCallback=A,this.watcher)this.watcher.on("all",A)}async handleFileChange(A,Q){if(!mmQ(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=lC(this.syncPath,Q);if(this.pendingChanges.set(w,A),this.batchTimeout)clearTimeout(this.batchTimeout);this.batchTimeout=setTimeout(()=>{this.processPendingChanges()},500)}async processPendingChanges(){if(this.pendingChanges.size===0)return;let A=new Map(this.pendingChanges);this.pendingChanges.clear(),this.batchTimeout=void 0,this.logger.debug("Processing batched file changes",{changeCount:A.size});for(let[Q,w]of A){let B=bW(this.syncPath,Q);try{if(this.onFileChange)await this.onFileChange(w,B)}catch($){this.logger.error("Error processing file change",{path:Q,event:w,error:$})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}async function KO1(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return umQ(Q)}function UO1(A){if(A)A.stop();return}function GO1(A,Q){if(A)A.setCallback(Q)}async function umQ(A){let{logger:Q,syncPath:w,watchInterval:B,importEntities:$,jobQueueCallback:f,fileOperations:Y,deleteOnFileRemoval:X}=A,H=new nu0(Q,$,f,Y,X),W=new Yc0({syncPath:w,watchInterval:B,logger:Q,onFileChange:async(K,U)=>{await H.handleFileChange(K,U)}});return await W.start(),W}async function DO1(A){let Q=Date.now();A.logger.debug("Starting sync (import only)");let w=await A.importEntities(),B=await A.removeOrphanedEntities(),$=Date.now()-Q;return A.markSynced(new Date),A.logger.debug("Sync completed",{duration:$,imported:w.imported,orphansDeleted:B.deleted}),{export:{exported:0,failed:0,errors:[]},import:w,duration:$}}wA();class Xc0{logger;syncPath;deleteOnFileRemoval;constructor(A){this.logger=A.logger,this.syncPath=A.syncPath,this.deleteOnFileRemoval=A.deleteOnFileRemoval}prepareBatchOperations(A){let Q=[],w=this.createImportOperations(A);Q.push(...w);let B=w.length;if(this.deleteOnFileRemoval)Q.push({type:"directory-cleanup",data:{}});let $=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:B,totalFiles:$}),{operations:Q,exportOperationsCount:0,importOperationsCount:B,totalFiles:$}}async queueSyncBatch(A,Q,w,B){let $=this.prepareBatchOperations(w);if($.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch($.operations,{source:Q,rootJobId:B?.rootJobId??U4(),metadata:{progressToken:B?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:B?.pluginId??"directory-sync",interfaceType:B?.interfaceType,channelId:B?.channelId}}),operationCount:$.operations.length,exportOperationsCount:$.exportOperationsCount,importOperationsCount:$.importOperationsCount,totalFiles:$.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,w=[];for(let B=0;B<A.length;B+=Q){let $=A.slice(B,B+Q);w.push({type:"directory-import",data:{batchIndex:Math.floor(B/Q),paths:$,batchSize:$.length}})}return w}}class Zc0{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new Xc0({logger:A.logger,syncPath:A.syncPath,deleteOnFileRemoval:A.deleteOnFileRemoval})}async queueSyncBatch(A,Q,w){if(this.syncInProgress)return this.logger.debug("Sync already in progress, skipping",{source:Q}),null;this.syncInProgress=!0;try{let B=await this.fileOperations.getAllSyncFiles();return await this.batchOperationsManager.queueSyncBatch(A,Q,B,w)}finally{this.syncInProgress=!1}}}class Hc0{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 nmQ,dirname as rmQ,extname as omQ}from"path";import{extname as cmQ}from"path";var q90=[".pdf"],zO1=".meta.json";function ZP(A){let Q=cmQ(A).toLowerCase();return q90.includes(Q)}function qO1(A){return A.toLowerCase().endsWith(zO1)}function Wc0(A){return`${A}${zO1}`}function bO1(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as lmQ,join as b90}from"path";function V90(A,Q){let B=lC(A,Q).split("/"),$,f;if(B.length===1)$="note",f=B;else if(B.length>1&&B[0])$=B[0],f=B.slice(1);else $="note",f=B;let Y;if(f.length>1){let X=f[f.length-1];if(X)f[f.length-1]=VO1(X);Y=f.join(":")}else Y=VO1(f[0]??"");return{entityType:$,id:Y}}function JO1(A,Q,w,B=".md"){let $=Q.split(":").filter((W)=>W.length>0),f=w==="note";if($.length===1)return f?b90(A,`${$[0]}${B}`):b90(A,w,`${$[0]}${B}`);let Y=$;if($[0]===w)Y=$.slice(1);let X=Y[Y.length-1],H=Y.slice(0,-1);if(f)return b90(A,...H,`${X}${B}`);return b90(A,w,...H,`${X}${B}`)}function IO1(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return fc0(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?fc0(w[1]):".md"}function VO1(A){let Q=lmQ(A).toLowerCase();return Q===".md"||z90.includes(Q)||q90.includes(Q)?A.slice(0,-Q.length):A}L0();yX();import{mkdir as smQ,readFile as pC,writeFile as Uc0,stat as amQ,utimes as tmQ}from"fs/promises";import{join as J90}from"path";import{mkdir as FO1,readdir as imQ,stat as dmQ}from"fs/promises";import{access as pmQ}from"fs/promises";async function o8(A){try{return await pmQ(A),!0}catch{return!1}}async function Kc0(A,Q){return NO1(A,Q,{includeDocuments:!1,includeImages:!1})}async function kO1(A,Q){return NO1(A,Q,{includeDocuments:!0,includeImages:!0})}async function LO1(A,Q){if(!await o8(A))await FO1(A,{recursive:!0});for(let w of Q)if(w!=="note")await FO1(J90(A,w),{recursive:!0})}async function _O1(A,Q){let w=[],B={totalFiles:0,byEntityType:{}};if(!await o8(A))return{files:w,stats:B};let $=await Kc0(A,Q);for(let f of $)try{let Y=J90(A,f),X=await dmQ(Y),{entityType:H}=V90(A,f);w.push({path:f,entityType:H,modified:X.mtime}),B.totalFiles++,B.byEntityType[H]=(B.byEntityType[H]??0)+1}catch{continue}return{files:w,stats:B}}async function NO1(A,Q,w){let B=[];if(!await o8(A))return B;let $=async(f,Y="",X=!1,H=!1)=>{let W=await imQ(f,{withFileTypes:!0});for(let K of W){let U=Y?J90(Y,K.name):K.name;if(K.isFile()&&!K.name.endsWith(".invalid")&&!qO1(K.name)){if(K.name.endsWith(".md"))B.push(U);else if(w.includeImages&&X&&XP(K.name))B.push(U);else if(w.includeDocuments&&H&&ZP(K.name))B.push(U)}else if(K.isDirectory()&&!K.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(K.name))continue;let G=J90(f,K.name),q=K.name==="image"&&Y==="",b=K.name==="document"&&Y==="";await $(G,U,X||q,H||b)}}};return await $(A),B}var emQ=Z.record(Z.string(),Z.unknown());class Gc0{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return V90(this.syncPath,A)}async readEntity(A){let Q=bW(this.syncPath,A),w=await amQ(Q),{entityType:B,id:$}=this.parseEntityFromPath(A),f=w.birthtime.getTime()>0?w.birthtime:w.mtime,Y=w.mtime,X,H;if(XP(A)||ZP(A)){let U=(await pC(Q)).toString("base64"),G=omQ(A);if(X=`data:${ZP(A)?bO1(G):HO1(G)};base64,${U}`,ZP(A))H=await this.readDocumentSidecar(Q,A)}else X=await pC(Q,"utf-8");let W={entityType:B,id:$,content:X,created:f,updated:Y};if(H)W.metadata=H;return W}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:nmQ(Q)},B=Wc0(A);if(!await o8(B))return w;try{let $=await pC(B,"utf-8"),f=emQ.safeParse(JSON.parse($));return{...w,...f.success?f.data:{}}}catch{return w}}async writeEntity(A){let Q=this.getEntityFilePath(A),w=A.entityType==="image",B=A.entityType==="document";if(w||B){let f=w?/^data:image\/[a-z+]+;base64,(.+)$/i:/^data:application\/pdf;base64,(.+)$/i,Y=A.content.match(f),X=Y?.[1]?Buffer.from(Y[1],"base64"):Buffer.from(A.content,"base64"),H=!1;if(await o8(Q)){let W=await pC(Q),K=f6(W.toString("base64")),U=f6(X.toString("base64"));if(K===U)H=!0}if(!H)await this.ensureEntityDirectory(A,Q),await Uc0(Q,X);if(B)await this.writeDocumentSidecar(A,Q);if(H)return}else{let f=this.entityService.serializeEntity(A);if(await o8(Q)){let Y=await pC(Q,"utf-8"),X=f6(Y),H=f6(f);if(X===H)return}await this.ensureEntityDirectory(A,Q),await Uc0(Q,f,"utf-8")}let $=new Date(A.updated);await tmQ(Q,$,$)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await smQ(rmQ(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let w=A.metadata,B={};for(let[Y,X]of Object.entries(w)){if(Y==="mimeType")continue;if(X===void 0)continue;B[Y]=X}let $=Wc0(Q),f=`${JSON.stringify(B,null,2)}
|
|
5734
5734
|
`;if(await o8($)){if(await pC($,"utf-8")===f)return}await this.ensureEntityDirectory(A,$),await Uc0($,f,"utf-8")}getFilePath(A,Q,w=".md"){return JO1(this.syncPath,A,Q,w)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,IO1(A))}async getAllMarkdownFiles(){return Kc0(this.syncPath,this.entityService)}async getAllSyncFiles(){return kO1(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await LO1(this.syncPath,A)}shouldUpdateEntity(A,Q){let w=f6(Q.content);return A.contentHash!==w}async gatherFileStatus(){return _O1(this.syncPath,this.entityService)}async syncDirectoryExists(){return o8(this.syncPath)}async fileExists(A){return o8(A)}}_4();L0();l9();D2();_4();async function I90(A,Q,w,B){let{sourceUrl:$}=A,f=await Q.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}});if(f[0])return B.debug("Reusing existing image entity",{sourceUrl:$,imageId:f[0].id}),f[0].id;let Y=await w($),{base64:X}=AJ(Y),H=aL(X),W=QJ(X);if(!H||!W)throw Error("Could not detect image format or dimensions");let K=await Q.createEntity({entity:{id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:H,width:W.width,height:W.height,sourceUrl:$}}});return B.debug("Created image entity from URL",{sourceUrl:$,imageId:K.entityId}),K.entityId}var PO1=Z.object({title:Z.string(),slug:Z.string().optional(),coverImageUrl:Z.url(),coverImageId:Z.string().optional(),coverImageAlt:Z.string().optional()});class Dc0{entityService;fetcher;logger;constructor(A,Q,w=pH){this.entityService=A,this.fetcher=w,this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=M6(A)}catch{return null}let{frontmatter:w}=Q,B=PO1.safeParse(w);if(!B.success)return null;if(B.data.coverImageId)return null;let{title:$,slug:f,coverImageUrl:Y,coverImageAlt:X}=B.data;if(!sL(Y))return null;return{sourceUrl:Y,postTitle:$,postSlug:f??H1($),customAlt:X}}async convert(A){let Q;try{Q=M6(A)}catch(W){return this.logger.debug("Parse failed",{error:W}),{content:A,converted:!1}}let{frontmatter:w}=Q,B=PO1.safeParse(w);if(!B.success)return{content:A,converted:!1};if(B.data.coverImageId)return{content:A,converted:!1};let{title:$,slug:f,coverImageUrl:Y,coverImageAlt:X}=B.data;if(!sL(Y))return{content:A,converted:!1};let H={postTitle:$,postSlug:f??H1($),sourceUrl:Y,customAlt:X};try{let W=await this.createImageEntity(H),K={...w};return delete K.coverImageUrl,delete K.coverImageAlt,K.coverImageId=W,{content:IL(K,Q.content),converted:!0,imageId:W}}catch(W){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:SA(W)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:w,sourceUrl:B,customAlt:$}=A,f=`Cover image for ${Q}`;return I90({id:`${w}-cover`,title:f,alt:$??f,sourceUrl:B},this.entityService,this.fetcher,this.logger)}}_4();class nd{entityService;fetcher;logger;constructor(A,Q,w=pH){this.entityService=A,this.fetcher=w,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let w=[],B=_N0(A);for(let $ of B){if(!sL($.url))continue;if($.url.startsWith("entity://"))continue;let f=this.reconstructMarkdown($);w.push({sourceUrl:$.url,alt:$.alt,originalMarkdown:f,postSlug:Q})}return w}reconstructMarkdown(A){if(A.title)return``;return``}async convert(A,Q){let w=this.detectInlineImages(A,Q);if(w.length===0)return{content:A,converted:!1,convertedCount:0};let B=A,$=0,f=0;for(let Y of w)try{let X=await this.createImageEntity(Y,f++),H=``;B=B.replace(Y.originalMarkdown,H),$++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:X})}catch(X){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:SA(X)})}return{content:B,converted:$>0,convertedCount:$}}async createImageEntity(A,Q){let{sourceUrl:w,alt:B,postSlug:$}=A;return I90({id:`${$}-inline-${Q}`,title:B||`Inline image ${Q+1} for ${$}`,alt:B||"",sourceUrl:w},this.entityService,this.fetcher,this.logger)}}class zc0{logger;entityService;fileOperations;constructor(A,Q,w){this.logger=A,this.entityService=Q,this.fileOperations=w}async importEntitiesWithProgress(A,Q,w,B){this.logger.debug("Importing entities with progress reporting");let $={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},f=A??await this.fileOperations.getAllSyncFiles(),Y=f.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let X=0;X<Y;X+=w){let H=f.slice(X,X+w),W=await B(H);$.imported+=W.imported,$.skipped+=W.skipped,$.failed+=W.failed,$.quarantined+=W.quarantined,$.errors.push(...W.errors),$.quarantinedFiles.push(...W.quarantinedFiles),$.jobIds.push(...W.jobIds);let K=Math.min(X+w,Y),U=Math.round(K/Y*40);await Q.report({progress:U,message:`Imported ${K}/${Y} files`})}return $}async exportEntitiesWithProgress(A,Q,w,B){this.logger.debug("Exporting entities with progress reporting");let $=A??this.entityService.getEntityTypes();await Q.report({progress:50,message:`Starting export of ${$.length} entity types`});let f=await B(A);return await Q.report({progress:100,message:`Exported ${f.exported} entities`}),this.logger.debug("Export completed",f),f}}wA();import{rename as AuQ,appendFile as QuQ,readFile as wuQ,writeFile as BuQ,access as $uQ}from"fs/promises";import{join as jO1}from"path";class qc0{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return kA0(A)}async quarantineInvalidFile(A,Q,w,B){let $=B(A),f=`${$}.invalid`;try{await AuQ($,f),w.quarantined++,w.quarantinedFiles.push(A);let Y=jO1(this.syncPath,".import-errors.log"),X=new Date().toISOString(),H=SA(Q),W=`${X} - ${A}: ${H}
|
|
5735
5735
|
\u2192 ${A}.invalid
|
|
@@ -5758,7 +5758,7 @@ ${dM1}</style></head><body>${md(A)}<main id="root" data-web-chat-root>Brain Chat
|
|
|
5758
5758
|
*...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
|
|
5759
5759
|
## Getting Started
|
|
5760
5760
|
`),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(`
|
|
5761
|
-
`)}}wA();class i90 extends ew{directorySync;constructor(A,Q,w){super(A,{schema:Vl0,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory export job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}wA();class d90 extends ew{directorySync;constructor(A,Q,w){super(A,{schema:bl0,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,quarantined:$.quarantined,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory import job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}wA();class n90 extends ew{directorySync;context;constructor(A,Q,w){super(A,{schema:zl0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let B=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let f={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),f=await this.importWithProgress(A.paths,w),$==="import")await this.waitForImportJobs(f.jobIds,w),await w.report({progress:100,message:`Import complete: ${f.imported} imported`});else await w.report({progress:50,message:`Imported ${f.imported} entities`}),await this.waitForImportJobs(f.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let H=$==="export"?10:60;await w.report({progress:H,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${f.imported} imported, ${Y.exported} exported`})}let X=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:f.imported,exported:Y.exported}),{import:f,export:Y,duration:X}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:w}=this.context,B=300000,$=500,f=Date.now(),Y=async()=>{let H=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(H===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${H}/${A.length} completed)`);return}let W=Math.round(H/A.length*100);return await Q.report({progress:50+Math.round(W*0.05),message:`Processing ${H}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}wA();class r90 extends ew{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:ql0,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=B}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let B=await this.gitSync.withLock(async()=>{return await this.gitSync.pull(),await w.report({progress:35,message:"Scanning pulled content for sync changes"}),this.directorySync.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!B)return await w.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await w.report({progress:100,message:`Sync queued: ${B.importOperationsCount} import jobs for ${B.totalFiles} files`}),kiQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function kiQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}wA();class o90 extends ew{context;constructor(A,Q,w){super(A,{schema:l90,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=l90.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}),await w.report({progress:0,total:1,message:`Deleting ${B.entityType}:${B.entityId}`});try{let $=await this.context.entityService.deleteEntity({entityType:B.entityType,id:B.entityId});if($)this.logger.info("Successfully deleted entity for removed file",{entityId:B.entityId,entityType:B.entityType});else this.logger.warn("Entity not found in database",{entityId:B.entityId,entityType:B.entityType});return await w.report({progress:1,total:1,message:`Deleted ${B.entityType}:${B.entityId}`}),{deleted:$,entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:B.entityId,entityType:B.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}wA();L0();var LiQ=Z.object({});class s90 extends ew{directorySync;constructor(A,Q){super(A,{schema:LiQ,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let B=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${B.deleted} orphans removed`}),B}}wA();_4();l9();T6();L0();_4();import{readFile as _iQ,writeFile as NiQ}from"fs/promises";var PiQ=Jl0,jiQ=Z.record(Z.string(),Z.unknown());class a90 extends ew{context;fetcher;constructor(A,Q,w=pH){super(Q,{schema:PiQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:Y});try{await this.reportProgress(w,{progress:oQ.INIT,message:`Reading file: ${B}`});let H;try{H=await _iQ(B,"utf-8")}catch(V){return this.logger.error("Failed to read file",{filePath:B,error:SA(V)}),f$.failure(V)}let W;try{W=M6(H)}catch(V){return this.logger.warn("Failed to parse markdown",{filePath:B,error:SA(V)}),f$.failure(V)}let K=jiQ.safeParse(W.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:oQ.FETCH,message:"Checking for existing image"});let G=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),q;if(G[0])q=G[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:q}),await this.reportProgress(w,{progress:oQ.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:oQ.PROCESS,message:`Fetching image from ${$}`});let V;try{V=await this.fetcher($)}catch(h){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:SA(h)}),f$.failure(h)}await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let{base64:k}=AJ(V),N=aL(k),L=QJ(k);if(!N||!L)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),f$.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let O=`Cover image for ${f}`,v=X??O;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:V,metadata:{title:O,alt:v,format:N,width:L.width,height:L.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:$}),await this.reportProgress(w,{progress:oQ.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:oQ.SAVE,message:"Updating file"});let b={...U};delete b.coverImageUrl,delete b.coverImageAlt,b.coverImageId=q;let J=IL(b,W.content);try{await NiQ(B,J,"utf-8")}catch(V){return this.logger.error("Failed to write file",{filePath:B,error:SA(V)}),f$.failure(V)}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:q,sourceUrl:$}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:SA(H)}),f$.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}wA();_4();T6();import{readFile as MiQ,writeFile as xiQ}from"fs/promises";class t90 extends ew{converter;constructor(A,Q,w=pH){super(Q,{schema:Il0,jobTypeName:"inline-image-convert"});this.converter=new nd(A.entityService,Q,w)}async process(A,Q,w){let{filePath:B,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:B,postSlug:$});try{await this.reportProgress(w,{progress:oQ.INIT,message:`Reading file: ${B}`});let f;try{f=await MiQ(B,"utf-8")}catch(H){let W=SA(H);return this.logger.error("Failed to read file",{filePath:B,error:W}),{success:!1,error:W}}await this.reportProgress(w,{progress:oQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(f,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:Y.length}),await this.reportProgress(w,{progress:oQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(f,$);if(!X.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:oQ.SAVE,message:"Writing updated file"});try{await xiQ(B,X.content,"utf-8")}catch(H){let W=SA(H);return this.logger.error("Failed to write file",{filePath:B,error:W}),{success:!1,error:W}}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(f){let Y=SA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function KC1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new n90(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new i90(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new d90(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new o90(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new s90(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new a90(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new t90(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}wA();L0();import{unlink as OiQ,access as viQ}from"fs/promises";var RiQ=Z.record(Z.string(),Z.unknown());function UC1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),w.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(H){w.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:X,entityId:H}=Y.payload;try{let W=await f.getEntity({entityType:X,id:H});if(!W)return w.debug("Entity not found in DB, skipping export",{entityType:X,entityId:H}),{success:!1};await Q.fileOps.writeEntity(W),w.debug("Auto-exported updated entity",{id:W.id,entityType:W.entityType})}catch(W){w.error("Auto-export FAILED for updated entity",{entityType:X,entityId:H,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:X,entityType:H}=Y.payload,W=Q.fileOps.getFilePath(X,H);if(await viQ(W).then(()=>!0,()=>!1))await OiQ(W),w.debug("Auto-deleted entity file",{id:X,entityType:H,path:W});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function GC1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:RiQ.parse(B.data)}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:U4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}wA();import{readdir as qC1,mkdir as CiQ,copyFile as giQ}from"fs/promises";import{join as zC1,resolve as Fl0}from"path";import{join as hiQ}from"path";async function DC1(A){if(!await o8(hiQ(A,".git")))return!1;try{return await ZU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function yiQ(A,Q){if(!await o8(A))return!0;if((await qC1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await DC1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function bC1(A,Q){let w=await qC1(A,{withFileTypes:!0});for(let B of w){let $=zC1(A,B.name),f=zC1(Q,B.name);if(B.isDirectory()){if(!await o8(f))await CiQ(f,{recursive:!0});await bC1($,f)}else await giQ($,f)}}async function VC1(A,Q,w){let B=Fl0(process.cwd(),A);w=w?Fl0(w):Fl0(process.cwd(),"seed-content");let $=await yiQ(B,Q);if($&&await o8(w))Q.debug("Copying seed content to brain-data directory"),await bC1(w,B),Q.debug("Seed content copied successfully");else if($)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function JC1(A,Q,w,B,$){let f=!1,Y=async()=>{if(f)return;f=!0;let X=Q();if(w.seedContent){let H=w.syncPath??A.dataDir;await VC1(H,B,w.seedContentPath)}try{if($){B.debug("Git enabled \u2014 pulling before import");let W=await $.pull();if(W.files.length>0)B.info("Pulled changes from remote",{filesChanged:W.files.length})}B.debug("Starting initial sync");let H=await X.sync();B.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:_L.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){B.error("Initial sync failed",H),await A.messaging.send({type:_L.initialSyncCompleted,payload:{success:!1,error:SA(H)},...{broadcast:!0}})}};A.messaging.subscribe(_L.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class kl0{fn;delayMs;timeout;pending=!1;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(!this.timeout){this.fn(),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs);return}this.pending=!0,clearTimeout(this.timeout),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0;this.pending=!1}}class Ll0{fn;delayMs;timeout;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(this.timeout)clearTimeout(this.timeout);this.timeout=setTimeout(()=>{this.timeout=void 0,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0}}function IC1(A,Q,w,B){let $=new Ll0(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){B.error("Git auto-commit failed",{error:X})}})},w),f=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of f){let H=A.subscribe(X,async()=>{return $.trigger(),{success:!0}});Y.push(H)}return()=>{$.dispose();for(let X of Y)X()}}function FC1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:W,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:G}});if(W.length>0)$.info("Periodic sync: pulled changes",{filesChanged:W.length});if(K)$.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(W){$.error("Periodic git sync failed",{error:W})}finally{Y=!1}},H=setInterval(()=>{X()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(H)}}import{spawnSync as LC1}from"child_process";import{cpSync as EiQ,existsSync as kC1,mkdirSync as TiQ,mkdtempSync as SiQ,rmSync as miQ}from"fs";import{tmpdir as uiQ}from"os";import{fileURLToPath as ciQ}from"url";import{join as liQ,resolve as piQ}from"path";function sI(A,Q){let w=LC1("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let B=w.stderr.toString().trim(),$=w.stdout.toString().trim();throw Error(B||$||`git ${Q.join(" ")} failed`)}}function iiQ(A){return A.startsWith("file://")}function diQ(A){return ciQ(A)}function niQ(A,Q){return LC1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function _C1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!iiQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=diQ(A.gitUrl),B=piQ(A.seedContentPath);if(!kC1(B))throw Error(`Seed content path not found: ${B}`);if(!kC1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),TiQ(w,{recursive:!0}),sI(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(niQ(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:B,branch:Q});let $=SiQ(liQ(uiQ(),"directory-sync-seed-"));try{sI($,["init",`--initial-branch=${Q}`]),sI($,["config","user.name",A.authorName??"Brain"]),sI($,["config","user.email",A.authorEmail??"brain@localhost"]),EiQ(B,$,{recursive:!0,filter:(f)=>!f.split("/").includes(".git")}),sI($,["add","."]),sI($,["commit","-m","seed content remote"]),sI($,["remote","add","origin",A.gitUrl]),sI($,["push","-u","origin",Q])}finally{miQ($,{recursive:!0,force:!0})}}function NC1(A,Q,w,B,$,f){let{subscribe:Y}=A.messaging;Y("entity:export:request",async(X)=>{try{return{success:!0,data:await Q().exportEntities(X.payload.entityTypes)}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Export failed"}}}),Y("entity:import:request",async(X)=>{try{let H=Q(),W=X.payload.paths,K=await H.importEntities(W);if(W&&W.length>0)await H.removeOrphanedEntities();return{success:!0,data:K}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let H=await Q().getStatus();return{success:!0,data:{syncPath:H.syncPath,isInitialized:H.exists,watchEnabled:H.watching,lastSync:H.lastSync?.toISOString()??null,totalFiles:H.stats.totalFiles,byEntityType:H.stats.byEntityType,git:await riQ(f?.(),B)}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Status check failed"}}}),Y("sync:configure:request",async(X)=>{try{return await w({syncPath:X.payload.syncPath}),{success:!0,data:{syncPath:X.payload.syncPath,configured:!0}}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Configuration failed"}}}),Y("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),B.debug("Registered message handlers")}async function riQ(A,Q){if(!A)return null;try{let w=await A.getStatus();return{branch:w.branch,hasChanges:w.hasChanges,ahead:w.ahead,behind:w.behind,lastCommit:w.lastCommit??null,remote:w.remote??null}}catch(w){return Q.debug("Git status unavailable for sync:status:request",{error:w}),null}}wA();L0();wA();L0();function PC1(A,Q){return x6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let B=`${w.entityType}/${w.id}.md`;try{if(w.sha){let f=await Q.show(w.sha,B);return k5({sha:w.sha,entityType:w.entityType,id:w.id,content:f},`Content at ${w.sha.slice(0,7)}`)}let $=await Q.log(B,w.limit);if($.length===0)return k5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return k5({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return j7($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function jC1(A,Q,w,B){let $=[x6(w,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(f,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,H={interfaceType:Y.interfaceType,channelId:Y.channelId};if(B){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:X,interfaceType:H.interfaceType,channelId:H.channelId},toolContext:Y});return k5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let W=await A.queueSyncBatch(Q,X,H);if(!W)return k5({gitPulled:!1},"No files to sync");return k5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:!1},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files`)}catch(X){return j7(X instanceof Error?X.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),x6(w,"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.",Z.object({}),async()=>{try{let f=await A.getStatus(),Y={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let X=await B.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return k5(Y)}catch(f){return j7(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(PC1(w,B));return $}var MC1={name:"@brains/directory-sync",version:"0.2.0-alpha.163",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 _l0 extends Aw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",MC1,A,Yn)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){let{logger:Q,entityService:w}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:Xn,basePrompt:"",formatter:new p90,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new rd({syncPath:B,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:w,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:B})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(UC1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)GC1(A,$,this.config.syncPath??A.dataDir);let f=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!f)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(f&&this.config.git){await _C1({gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:this.config.git.bootstrapFromSeed,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")});let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new Dl0({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),A.jobs.registerHandler("sync-request",new r90(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(IC1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(FC1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)JC1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);NC1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return jC1(A,this.getContext(),this.id,this.gitSync)}async onShutdown(){for(let A of this.gitCleanups)A();this.gitCleanups=[],this.directorySync?.stopWatching(),this.gitSync?.cleanup()}getDirectorySync(){return this.directorySync}async configure(A){this.requireDirectorySync();let Q=this.getContext();this.directorySync=new rd({...this.config,syncPath:A.syncPath,entityService:Q.entityService,logger:Q.logger}),await this.directorySync.initialize(),this.logger.info("Directory sync reconfigured",{path:A.syncPath})}async registerJobHandlers(A){KC1(A,this.requireDirectorySync(),this.logger)}}function UP(A={}){return new _l0(A)}wA();L0();var xC1={name:"@brains/email-resend",version:"0.2.0-alpha.163",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 aiQ=Z.object({apiKey:Z.string().min(1).optional(),from:Z.string().min(1).optional()}),tiQ=Z.looseObject({id:Z.string().optional()});class OC1 extends Aw{fetchImpl;constructor(A={},Q={}){super("email-resend",xC1,A,aiQ);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(AB0,async(w)=>{let B=OyA.parse(w.payload);try{return{success:!0,data:await this.sendWithResend(B)}}catch($){if(B.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:B.to,subject:B.subject,error:$ instanceof Error?$.message:String($)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,w=this.config.from;if(!Q||!w)return{status:"failed"};let B=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:w,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!B.ok)throw Error("Resend email request failed");let $=tiQ.parse(await B.json());return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function e90(A={}){return new OC1(A)}wA();import{render as qs1}from"preact-render-to-string";import{h as rP}from"preact";function vC1(A){var Q,w,B="";if(typeof A=="string"||typeof A=="number")B+=A;else if(typeof A=="object")if(Array.isArray(A)){var $=A.length;for(Q=0;Q<$;Q++)A[Q]&&(w=vC1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function Qg(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=vC1(A))&&(B&&(B+=" "),B+=Q);return B}var eiQ=(A,Q)=>{let w=Array(A.length+Q.length);for(let B=0;B<A.length;B++)w[B]=A[B];for(let B=0;B<Q.length;B++)w[A.length+B]=Q[B];return w},AdQ=(A,Q)=>({classGroupId:A,validator:Q}),SC1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var RC1=[];var QdQ=(A)=>{let Q=BdQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return wdQ(Y);let X=Y.split("-"),H=X[0]===""&&X.length>1?1:0;return mC1(X,H,Q)},getConflictingClassGroupIds:(Y,X)=>{if(X){let H=B[Y],W=w[Y];if(H){if(W)return eiQ(W,H);return H}return W||RC1}return w[Y]||RC1}}},mC1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let $=A[Q],f=w.nextPart.get($);if(f){let W=mC1(A,Q+1,f);if(W)return W}let Y=w.validators;if(Y===null)return;let X=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let W=0;W<H;W++){let K=Y[W];if(K.validator(X))return K.classGroupId}return},wdQ=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),B=Q.slice(0,w);return B?"arbitrary.."+B:void 0})(),BdQ=(A)=>{let{theme:Q,classGroups:w}=A;return $dQ(w,Q)},$dQ=(A,Q)=>{let w=SC1();for(let B in A){let $=A[B];jl0($,w,B,Q)}return w},jl0=(A,Q,w,B)=>{let $=A.length;for(let f=0;f<$;f++){let Y=A[f];fdQ(Y,Q,w,B)}},fdQ=(A,Q,w,B)=>{if(typeof A==="string"){YdQ(A,Q,w);return}if(typeof A==="function"){XdQ(A,Q,w,B);return}ZdQ(A,Q,w,B)},YdQ=(A,Q,w)=>{let B=A===""?Q:uC1(Q,A);B.classGroupId=w},XdQ=(A,Q,w,B)=>{if(HdQ(A)){jl0(A(B),Q,w,B);return}if(Q.validators===null)Q.validators=[];Q.validators.push(AdQ(w,A))},ZdQ=(A,Q,w,B)=>{let $=Object.entries(A),f=$.length;for(let Y=0;Y<f;Y++){let[X,H]=$[Y];jl0(H,uC1(Q,X),w,B)}},uC1=(A,Q)=>{let w=A,B=Q.split("-"),$=B.length;for(let f=0;f<$;f++){let Y=B[f],X=w.nextPart.get(Y);if(!X)X=SC1(),w.nextPart.set(Y,X);w=X}return w},HdQ=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,WdQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),B=Object.create(null),$=(f,Y)=>{if(w[f]=Y,Q++,Q>A)Q=0,B=w,w=Object.create(null)};return{get(f){let Y=w[f];if(Y!==void 0)return Y;if((Y=B[f])!==void 0)return $(f,Y),Y},set(f,Y){if(f in w)w[f]=Y;else $(f,Y)}}};var KdQ=[],hC1=(A,Q,w,B,$)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:B,isExternal:$}),UdQ=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,B=($)=>{let f=[],Y=0,X=0,H=0,W,K=$.length;for(let J=0;J<K;J++){let V=$[J];if(Y===0&&X===0){if(V===":"){f.push($.slice(H,J)),H=J+1;continue}if(V==="/"){W=J;continue}}if(V==="[")Y++;else if(V==="]")Y--;else if(V==="(")X++;else if(V===")")X--}let U=f.length===0?$:$.slice(H),G=U,q=!1;if(U.endsWith("!"))G=U.slice(0,-1),q=!0;else if(U.startsWith("!"))G=U.slice(1),q=!0;let b=W&&W>H?W-H:void 0;return hC1(f,q,G,b)};if(Q){let $=Q+":",f=B;B=(Y)=>Y.startsWith($)?f(Y.slice($.length)):hC1(KdQ,!1,Y,void 0,!0)}if(w){let $=B;B=(f)=>w({className:f,parseClassName:$})}return B},GdQ=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,B)=>{Q.set(w,1e6+B)}),(w)=>{let B=[],$=[];for(let f=0;f<w.length;f++){let Y=w[f],X=Y[0]==="[",H=Q.has(Y);if(X||H){if($.length>0)$.sort(),B.push(...$),$=[];B.push(Y)}else $.push(Y)}if($.length>0)$.sort(),B.push(...$);return B}},DdQ=(A)=>({cache:WdQ(A.cacheSize),parseClassName:UdQ(A),sortModifiers:GdQ(A),postfixLookupClassGroupIds:zdQ(A),...QdQ(A)}),zdQ=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let B=0;B<w.length;B++)Q[w[B]]=!0;return Q},qdQ=/\s+/,bdQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$,sortModifiers:f,postfixLookupClassGroupIds:Y}=Q,X=[],H=A.trim().split(qdQ),W="";for(let K=H.length-1;K>=0;K-=1){let U=H[K],{isExternal:G,modifiers:q,hasImportantModifier:b,baseClassName:J,maybePostfixModifierPosition:V}=w(U);if(G){W=U+(W.length>0?" "+W:W);continue}let k=!!V,N;if(k){let j=J.substring(0,V);N=B(j);let E=N&&Y[N]?B(J):void 0;if(E&&E!==N)N=E,k=!1}else N=B(J);if(!N){if(!k){W=U+(W.length>0?" "+W:W);continue}if(N=B(J),!N){W=U+(W.length>0?" "+W:W);continue}k=!1}let L=q.length===0?"":q.length===1?q[0]:f(q).join(":"),O=b?L+"!":L,v=O+N;if(X.indexOf(v)>-1)continue;X.push(v);let h=$(N,k);for(let j=0;j<h.length;++j){let E=h[j];X.push(O+E)}W=U+(W.length>0?" "+W:W)}return W},VdQ=(...A)=>{let Q=0,w,B,$="";while(Q<A.length)if(w=A[Q++]){if(B=cC1(w))$&&($+=" "),$+=B}return $},cC1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=cC1(A[B]))w&&(w+=" "),w+=Q}return w},CC1=(A,...Q)=>{let w,B,$,f,Y=(H)=>{let W=Q.reduce((K,U)=>U(K),A());return w=DdQ(W),B=w.cache.get,$=w.cache.set,f=X,X(H)},X=(H)=>{let W=B(H);if(W)return W;let K=bdQ(H,w);return $(H,K),K};return f=Y,(...H)=>f(VdQ(...H))},JdQ=[],k9=(A)=>{let Q=(w)=>w[A]||JdQ;return Q.isThemeGetter=!0,Q},lC1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,pC1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,IdQ=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,FdQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,kdQ=/\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$/,LdQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,_dQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,NdQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,aI=(A)=>IdQ.test(A),Ew=(A)=>!!A&&!Number.isNaN(Number(A)),jD=(A)=>!!A&&Number.isInteger(Number(A)),Nl0=(A)=>A.endsWith("%")&&Ew(A.slice(0,-1)),Eq=(A)=>FdQ.test(A),iC1=()=>!0,PdQ=(A)=>kdQ.test(A)&&!LdQ.test(A),Ml0=()=>!1,jdQ=(A)=>_dQ.test(A),MdQ=(A)=>NdQ.test(A),xdQ=(A)=>!k2(A)&&!P2(A),OdQ=(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)),vdQ=(A)=>tI(A,rC1,Ml0),k2=(A)=>lC1.test(A),GP=(A)=>tI(A,oC1,PdQ),gC1=(A)=>tI(A,SdQ,Ew),RdQ=(A)=>tI(A,aC1,iC1),hdQ=(A)=>tI(A,sC1,Ml0),yC1=(A)=>tI(A,dC1,Ml0),CdQ=(A)=>tI(A,nC1,MdQ),A70=(A)=>tI(A,tC1,jdQ),P2=(A)=>pC1.test(A),Zn=(A)=>DP(A,oC1),gdQ=(A)=>DP(A,sC1),EC1=(A)=>DP(A,dC1),ydQ=(A)=>DP(A,rC1),EdQ=(A)=>DP(A,nC1),Q70=(A)=>DP(A,tC1,!0),TdQ=(A)=>DP(A,aC1,!0),tI=(A,Q,w)=>{let B=lC1.exec(A);if(B){if(B[1])return Q(B[1]);return w(B[2])}return!1},DP=(A,Q,w=!1)=>{let B=pC1.exec(A);if(B){if(B[1])return Q(B[1]);return w}return!1},dC1=(A)=>A==="position"||A==="percentage",nC1=(A)=>A==="image"||A==="url",rC1=(A)=>A==="length"||A==="size"||A==="bg-size",oC1=(A)=>A==="length",SdQ=(A)=>A==="number",sC1=(A)=>A==="family-name",aC1=(A)=>A==="number"||A==="weight",tC1=(A)=>A==="shadow";var TC1=()=>{let A=k9("color"),Q=k9("font"),w=k9("text"),B=k9("font-weight"),$=k9("tracking"),f=k9("leading"),Y=k9("breakpoint"),X=k9("container"),H=k9("spacing"),W=k9("radius"),K=k9("shadow"),U=k9("inset-shadow"),G=k9("text-shadow"),q=k9("drop-shadow"),b=k9("blur"),J=k9("perspective"),V=k9("aspect"),k=k9("ease"),N=k9("animate"),L=()=>["auto","avoid","all","avoid-page","page","left","right","column"],O=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...O(),P2,k2],h=()=>["auto","hidden","clip","visible","scroll"],j=()=>["auto","contain","none"],E=()=>[P2,k2,H],S=()=>[aI,"full","auto",...E()],p=()=>[jD,"none","subgrid",P2,k2],e=()=>["auto",{span:["full",jD,P2,k2]},jD,P2,k2],Y0=()=>[jD,"auto",P2,k2],l=()=>["auto","min","max","fr",P2,k2],P=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...E()],n=()=>[aI,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...E()],o=()=>[aI,"screen","full","dvw","lvw","svw","min","max","fit",...E()],K0=()=>[aI,"screen","full","lh","dvh","lvh","svh","min","max","fit",...E()],c=()=>[A,P2,k2],X0=()=>[...O(),EC1,yC1,{position:[P2,k2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],w0=()=>["auto","cover","contain",ydQ,vdQ,{size:[P2,k2]}],h0=()=>[Nl0,Zn,GP],S0=()=>["","none","full",W,P2,k2],V0=()=>["",Ew,Zn,GP],J0=()=>["solid","dashed","dotted","double"],P0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],C0=()=>[Ew,Nl0,EC1,yC1],_0=()=>["","none",b,P2,k2],N0=()=>["none",Ew,P2,k2],j0=()=>["none",Ew,P2,k2],M0=()=>[Ew,P2,k2],T0=()=>[aI,"full",...E()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Eq],breakpoint:[Eq],color:[iC1],container:[Eq],"drop-shadow":[Eq],ease:["in","out","in-out"],font:[xdQ],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Eq],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Eq],shadow:[Eq],spacing:["px",Ew],text:[Eq],"text-shadow":[Eq],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",aI,k2,P2,V]}],container:["container"],"container-type":[{"@container":["","normal","size",P2,k2]}],"container-named":[OdQ],columns:[{columns:[Ew,k2,P2,X]}],"break-after":[{"break-after":L()}],"break-before":[{"break-before":L()}],"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:h()}],"overflow-x":[{"overflow-x":h()}],"overflow-y":[{"overflow-y":h()}],overscroll:[{overscroll:j()}],"overscroll-x":[{"overscroll-x":j()}],"overscroll-y":[{"overscroll-y":j()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:S()}],"inset-x":[{"inset-x":S()}],"inset-y":[{"inset-y":S()}],start:[{"inset-s":S(),start:S()}],end:[{"inset-e":S(),end:S()}],"inset-bs":[{"inset-bs":S()}],"inset-be":[{"inset-be":S()}],top:[{top:S()}],right:[{right:S()}],bottom:[{bottom:S()}],left:[{left:S()}],visibility:["visible","invisible","collapse"],z:[{z:[jD,"auto",P2,k2]}],basis:[{basis:[aI,"full","auto",X,...E()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Ew,aI,"auto","initial","none",k2]}],grow:[{grow:["",Ew,P2,k2]}],shrink:[{shrink:["",Ew,P2,k2]}],order:[{order:[jD,"first","last","none",P2,k2]}],"grid-cols":[{"grid-cols":p()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":Y0()}],"col-end":[{"col-end":Y0()}],"grid-rows":[{"grid-rows":p()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":Y0()}],"row-end":[{"row-end":Y0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:E()}],"gap-x":[{"gap-x":E()}],"gap-y":[{"gap-y":E()}],"justify-content":[{justify:[...P(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...P()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":P()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:E()}],px:[{px:E()}],py:[{py:E()}],ps:[{ps:E()}],pe:[{pe:E()}],pbs:[{pbs:E()}],pbe:[{pbe:E()}],pt:[{pt:E()}],pr:[{pr:E()}],pb:[{pb:E()}],pl:[{pl:E()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":E()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":E()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...o()]}],"min-inline-size":[{"min-inline":["auto",...o()]}],"max-inline-size":[{"max-inline":["none",...o()]}],"block-size":[{block:["auto",...K0()]}],"min-block-size":[{"min-block":["auto",...K0()]}],"max-block-size":[{"max-block":["none",...K0()]}],w:[{w:[X,"screen",...n()]}],"min-w":[{"min-w":[X,"screen","none",...n()]}],"max-w":[{"max-w":[X,"screen","none","prose",{screen:[Y]},...n()]}],h:[{h:["screen","lh",...n()]}],"min-h":[{"min-h":["screen","lh","none",...n()]}],"max-h":[{"max-h":["screen","lh",...n()]}],"font-size":[{text:["base",w,Zn,GP]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[B,TdQ,RdQ]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Nl0,k2]}],"font-family":[{font:[gdQ,hdQ,Q]}],"font-features":[{"font-features":[k2]}],"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:[$,P2,k2]}],"line-clamp":[{"line-clamp":[Ew,"none",P2,gC1]}],leading:[{leading:[f,...E()]}],"list-image":[{"list-image":["none",P2,k2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",P2,k2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:c()}],"text-color":[{text:c()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...J0(),"wavy"]}],"text-decoration-thickness":[{decoration:[Ew,"from-font","auto",P2,GP]}],"text-decoration-color":[{decoration:c()}],"underline-offset":[{"underline-offset":[Ew,"auto",P2,k2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:E()}],"tab-size":[{tab:[jD,P2,k2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",P2,k2]}],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",P2,k2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:X0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:w0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},jD,P2,k2],radial:["",P2,k2],conic:[jD,P2,k2]},EdQ,CdQ]}],"bg-color":[{bg:c()}],"gradient-from-pos":[{from:h0()}],"gradient-via-pos":[{via:h0()}],"gradient-to-pos":[{to:h0()}],"gradient-from":[{from:c()}],"gradient-via":[{via:c()}],"gradient-to":[{to:c()}],rounded:[{rounded:S0()}],"rounded-s":[{"rounded-s":S0()}],"rounded-e":[{"rounded-e":S0()}],"rounded-t":[{"rounded-t":S0()}],"rounded-r":[{"rounded-r":S0()}],"rounded-b":[{"rounded-b":S0()}],"rounded-l":[{"rounded-l":S0()}],"rounded-ss":[{"rounded-ss":S0()}],"rounded-se":[{"rounded-se":S0()}],"rounded-ee":[{"rounded-ee":S0()}],"rounded-es":[{"rounded-es":S0()}],"rounded-tl":[{"rounded-tl":S0()}],"rounded-tr":[{"rounded-tr":S0()}],"rounded-br":[{"rounded-br":S0()}],"rounded-bl":[{"rounded-bl":S0()}],"border-w":[{border:V0()}],"border-w-x":[{"border-x":V0()}],"border-w-y":[{"border-y":V0()}],"border-w-s":[{"border-s":V0()}],"border-w-e":[{"border-e":V0()}],"border-w-bs":[{"border-bs":V0()}],"border-w-be":[{"border-be":V0()}],"border-w-t":[{"border-t":V0()}],"border-w-r":[{"border-r":V0()}],"border-w-b":[{"border-b":V0()}],"border-w-l":[{"border-l":V0()}],"divide-x":[{"divide-x":V0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":V0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...J0(),"hidden","none"]}],"divide-style":[{divide:[...J0(),"hidden","none"]}],"border-color":[{border:c()}],"border-color-x":[{"border-x":c()}],"border-color-y":[{"border-y":c()}],"border-color-s":[{"border-s":c()}],"border-color-e":[{"border-e":c()}],"border-color-bs":[{"border-bs":c()}],"border-color-be":[{"border-be":c()}],"border-color-t":[{"border-t":c()}],"border-color-r":[{"border-r":c()}],"border-color-b":[{"border-b":c()}],"border-color-l":[{"border-l":c()}],"divide-color":[{divide:c()}],"outline-style":[{outline:[...J0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Ew,P2,k2]}],"outline-w":[{outline:["",Ew,Zn,GP]}],"outline-color":[{outline:c()}],shadow:[{shadow:["","none",K,Q70,A70]}],"shadow-color":[{shadow:c()}],"inset-shadow":[{"inset-shadow":["none",U,Q70,A70]}],"inset-shadow-color":[{"inset-shadow":c()}],"ring-w":[{ring:V0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:c()}],"ring-offset-w":[{"ring-offset":[Ew,GP]}],"ring-offset-color":[{"ring-offset":c()}],"inset-ring-w":[{"inset-ring":V0()}],"inset-ring-color":[{"inset-ring":c()}],"text-shadow":[{"text-shadow":["none",G,Q70,A70]}],"text-shadow-color":[{"text-shadow":c()}],opacity:[{opacity:[Ew,P2,k2]}],"mix-blend":[{"mix-blend":[...P0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":P0()}],"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":[Ew]}],"mask-image-linear-from-pos":[{"mask-linear-from":C0()}],"mask-image-linear-to-pos":[{"mask-linear-to":C0()}],"mask-image-linear-from-color":[{"mask-linear-from":c()}],"mask-image-linear-to-color":[{"mask-linear-to":c()}],"mask-image-t-from-pos":[{"mask-t-from":C0()}],"mask-image-t-to-pos":[{"mask-t-to":C0()}],"mask-image-t-from-color":[{"mask-t-from":c()}],"mask-image-t-to-color":[{"mask-t-to":c()}],"mask-image-r-from-pos":[{"mask-r-from":C0()}],"mask-image-r-to-pos":[{"mask-r-to":C0()}],"mask-image-r-from-color":[{"mask-r-from":c()}],"mask-image-r-to-color":[{"mask-r-to":c()}],"mask-image-b-from-pos":[{"mask-b-from":C0()}],"mask-image-b-to-pos":[{"mask-b-to":C0()}],"mask-image-b-from-color":[{"mask-b-from":c()}],"mask-image-b-to-color":[{"mask-b-to":c()}],"mask-image-l-from-pos":[{"mask-l-from":C0()}],"mask-image-l-to-pos":[{"mask-l-to":C0()}],"mask-image-l-from-color":[{"mask-l-from":c()}],"mask-image-l-to-color":[{"mask-l-to":c()}],"mask-image-x-from-pos":[{"mask-x-from":C0()}],"mask-image-x-to-pos":[{"mask-x-to":C0()}],"mask-image-x-from-color":[{"mask-x-from":c()}],"mask-image-x-to-color":[{"mask-x-to":c()}],"mask-image-y-from-pos":[{"mask-y-from":C0()}],"mask-image-y-to-pos":[{"mask-y-to":C0()}],"mask-image-y-from-color":[{"mask-y-from":c()}],"mask-image-y-to-color":[{"mask-y-to":c()}],"mask-image-radial":[{"mask-radial":[P2,k2]}],"mask-image-radial-from-pos":[{"mask-radial-from":C0()}],"mask-image-radial-to-pos":[{"mask-radial-to":C0()}],"mask-image-radial-from-color":[{"mask-radial-from":c()}],"mask-image-radial-to-color":[{"mask-radial-to":c()}],"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":O()}],"mask-image-conic-pos":[{"mask-conic":[Ew]}],"mask-image-conic-from-pos":[{"mask-conic-from":C0()}],"mask-image-conic-to-pos":[{"mask-conic-to":C0()}],"mask-image-conic-from-color":[{"mask-conic-from":c()}],"mask-image-conic-to-color":[{"mask-conic-to":c()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:X0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:w0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",P2,k2]}],filter:[{filter:["","none",P2,k2]}],blur:[{blur:_0()}],brightness:[{brightness:[Ew,P2,k2]}],contrast:[{contrast:[Ew,P2,k2]}],"drop-shadow":[{"drop-shadow":["","none",q,Q70,A70]}],"drop-shadow-color":[{"drop-shadow":c()}],grayscale:[{grayscale:["",Ew,P2,k2]}],"hue-rotate":[{"hue-rotate":[Ew,P2,k2]}],invert:[{invert:["",Ew,P2,k2]}],saturate:[{saturate:[Ew,P2,k2]}],sepia:[{sepia:["",Ew,P2,k2]}],"backdrop-filter":[{"backdrop-filter":["","none",P2,k2]}],"backdrop-blur":[{"backdrop-blur":_0()}],"backdrop-brightness":[{"backdrop-brightness":[Ew,P2,k2]}],"backdrop-contrast":[{"backdrop-contrast":[Ew,P2,k2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Ew,P2,k2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Ew,P2,k2]}],"backdrop-invert":[{"backdrop-invert":["",Ew,P2,k2]}],"backdrop-opacity":[{"backdrop-opacity":[Ew,P2,k2]}],"backdrop-saturate":[{"backdrop-saturate":[Ew,P2,k2]}],"backdrop-sepia":[{"backdrop-sepia":["",Ew,P2,k2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":E()}],"border-spacing-x":[{"border-spacing-x":E()}],"border-spacing-y":[{"border-spacing-y":E()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",P2,k2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Ew,"initial",P2,k2]}],ease:[{ease:["linear","initial",k,P2,k2]}],delay:[{delay:[Ew,P2,k2]}],animate:[{animate:["none",N,P2,k2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[J,P2,k2]}],"perspective-origin":[{"perspective-origin":v()}],rotate:[{rotate:N0()}],"rotate-x":[{"rotate-x":N0()}],"rotate-y":[{"rotate-y":N0()}],"rotate-z":[{"rotate-z":N0()}],scale:[{scale:j0()}],"scale-x":[{"scale-x":j0()}],"scale-y":[{"scale-y":j0()}],"scale-z":[{"scale-z":j0()}],"scale-3d":["scale-3d"],skew:[{skew:M0()}],"skew-x":[{"skew-x":M0()}],"skew-y":[{"skew-y":M0()}],transform:[{transform:[P2,k2,"","none","gpu","cpu"]}],"transform-origin":[{origin:v()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:T0()}],"translate-x":[{"translate-x":T0()}],"translate-y":[{"translate-y":T0()}],"translate-z":[{"translate-z":T0()}],"translate-none":["translate-none"],zoom:[{zoom:[jD,P2,k2]}],accent:[{accent:c()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:c()}],"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",P2,k2]}],"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":c()}],"scrollbar-track-color":[{"scrollbar-track":c()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":E()}],"scroll-mx":[{"scroll-mx":E()}],"scroll-my":[{"scroll-my":E()}],"scroll-ms":[{"scroll-ms":E()}],"scroll-me":[{"scroll-me":E()}],"scroll-mbs":[{"scroll-mbs":E()}],"scroll-mbe":[{"scroll-mbe":E()}],"scroll-mt":[{"scroll-mt":E()}],"scroll-mr":[{"scroll-mr":E()}],"scroll-mb":[{"scroll-mb":E()}],"scroll-ml":[{"scroll-ml":E()}],"scroll-p":[{"scroll-p":E()}],"scroll-px":[{"scroll-px":E()}],"scroll-py":[{"scroll-py":E()}],"scroll-ps":[{"scroll-ps":E()}],"scroll-pe":[{"scroll-pe":E()}],"scroll-pbs":[{"scroll-pbs":E()}],"scroll-pbe":[{"scroll-pbe":E()}],"scroll-pt":[{"scroll-pt":E()}],"scroll-pr":[{"scroll-pr":E()}],"scroll-pb":[{"scroll-pb":E()}],"scroll-pl":[{"scroll-pl":E()}],"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",P2,k2]}],fill:[{fill:["none",...c()]}],"stroke-w":[{stroke:[Ew,Zn,GP,gC1]}],stroke:[{stroke:["none",...c()]}],"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"]}},mdQ=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:B,extend:$={},override:f={}})=>{return wg(A,"cacheSize",Q),wg(A,"prefix",w),wg(A,"experimentalParseClassName",B),w70(A.theme,f.theme),w70(A.classGroups,f.classGroups),w70(A.conflictingClassGroups,f.conflictingClassGroups),w70(A.conflictingClassGroupModifiers,f.conflictingClassGroupModifiers),wg(A,"postfixLookupClassGroups",f.postfixLookupClassGroups),wg(A,"orderSensitiveModifiers",f.orderSensitiveModifiers),B70(A.theme,$.theme),B70(A.classGroups,$.classGroups),B70(A.conflictingClassGroups,$.conflictingClassGroups),B70(A.conflictingClassGroupModifiers,$.conflictingClassGroupModifiers),Pl0(A,$,"postfixLookupClassGroups"),Pl0(A,$,"orderSensitiveModifiers"),A},wg=(A,Q,w)=>{if(w!==void 0)A[Q]=w},w70=(A,Q)=>{if(Q)for(let w in Q)wg(A,w,Q[w])},B70=(A,Q)=>{if(Q)for(let w in Q)Pl0(A,Q,w)},Pl0=(A,Q,w)=>{let B=Q[w];if(B!==void 0)A[w]=A[w]?A[w].concat(B):B},$70=(A,...Q)=>typeof A==="function"?CC1(TC1,A,...Q):CC1(()=>mdQ(TC1(),A),...Q);var udQ=$70({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 j2(...A){return udQ(Qg(A))}var eC1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,Ag1=Qg,LB=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return Ag1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,Y=Object.keys($).map((W)=>{let K=w===null||w===void 0?void 0:w[W],U=f===null||f===void 0?void 0:f[W];if(K===null)return null;let G=eC1(K)||eC1(U);return $[W][G]}),X=w&&Object.entries(w).reduce((W,K)=>{let[U,G]=K;if(G===void 0)return W;return W[U]=G,W},{}),H=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((W,K)=>{let{class:U,className:G,...q}=K;return Object.entries(q).every((b)=>{let[J,V]=b;return Array.isArray(V)?V.includes({...f,...X}[J]):{...f,...X}[J]===V})?[...W,U,G]:W},[]);return Ag1(A,Y,H,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as xl0}from"preact/jsx-dev-runtime";var Qg1=LB("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 Ol0({variant:A,title:Q,children:w,className:B}){return xl0("div",{className:j2(Qg1({variant:A}),B),role:"alert",children:[Q&&xl0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),xl0("div",{className:j2(Q&&"mt-1","text-sm text-current opacity-75"),children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as cdQ}from"preact/jsx-dev-runtime";var wg1=LB("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 zP({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...Y}){return cdQ("button",{type:f,className:j2(wg1({variant:A,size:Q}),w),...Y,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as ldQ}from"preact/jsx-dev-runtime";var Bg1=LB("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 L9({href:A,children:Q,variant:w,size:B,external:$=!1,className:f,"aria-label":Y}){let X=$?{target:"_blank",rel:"noopener noreferrer"}:{};return ldQ("a",{href:A,className:j2(Bg1({variant:w,size:B}),f),"aria-label":Y,...X,children:Q},void 0,!1,void 0,this)}import{jsxDEV as f70}from"preact/jsx-dev-runtime";var $g1=LB("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"}}),pdQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Bg({variant:A,size:Q,className:w}){let B=pdQ[Q??"md"];return f70("button",{onclick:"toggleTheme()",type:"button",className:j2($g1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:f70("svg",{className:j2(B,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[f70("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),f70("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 vl0}from"preact/jsx-dev-runtime";var fg1=LB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function Y70({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((Y,X)=>Y.priority-X.priority);return vl0("ul",{className:j2(fg1({orientation:B}),Q),children:[f.map((Y)=>vl0("li",{children:vl0("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as vyB}from"preact/jsx-dev-runtime";import{jsxDEV as CyB}from"preact/jsx-dev-runtime";import{createContext as idQ,h as ddQ}from"preact";import{useContext as ndQ}from"preact/hooks";var Rl0=idQ(null);function $g({headCollector:A,children:Q}){return ddQ(Rl0.Provider,{value:A},Q)}function Yg1(){return ndQ(Rl0)}function dQ(A){let Q=Yg1();if(Q)Q.setHeadProps(A);return null}import{createContext as _eQ,h as NeQ}from"preact";import{useContext as PeQ}from"preact/hooks";Cj0();var qS1=Z1(zS1(),1),keQ=new Aw0({gfm:!0,breaks:!0}),LeQ={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 Bi0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new Aw0({gfm:!0,breaks:!0}).use({renderer:{image({href:f,title:Y,text:X}){return w(f,Y,X)??!1}}}):keQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5761
|
+
`)}}wA();class i90 extends ew{directorySync;constructor(A,Q,w){super(A,{schema:Vl0,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:$.exported,failed:$.failed,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory export job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}wA();class d90 extends ew{directorySync;constructor(A,Q,w){super(A,{schema:bl0,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let B=Date.now();try{let $=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:$.imported,skipped:$.skipped,failed:$.failed,quarantined:$.quarantined,duration:Date.now()-B}),$}catch($){throw this.logger.error("Directory import job failed",{jobId:Q,error:$}),$}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}wA();class n90 extends ew{directorySync;context;constructor(A,Q,w){super(A,{schema:zl0,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let B=Date.now(),$=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:$});let f={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if($!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),f=await this.importWithProgress(A.paths,w),$==="import")await this.waitForImportJobs(f.jobIds,w),await w.report({progress:100,message:`Import complete: ${f.imported} imported`});else await w.report({progress:50,message:`Imported ${f.imported} entities`}),await this.waitForImportJobs(f.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if($!=="import"){let H=$==="export"?10:60;await w.report({progress:H,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:$==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${f.imported} imported, ${Y.exported} exported`})}let X=Date.now()-B;return this.logger.info("Directory sync job completed",{jobId:Q,duration:X,imported:f.imported,exported:Y.exported}),{import:f,export:Y,duration:X}}async importWithProgress(A,Q){try{return await this.directorySync.importEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Import phase failed",{error:w}),w}}async exportWithProgress(A,Q){try{return await this.directorySync.exportEntitiesWithProgress(A,Q,10)}catch(w){throw this.logger.error("Export phase failed",{error:w}),w}}async waitForImportJobs(A,Q){if(A.length===0)return;this.logger.debug(`Waiting for ${A.length} import jobs to complete`);let{entityService:w}=this.context,B=300000,$=500,f=Date.now(),Y=async()=>{let H=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(H===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-f>B){this.logger.warn(`Timeout waiting for import jobs (${H}/${A.length} completed)`);return}let W=Math.round(H/A.length*100);return await Q.report({progress:50+Math.round(W*0.05),message:`Processing ${H}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,$)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}wA();class r90 extends ew{context;directorySync;gitSync;constructor(A,Q,w,B){super(A,{schema:ql0,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=B}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let B=await this.gitSync.withLock(async()=>{return await this.gitSync.pull(),await w.report({progress:35,message:"Scanning pulled content for sync changes"}),this.directorySync.queueSyncBatch(this.context,A.source,{rootJobId:Q,interfaceType:A.interfaceType,channelId:A.channelId})});if(!B)return await w.report({progress:100,message:"Sync complete: no files to import"}),{gitPulled:!0,batchQueued:!1};return await w.report({progress:100,message:`Sync queued: ${B.importOperationsCount} import jobs for ${B.totalFiles} files`}),kiQ(B)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function kiQ(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}wA();class o90 extends ew{context;constructor(A,Q,w){super(A,{schema:l90,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let B=l90.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}),await w.report({progress:0,total:1,message:`Deleting ${B.entityType}:${B.entityId}`});try{let $=await this.context.entityService.deleteEntity({entityType:B.entityType,id:B.entityId});if($)this.logger.info("Successfully deleted entity for removed file",{entityId:B.entityId,entityType:B.entityType});else this.logger.warn("Entity not found in database",{entityId:B.entityId,entityType:B.entityType});return await w.report({progress:1,total:1,message:`Deleted ${B.entityType}:${B.entityId}`}),{deleted:$,entityId:B.entityId,entityType:B.entityType,filePath:B.filePath}}catch($){throw this.logger.error("Failed to delete entity",{entityId:B.entityId,entityType:B.entityType,error:$}),$}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}wA();L0();var LiQ=Z.object({});class s90 extends ew{directorySync;constructor(A,Q){super(A,{schema:LiQ,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let B=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${B.deleted} orphans removed`}),B}}wA();_4();l9();T6();L0();_4();import{readFile as _iQ,writeFile as NiQ}from"fs/promises";var PiQ=Jl0,jiQ=Z.record(Z.string(),Z.unknown());class a90 extends ew{context;fetcher;constructor(A,Q,w=pH){super(Q,{schema:PiQ,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:B,sourceUrl:$,postTitle:f,postSlug:Y,customAlt:X}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:B,sourceUrl:$,postSlug:Y});try{await this.reportProgress(w,{progress:oQ.INIT,message:`Reading file: ${B}`});let H;try{H=await _iQ(B,"utf-8")}catch(V){return this.logger.error("Failed to read file",{filePath:B,error:SA(V)}),f$.failure(V)}let W;try{W=M6(H)}catch(V){return this.logger.warn("Failed to parse markdown",{filePath:B,error:SA(V)}),f$.failure(V)}let K=jiQ.safeParse(W.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:oQ.FETCH,message:"Checking for existing image"});let G=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:$}},limit:1}}),q;if(G[0])q=G[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:$,imageId:q}),await this.reportProgress(w,{progress:oQ.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:oQ.PROCESS,message:`Fetching image from ${$}`});let V;try{V=await this.fetcher($)}catch(h){return this.logger.error("Failed to fetch image",{sourceUrl:$,error:SA(h)}),f$.failure(h)}await this.reportProgress(w,{progress:oQ.GENERATE,message:"Creating image entity"});let{base64:k}=AJ(V),N=aL(k),L=QJ(k);if(!N||!L)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:$}),f$.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let O=`Cover image for ${f}`,v=X??O;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:V,metadata:{title:O,alt:v,format:N,width:L.width,height:L.height,sourceUrl:$}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:$}),await this.reportProgress(w,{progress:oQ.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:oQ.SAVE,message:"Updating file"});let b={...U};delete b.coverImageUrl,delete b.coverImageAlt,b.coverImageId=q;let J=IL(b,W.content);try{await NiQ(B,J,"utf-8")}catch(V){return this.logger.error("Failed to write file",{filePath:B,error:SA(V)}),f$.failure(V)}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:B,imageId:q,sourceUrl:$}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:B,error:SA(H)}),f$.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}wA();_4();T6();import{readFile as MiQ,writeFile as xiQ}from"fs/promises";class t90 extends ew{converter;constructor(A,Q,w=pH){super(Q,{schema:Il0,jobTypeName:"inline-image-convert"});this.converter=new nd(A.entityService,Q,w)}async process(A,Q,w){let{filePath:B,postSlug:$}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:B,postSlug:$});try{await this.reportProgress(w,{progress:oQ.INIT,message:`Reading file: ${B}`});let f;try{f=await MiQ(B,"utf-8")}catch(H){let W=SA(H);return this.logger.error("Failed to read file",{filePath:B,error:W}),{success:!1,error:W}}await this.reportProgress(w,{progress:oQ.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(f,$);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:B,count:Y.length}),await this.reportProgress(w,{progress:oQ.PROCESS,message:`Converting ${Y.length} images`});let X=await this.converter.convert(f,$);if(!X.converted)return this.logger.debug("No images were converted",{filePath:B}),await this.reportProgress(w,{progress:oQ.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:oQ.SAVE,message:"Writing updated file"});try{await xiQ(B,X.content,"utf-8")}catch(H){let W=SA(H);return this.logger.error("Failed to write file",{filePath:B,error:W}),{success:!1,error:W}}return await this.reportProgress(w,{progress:oQ.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:B,convertedCount:X.convertedCount}),{success:!0,convertedCount:X.convertedCount}}catch(f){let Y=SA(f);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:B,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function KC1(A,Q,w){let B=($)=>w.child($);A.jobs.registerHandler("directory-sync",new n90(B("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new i90(B("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new d90(B("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new o90(B("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new s90(B("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new a90(A,B("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new t90(A,B("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}wA();L0();import{unlink as OiQ,access as viQ}from"fs/promises";var RiQ=Z.record(Z.string(),Z.unknown());function UC1(A,Q,w,B){let{subscribe:$}=A.messaging,{entityService:f}=A;$("entity:created",async(Y)=>{let{entity:X}=Y.payload;try{await Q.fileOps.writeEntity(X),w.debug("Auto-exported created entity",{id:X.id,entityType:X.entityType})}catch(H){w.error("Auto-export FAILED for created entity",{id:X.id,entityType:X.entityType,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),$("entity:updated",async(Y)=>{let{entityType:X,entityId:H}=Y.payload;try{let W=await f.getEntity({entityType:X,id:H});if(!W)return w.debug("Entity not found in DB, skipping export",{entityType:X,entityId:H}),{success:!1};await Q.fileOps.writeEntity(W),w.debug("Auto-exported updated entity",{id:W.id,entityType:W.entityType})}catch(W){w.error("Auto-export FAILED for updated entity",{entityType:X,entityId:H,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),$("entity:deleted",async(Y)=>{let{entityId:X,entityType:H}=Y.payload,W=Q.fileOps.getFilePath(X,H);if(await viQ(W).then(()=>!0,()=>!1))await OiQ(W),w.debug("Auto-deleted entity file",{id:X,entityType:H,path:W});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:B})}function GC1(A,Q,w){Q.setJobQueueCallback(async(B)=>{let $=[{type:B.type,data:RiQ.parse(B.data)}];return A.jobs.enqueueBatch($,{priority:5,source:"directory-sync-watcher",rootJobId:U4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}wA();import{readdir as qC1,mkdir as CiQ,copyFile as giQ}from"fs/promises";import{join as zC1,resolve as Fl0}from"path";import{join as hiQ}from"path";async function DC1(A){if(!await o8(hiQ(A,".git")))return!1;try{return await ZU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function yiQ(A,Q){if(!await o8(A))return!0;if((await qC1(A)).filter(($)=>!$.startsWith(".")&&!$.startsWith("_")).length>0)return!1;if(await DC1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function bC1(A,Q){let w=await qC1(A,{withFileTypes:!0});for(let B of w){let $=zC1(A,B.name),f=zC1(Q,B.name);if(B.isDirectory()){if(!await o8(f))await CiQ(f,{recursive:!0});await bC1($,f)}else await giQ($,f)}}async function VC1(A,Q,w){let B=Fl0(process.cwd(),A);w=w?Fl0(w):Fl0(process.cwd(),"seed-content");let $=await yiQ(B,Q);if($&&await o8(w))Q.debug("Copying seed content to brain-data directory"),await bC1(w,B),Q.debug("Seed content copied successfully");else if($)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function JC1(A,Q,w,B,$){let f=!1,Y=async()=>{if(f)return;f=!0;let X=Q();if(w.seedContent){let H=w.syncPath??A.dataDir;await VC1(H,B,w.seedContentPath)}try{if($){B.debug("Git enabled \u2014 pulling before import");let W=await $.pull();if(W.files.length>0)B.info("Pulled changes from remote",{filesChanged:W.files.length})}B.debug("Starting initial sync");let H=await X.sync();B.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:_L.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){B.error("Initial sync failed",H),await A.messaging.send({type:_L.initialSyncCompleted,payload:{success:!1,error:SA(H)},...{broadcast:!0}})}};A.messaging.subscribe(_L.pluginsRegistered,async()=>{return B.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class kl0{fn;delayMs;timeout;pending=!1;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(!this.timeout){this.fn(),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs);return}this.pending=!0,clearTimeout(this.timeout),this.timeout=setTimeout(()=>{if(this.timeout=void 0,this.pending)this.pending=!1,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0;this.pending=!1}}class Ll0{fn;delayMs;timeout;constructor(A,Q){this.fn=A,this.delayMs=Q}trigger(){if(this.timeout)clearTimeout(this.timeout);this.timeout=setTimeout(()=>{this.timeout=void 0,this.fn()},this.delayMs)}dispose(){if(this.timeout)clearTimeout(this.timeout),this.timeout=void 0}}function IC1(A,Q,w,B){let $=new Ll0(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(X){B.error("Git auto-commit failed",{error:X})}})},w),f=["entity:created","entity:updated","entity:deleted"],Y=[];for(let X of f){let H=A.subscribe(X,async()=>{return $.trigger(),{success:!0}});Y.push(H)}return()=>{$.dispose();for(let X of Y)X()}}function FC1(A,Q,w,B,$){if(B<=0)return()=>{};let f=B*60*1000,Y=!1,X=async()=>{if(Y)return;Y=!0;try{let{files:W,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:G}});if(W.length>0)$.info("Periodic sync: pulled changes",{filesChanged:W.length});if(K)$.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(W){$.error("Periodic git sync failed",{error:W})}finally{Y=!1}},H=setInterval(()=>{X()},f);return $.info("Started periodic git sync",{intervalMinutes:B}),()=>{clearInterval(H)}}import{spawnSync as LC1}from"child_process";import{cpSync as EiQ,existsSync as kC1,mkdirSync as TiQ,mkdtempSync as SiQ,rmSync as miQ}from"fs";import{tmpdir as uiQ}from"os";import{fileURLToPath as ciQ}from"url";import{join as liQ,resolve as piQ}from"path";function sI(A,Q){let w=LC1("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let B=w.stderr.toString().trim(),$=w.stdout.toString().trim();throw Error(B||$||`git ${Q.join(" ")} failed`)}}function iiQ(A){return A.startsWith("file://")}function diQ(A){return ciQ(A)}function niQ(A,Q){return LC1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function _C1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!iiQ(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=diQ(A.gitUrl),B=piQ(A.seedContentPath);if(!kC1(B))throw Error(`Seed content path not found: ${B}`);if(!kC1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),TiQ(w,{recursive:!0}),sI(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(niQ(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:B,branch:Q});let $=SiQ(liQ(uiQ(),"directory-sync-seed-"));try{sI($,["init",`--initial-branch=${Q}`]),sI($,["config","user.name",A.authorName??"Brain"]),sI($,["config","user.email",A.authorEmail??"brain@localhost"]),EiQ(B,$,{recursive:!0,filter:(f)=>!f.split("/").includes(".git")}),sI($,["add","."]),sI($,["commit","-m","seed content remote"]),sI($,["remote","add","origin",A.gitUrl]),sI($,["push","-u","origin",Q])}finally{miQ($,{recursive:!0,force:!0})}}function NC1(A,Q,w,B,$,f){let{subscribe:Y}=A.messaging;Y("entity:export:request",async(X)=>{try{return{success:!0,data:await Q().exportEntities(X.payload.entityTypes)}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Export failed"}}}),Y("entity:import:request",async(X)=>{try{let H=Q(),W=X.payload.paths,K=await H.importEntities(W);if(W&&W.length>0)await H.removeOrphanedEntities();return{success:!0,data:K}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let H=await Q().getStatus();return{success:!0,data:{syncPath:H.syncPath,isInitialized:H.exists,watchEnabled:H.watching,lastSync:H.lastSync?.toISOString()??null,totalFiles:H.stats.totalFiles,byEntityType:H.stats.byEntityType,git:await riQ(f?.(),B)}}}catch(X){return{success:!1,error:X instanceof Error?X.message:"Status check failed"}}}),Y("sync:configure:request",async(X)=>{try{return await w({syncPath:X.payload.syncPath}),{success:!0,data:{syncPath:X.payload.syncPath,configured:!0}}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Configuration failed"}}}),Y("git-sync:get-repo-info",async()=>{if(!$?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:$.repo,branch:$.branch??"main"}}}),B.debug("Registered message handlers")}async function riQ(A,Q){if(!A)return null;try{let w=await A.getStatus();return{branch:w.branch,hasChanges:w.hasChanges,ahead:w.ahead,behind:w.behind,lastCommit:w.lastCommit??null,remote:w.remote??null}}catch(w){return Q.debug("Git status unavailable for sync:status:request",{error:w}),null}}wA();L0();wA();L0();function PC1(A,Q){return x6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",Z.object({entityType:Z.string().describe("Entity type (e.g. post, note, link)"),id:Z.string().describe("Entity ID"),sha:Z.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:Z.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let B=`${w.entityType}/${w.id}.md`;try{if(w.sha){let f=await Q.show(w.sha,B);return k5({sha:w.sha,entityType:w.entityType,id:w.id,content:f},`Content at ${w.sha.slice(0,7)}`)}let $=await Q.log(B,w.limit);if($.length===0)return k5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return k5({commits:$,entityType:w.entityType,id:w.id},`${$.length} version${$.length===1?"":"s"} found`)}catch($){return j7($ instanceof Error?$.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function jC1(A,Q,w,B){let $=[x6(w,"sync","Sync brain entities with the filesystem. Use this for refresh, pull, sync, or backup-to-git requests. Pulls from git if configured, then imports files. Git commit and push happen automatically after imports complete.",Z.object({}),async(f,Y)=>{try{let X=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,H={interfaceType:Y.interfaceType,channelId:Y.channelId};if(B){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:X,interfaceType:H.interfaceType,channelId:H.channelId},toolContext:Y});return k5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let W=await A.queueSyncBatch(Q,X,H);if(!W)return k5({gitPulled:!1},"No files to sync");return k5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:!1},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files`)}catch(X){return j7(X instanceof Error?X.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),x6(w,"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.",Z.object({}),async()=>{try{let f=await A.getStatus(),Y={syncPath:f.syncPath,lastSync:f.lastSync?.toISOString(),watching:f.watching};if(B){let X=await B.getStatus();Y.git={isRepo:X.isRepo,branch:X.branch,hasChanges:X.hasChanges,ahead:X.ahead,behind:X.behind,remote:X.remote}}return k5(Y)}catch(f){return j7(f instanceof Error?f.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if(B)$.push(PC1(w,B));return $}var MC1={name:"@brains/directory-sync",version:"0.2.0-alpha.164",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 _l0 extends Aw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",MC1,A,Yn)}requireDirectorySync(){if(!this.directorySync)throw Error("DirectorySync service not initialized");return this.directorySync}hasGitSync(){return this.gitSync!==void 0}async onRegister(A){let{logger:Q,entityService:w}=A;A.templates.register({status:{name:"status",description:"Directory synchronization status",schema:Xn,basePrompt:"",formatter:new p90,requiredPermission:"anchor"}});let B=this.config.syncPath??A.dataDir;this.directorySync=new rd({syncPath:B,autoSync:this.config.autoSync,watchInterval:this.config.watchInterval,includeMetadata:this.config.includeMetadata,entityTypes:this.config.entityTypes,deleteOnFileRemoval:this.config.deleteOnFileRemoval,entityService:w,logger:Q});try{await this.directorySync.initializeDirectory(),this.logger.debug("Directory structure initialized",{path:B})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let $=this.requireDirectorySync();if(UC1(A,$,this.logger,this.config.entityTypes),this.config.autoSync)GC1(A,$,this.config.syncPath??A.dataDir);let f=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!f)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(f&&this.config.git){await _C1({gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,seedContentPath:this.config.seedContentPath,bootstrapFromSeed:this.config.git.bootstrapFromSeed,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail,logger:this.logger.child("ContentRemoteBootstrap")});let Y=this.config.syncPath??A.dataDir;if(this.gitSync=new Dl0({logger:this.logger.child("GitSync"),dataDir:Y,repo:this.config.git.repo,gitUrl:this.config.git.gitUrl,branch:this.config.git.branch,authToken:this.config.git.authToken,authorName:this.config.git.authorName,authorEmail:this.config.git.authorEmail}),await this.gitSync.initialize(),this.logger.info("Git integration enabled",{repo:this.config.git.repo}),A.jobs.registerHandler("sync-request",new r90(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(IC1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(FC1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)JC1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);NC1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return jC1(A,this.getContext(),this.id,this.gitSync)}async onShutdown(){for(let A of this.gitCleanups)A();this.gitCleanups=[],this.directorySync?.stopWatching(),this.gitSync?.cleanup()}getDirectorySync(){return this.directorySync}async configure(A){this.requireDirectorySync();let Q=this.getContext();this.directorySync=new rd({...this.config,syncPath:A.syncPath,entityService:Q.entityService,logger:Q.logger}),await this.directorySync.initialize(),this.logger.info("Directory sync reconfigured",{path:A.syncPath})}async registerJobHandlers(A){KC1(A,this.requireDirectorySync(),this.logger)}}function UP(A={}){return new _l0(A)}wA();L0();var xC1={name:"@brains/email-resend",version:"0.2.0-alpha.164",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 aiQ=Z.object({apiKey:Z.string().min(1).optional(),from:Z.string().min(1).optional()}),tiQ=Z.looseObject({id:Z.string().optional()});class OC1 extends Aw{fetchImpl;constructor(A={},Q={}){super("email-resend",xC1,A,aiQ);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(AB0,async(w)=>{let B=OyA.parse(w.payload);try{return{success:!0,data:await this.sendWithResend(B)}}catch($){if(B.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:B.to,subject:B.subject,error:$ instanceof Error?$.message:String($)});return{success:!1,error:"Email delivery failed"}}})}async sendWithResend(A){let Q=this.config.apiKey,w=this.config.from;if(!Q||!w)return{status:"failed"};let B=await this.fetchImpl("https://api.resend.com/emails",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({from:w,to:A.to,subject:A.subject,text:A.text,...A.html?{html:A.html}:{}})});if(!B.ok)throw Error("Resend email request failed");let $=tiQ.parse(await B.json());return $.id?{status:"sent",id:$.id}:{status:"sent"}}}function e90(A={}){return new OC1(A)}wA();import{render as qs1}from"preact-render-to-string";import{h as rP}from"preact";function vC1(A){var Q,w,B="";if(typeof A=="string"||typeof A=="number")B+=A;else if(typeof A=="object")if(Array.isArray(A)){var $=A.length;for(Q=0;Q<$;Q++)A[Q]&&(w=vC1(A[Q]))&&(B&&(B+=" "),B+=w)}else for(w in A)A[w]&&(B&&(B+=" "),B+=w);return B}function Qg(){for(var A,Q,w=0,B="",$=arguments.length;w<$;w++)(A=arguments[w])&&(Q=vC1(A))&&(B&&(B+=" "),B+=Q);return B}var eiQ=(A,Q)=>{let w=Array(A.length+Q.length);for(let B=0;B<A.length;B++)w[B]=A[B];for(let B=0;B<Q.length;B++)w[A.length+B]=Q[B];return w},AdQ=(A,Q)=>({classGroupId:A,validator:Q}),SC1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var RC1=[];var QdQ=(A)=>{let Q=BdQ(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:B}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return wdQ(Y);let X=Y.split("-"),H=X[0]===""&&X.length>1?1:0;return mC1(X,H,Q)},getConflictingClassGroupIds:(Y,X)=>{if(X){let H=B[Y],W=w[Y];if(H){if(W)return eiQ(W,H);return H}return W||RC1}return w[Y]||RC1}}},mC1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let $=A[Q],f=w.nextPart.get($);if(f){let W=mC1(A,Q+1,f);if(W)return W}let Y=w.validators;if(Y===null)return;let X=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let W=0;W<H;W++){let K=Y[W];if(K.validator(X))return K.classGroupId}return},wdQ=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),B=Q.slice(0,w);return B?"arbitrary.."+B:void 0})(),BdQ=(A)=>{let{theme:Q,classGroups:w}=A;return $dQ(w,Q)},$dQ=(A,Q)=>{let w=SC1();for(let B in A){let $=A[B];jl0($,w,B,Q)}return w},jl0=(A,Q,w,B)=>{let $=A.length;for(let f=0;f<$;f++){let Y=A[f];fdQ(Y,Q,w,B)}},fdQ=(A,Q,w,B)=>{if(typeof A==="string"){YdQ(A,Q,w);return}if(typeof A==="function"){XdQ(A,Q,w,B);return}ZdQ(A,Q,w,B)},YdQ=(A,Q,w)=>{let B=A===""?Q:uC1(Q,A);B.classGroupId=w},XdQ=(A,Q,w,B)=>{if(HdQ(A)){jl0(A(B),Q,w,B);return}if(Q.validators===null)Q.validators=[];Q.validators.push(AdQ(w,A))},ZdQ=(A,Q,w,B)=>{let $=Object.entries(A),f=$.length;for(let Y=0;Y<f;Y++){let[X,H]=$[Y];jl0(H,uC1(Q,X),w,B)}},uC1=(A,Q)=>{let w=A,B=Q.split("-"),$=B.length;for(let f=0;f<$;f++){let Y=B[f],X=w.nextPart.get(Y);if(!X)X=SC1(),w.nextPart.set(Y,X);w=X}return w},HdQ=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,WdQ=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),B=Object.create(null),$=(f,Y)=>{if(w[f]=Y,Q++,Q>A)Q=0,B=w,w=Object.create(null)};return{get(f){let Y=w[f];if(Y!==void 0)return Y;if((Y=B[f])!==void 0)return $(f,Y),Y},set(f,Y){if(f in w)w[f]=Y;else $(f,Y)}}};var KdQ=[],hC1=(A,Q,w,B,$)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:B,isExternal:$}),UdQ=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,B=($)=>{let f=[],Y=0,X=0,H=0,W,K=$.length;for(let J=0;J<K;J++){let V=$[J];if(Y===0&&X===0){if(V===":"){f.push($.slice(H,J)),H=J+1;continue}if(V==="/"){W=J;continue}}if(V==="[")Y++;else if(V==="]")Y--;else if(V==="(")X++;else if(V===")")X--}let U=f.length===0?$:$.slice(H),G=U,q=!1;if(U.endsWith("!"))G=U.slice(0,-1),q=!0;else if(U.startsWith("!"))G=U.slice(1),q=!0;let b=W&&W>H?W-H:void 0;return hC1(f,q,G,b)};if(Q){let $=Q+":",f=B;B=(Y)=>Y.startsWith($)?f(Y.slice($.length)):hC1(KdQ,!1,Y,void 0,!0)}if(w){let $=B;B=(f)=>w({className:f,parseClassName:$})}return B},GdQ=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,B)=>{Q.set(w,1e6+B)}),(w)=>{let B=[],$=[];for(let f=0;f<w.length;f++){let Y=w[f],X=Y[0]==="[",H=Q.has(Y);if(X||H){if($.length>0)$.sort(),B.push(...$),$=[];B.push(Y)}else $.push(Y)}if($.length>0)$.sort(),B.push(...$);return B}},DdQ=(A)=>({cache:WdQ(A.cacheSize),parseClassName:UdQ(A),sortModifiers:GdQ(A),postfixLookupClassGroupIds:zdQ(A),...QdQ(A)}),zdQ=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let B=0;B<w.length;B++)Q[w[B]]=!0;return Q},qdQ=/\s+/,bdQ=(A,Q)=>{let{parseClassName:w,getClassGroupId:B,getConflictingClassGroupIds:$,sortModifiers:f,postfixLookupClassGroupIds:Y}=Q,X=[],H=A.trim().split(qdQ),W="";for(let K=H.length-1;K>=0;K-=1){let U=H[K],{isExternal:G,modifiers:q,hasImportantModifier:b,baseClassName:J,maybePostfixModifierPosition:V}=w(U);if(G){W=U+(W.length>0?" "+W:W);continue}let k=!!V,N;if(k){let j=J.substring(0,V);N=B(j);let E=N&&Y[N]?B(J):void 0;if(E&&E!==N)N=E,k=!1}else N=B(J);if(!N){if(!k){W=U+(W.length>0?" "+W:W);continue}if(N=B(J),!N){W=U+(W.length>0?" "+W:W);continue}k=!1}let L=q.length===0?"":q.length===1?q[0]:f(q).join(":"),O=b?L+"!":L,v=O+N;if(X.indexOf(v)>-1)continue;X.push(v);let h=$(N,k);for(let j=0;j<h.length;++j){let E=h[j];X.push(O+E)}W=U+(W.length>0?" "+W:W)}return W},VdQ=(...A)=>{let Q=0,w,B,$="";while(Q<A.length)if(w=A[Q++]){if(B=cC1(w))$&&($+=" "),$+=B}return $},cC1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let B=0;B<A.length;B++)if(A[B]){if(Q=cC1(A[B]))w&&(w+=" "),w+=Q}return w},CC1=(A,...Q)=>{let w,B,$,f,Y=(H)=>{let W=Q.reduce((K,U)=>U(K),A());return w=DdQ(W),B=w.cache.get,$=w.cache.set,f=X,X(H)},X=(H)=>{let W=B(H);if(W)return W;let K=bdQ(H,w);return $(H,K),K};return f=Y,(...H)=>f(VdQ(...H))},JdQ=[],k9=(A)=>{let Q=(w)=>w[A]||JdQ;return Q.isThemeGetter=!0,Q},lC1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,pC1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,IdQ=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,FdQ=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,kdQ=/\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$/,LdQ=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,_dQ=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,NdQ=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,aI=(A)=>IdQ.test(A),Ew=(A)=>!!A&&!Number.isNaN(Number(A)),jD=(A)=>!!A&&Number.isInteger(Number(A)),Nl0=(A)=>A.endsWith("%")&&Ew(A.slice(0,-1)),Eq=(A)=>FdQ.test(A),iC1=()=>!0,PdQ=(A)=>kdQ.test(A)&&!LdQ.test(A),Ml0=()=>!1,jdQ=(A)=>_dQ.test(A),MdQ=(A)=>NdQ.test(A),xdQ=(A)=>!k2(A)&&!P2(A),OdQ=(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)),vdQ=(A)=>tI(A,rC1,Ml0),k2=(A)=>lC1.test(A),GP=(A)=>tI(A,oC1,PdQ),gC1=(A)=>tI(A,SdQ,Ew),RdQ=(A)=>tI(A,aC1,iC1),hdQ=(A)=>tI(A,sC1,Ml0),yC1=(A)=>tI(A,dC1,Ml0),CdQ=(A)=>tI(A,nC1,MdQ),A70=(A)=>tI(A,tC1,jdQ),P2=(A)=>pC1.test(A),Zn=(A)=>DP(A,oC1),gdQ=(A)=>DP(A,sC1),EC1=(A)=>DP(A,dC1),ydQ=(A)=>DP(A,rC1),EdQ=(A)=>DP(A,nC1),Q70=(A)=>DP(A,tC1,!0),TdQ=(A)=>DP(A,aC1,!0),tI=(A,Q,w)=>{let B=lC1.exec(A);if(B){if(B[1])return Q(B[1]);return w(B[2])}return!1},DP=(A,Q,w=!1)=>{let B=pC1.exec(A);if(B){if(B[1])return Q(B[1]);return w}return!1},dC1=(A)=>A==="position"||A==="percentage",nC1=(A)=>A==="image"||A==="url",rC1=(A)=>A==="length"||A==="size"||A==="bg-size",oC1=(A)=>A==="length",SdQ=(A)=>A==="number",sC1=(A)=>A==="family-name",aC1=(A)=>A==="number"||A==="weight",tC1=(A)=>A==="shadow";var TC1=()=>{let A=k9("color"),Q=k9("font"),w=k9("text"),B=k9("font-weight"),$=k9("tracking"),f=k9("leading"),Y=k9("breakpoint"),X=k9("container"),H=k9("spacing"),W=k9("radius"),K=k9("shadow"),U=k9("inset-shadow"),G=k9("text-shadow"),q=k9("drop-shadow"),b=k9("blur"),J=k9("perspective"),V=k9("aspect"),k=k9("ease"),N=k9("animate"),L=()=>["auto","avoid","all","avoid-page","page","left","right","column"],O=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],v=()=>[...O(),P2,k2],h=()=>["auto","hidden","clip","visible","scroll"],j=()=>["auto","contain","none"],E=()=>[P2,k2,H],S=()=>[aI,"full","auto",...E()],p=()=>[jD,"none","subgrid",P2,k2],e=()=>["auto",{span:["full",jD,P2,k2]},jD,P2,k2],Y0=()=>[jD,"auto",P2,k2],l=()=>["auto","min","max","fr",P2,k2],P=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...E()],n=()=>[aI,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...E()],o=()=>[aI,"screen","full","dvw","lvw","svw","min","max","fit",...E()],K0=()=>[aI,"screen","full","lh","dvh","lvh","svh","min","max","fit",...E()],c=()=>[A,P2,k2],X0=()=>[...O(),EC1,yC1,{position:[P2,k2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],w0=()=>["auto","cover","contain",ydQ,vdQ,{size:[P2,k2]}],h0=()=>[Nl0,Zn,GP],S0=()=>["","none","full",W,P2,k2],V0=()=>["",Ew,Zn,GP],J0=()=>["solid","dashed","dotted","double"],P0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],C0=()=>[Ew,Nl0,EC1,yC1],_0=()=>["","none",b,P2,k2],N0=()=>["none",Ew,P2,k2],j0=()=>["none",Ew,P2,k2],M0=()=>[Ew,P2,k2],T0=()=>[aI,"full",...E()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Eq],breakpoint:[Eq],color:[iC1],container:[Eq],"drop-shadow":[Eq],ease:["in","out","in-out"],font:[xdQ],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Eq],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Eq],shadow:[Eq],spacing:["px",Ew],text:[Eq],"text-shadow":[Eq],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",aI,k2,P2,V]}],container:["container"],"container-type":[{"@container":["","normal","size",P2,k2]}],"container-named":[OdQ],columns:[{columns:[Ew,k2,P2,X]}],"break-after":[{"break-after":L()}],"break-before":[{"break-before":L()}],"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:h()}],"overflow-x":[{"overflow-x":h()}],"overflow-y":[{"overflow-y":h()}],overscroll:[{overscroll:j()}],"overscroll-x":[{"overscroll-x":j()}],"overscroll-y":[{"overscroll-y":j()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:S()}],"inset-x":[{"inset-x":S()}],"inset-y":[{"inset-y":S()}],start:[{"inset-s":S(),start:S()}],end:[{"inset-e":S(),end:S()}],"inset-bs":[{"inset-bs":S()}],"inset-be":[{"inset-be":S()}],top:[{top:S()}],right:[{right:S()}],bottom:[{bottom:S()}],left:[{left:S()}],visibility:["visible","invisible","collapse"],z:[{z:[jD,"auto",P2,k2]}],basis:[{basis:[aI,"full","auto",X,...E()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[Ew,aI,"auto","initial","none",k2]}],grow:[{grow:["",Ew,P2,k2]}],shrink:[{shrink:["",Ew,P2,k2]}],order:[{order:[jD,"first","last","none",P2,k2]}],"grid-cols":[{"grid-cols":p()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":Y0()}],"col-end":[{"col-end":Y0()}],"grid-rows":[{"grid-rows":p()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":Y0()}],"row-end":[{"row-end":Y0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:E()}],"gap-x":[{"gap-x":E()}],"gap-y":[{"gap-y":E()}],"justify-content":[{justify:[...P(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...P()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":P()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:E()}],px:[{px:E()}],py:[{py:E()}],ps:[{ps:E()}],pe:[{pe:E()}],pbs:[{pbs:E()}],pbe:[{pbe:E()}],pt:[{pt:E()}],pr:[{pr:E()}],pb:[{pb:E()}],pl:[{pl:E()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":E()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":E()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...o()]}],"min-inline-size":[{"min-inline":["auto",...o()]}],"max-inline-size":[{"max-inline":["none",...o()]}],"block-size":[{block:["auto",...K0()]}],"min-block-size":[{"min-block":["auto",...K0()]}],"max-block-size":[{"max-block":["none",...K0()]}],w:[{w:[X,"screen",...n()]}],"min-w":[{"min-w":[X,"screen","none",...n()]}],"max-w":[{"max-w":[X,"screen","none","prose",{screen:[Y]},...n()]}],h:[{h:["screen","lh",...n()]}],"min-h":[{"min-h":["screen","lh","none",...n()]}],"max-h":[{"max-h":["screen","lh",...n()]}],"font-size":[{text:["base",w,Zn,GP]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[B,TdQ,RdQ]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",Nl0,k2]}],"font-family":[{font:[gdQ,hdQ,Q]}],"font-features":[{"font-features":[k2]}],"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:[$,P2,k2]}],"line-clamp":[{"line-clamp":[Ew,"none",P2,gC1]}],leading:[{leading:[f,...E()]}],"list-image":[{"list-image":["none",P2,k2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",P2,k2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:c()}],"text-color":[{text:c()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...J0(),"wavy"]}],"text-decoration-thickness":[{decoration:[Ew,"from-font","auto",P2,GP]}],"text-decoration-color":[{decoration:c()}],"underline-offset":[{"underline-offset":[Ew,"auto",P2,k2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:E()}],"tab-size":[{tab:[jD,P2,k2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",P2,k2]}],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",P2,k2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:X0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:w0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},jD,P2,k2],radial:["",P2,k2],conic:[jD,P2,k2]},EdQ,CdQ]}],"bg-color":[{bg:c()}],"gradient-from-pos":[{from:h0()}],"gradient-via-pos":[{via:h0()}],"gradient-to-pos":[{to:h0()}],"gradient-from":[{from:c()}],"gradient-via":[{via:c()}],"gradient-to":[{to:c()}],rounded:[{rounded:S0()}],"rounded-s":[{"rounded-s":S0()}],"rounded-e":[{"rounded-e":S0()}],"rounded-t":[{"rounded-t":S0()}],"rounded-r":[{"rounded-r":S0()}],"rounded-b":[{"rounded-b":S0()}],"rounded-l":[{"rounded-l":S0()}],"rounded-ss":[{"rounded-ss":S0()}],"rounded-se":[{"rounded-se":S0()}],"rounded-ee":[{"rounded-ee":S0()}],"rounded-es":[{"rounded-es":S0()}],"rounded-tl":[{"rounded-tl":S0()}],"rounded-tr":[{"rounded-tr":S0()}],"rounded-br":[{"rounded-br":S0()}],"rounded-bl":[{"rounded-bl":S0()}],"border-w":[{border:V0()}],"border-w-x":[{"border-x":V0()}],"border-w-y":[{"border-y":V0()}],"border-w-s":[{"border-s":V0()}],"border-w-e":[{"border-e":V0()}],"border-w-bs":[{"border-bs":V0()}],"border-w-be":[{"border-be":V0()}],"border-w-t":[{"border-t":V0()}],"border-w-r":[{"border-r":V0()}],"border-w-b":[{"border-b":V0()}],"border-w-l":[{"border-l":V0()}],"divide-x":[{"divide-x":V0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":V0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...J0(),"hidden","none"]}],"divide-style":[{divide:[...J0(),"hidden","none"]}],"border-color":[{border:c()}],"border-color-x":[{"border-x":c()}],"border-color-y":[{"border-y":c()}],"border-color-s":[{"border-s":c()}],"border-color-e":[{"border-e":c()}],"border-color-bs":[{"border-bs":c()}],"border-color-be":[{"border-be":c()}],"border-color-t":[{"border-t":c()}],"border-color-r":[{"border-r":c()}],"border-color-b":[{"border-b":c()}],"border-color-l":[{"border-l":c()}],"divide-color":[{divide:c()}],"outline-style":[{outline:[...J0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[Ew,P2,k2]}],"outline-w":[{outline:["",Ew,Zn,GP]}],"outline-color":[{outline:c()}],shadow:[{shadow:["","none",K,Q70,A70]}],"shadow-color":[{shadow:c()}],"inset-shadow":[{"inset-shadow":["none",U,Q70,A70]}],"inset-shadow-color":[{"inset-shadow":c()}],"ring-w":[{ring:V0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:c()}],"ring-offset-w":[{"ring-offset":[Ew,GP]}],"ring-offset-color":[{"ring-offset":c()}],"inset-ring-w":[{"inset-ring":V0()}],"inset-ring-color":[{"inset-ring":c()}],"text-shadow":[{"text-shadow":["none",G,Q70,A70]}],"text-shadow-color":[{"text-shadow":c()}],opacity:[{opacity:[Ew,P2,k2]}],"mix-blend":[{"mix-blend":[...P0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":P0()}],"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":[Ew]}],"mask-image-linear-from-pos":[{"mask-linear-from":C0()}],"mask-image-linear-to-pos":[{"mask-linear-to":C0()}],"mask-image-linear-from-color":[{"mask-linear-from":c()}],"mask-image-linear-to-color":[{"mask-linear-to":c()}],"mask-image-t-from-pos":[{"mask-t-from":C0()}],"mask-image-t-to-pos":[{"mask-t-to":C0()}],"mask-image-t-from-color":[{"mask-t-from":c()}],"mask-image-t-to-color":[{"mask-t-to":c()}],"mask-image-r-from-pos":[{"mask-r-from":C0()}],"mask-image-r-to-pos":[{"mask-r-to":C0()}],"mask-image-r-from-color":[{"mask-r-from":c()}],"mask-image-r-to-color":[{"mask-r-to":c()}],"mask-image-b-from-pos":[{"mask-b-from":C0()}],"mask-image-b-to-pos":[{"mask-b-to":C0()}],"mask-image-b-from-color":[{"mask-b-from":c()}],"mask-image-b-to-color":[{"mask-b-to":c()}],"mask-image-l-from-pos":[{"mask-l-from":C0()}],"mask-image-l-to-pos":[{"mask-l-to":C0()}],"mask-image-l-from-color":[{"mask-l-from":c()}],"mask-image-l-to-color":[{"mask-l-to":c()}],"mask-image-x-from-pos":[{"mask-x-from":C0()}],"mask-image-x-to-pos":[{"mask-x-to":C0()}],"mask-image-x-from-color":[{"mask-x-from":c()}],"mask-image-x-to-color":[{"mask-x-to":c()}],"mask-image-y-from-pos":[{"mask-y-from":C0()}],"mask-image-y-to-pos":[{"mask-y-to":C0()}],"mask-image-y-from-color":[{"mask-y-from":c()}],"mask-image-y-to-color":[{"mask-y-to":c()}],"mask-image-radial":[{"mask-radial":[P2,k2]}],"mask-image-radial-from-pos":[{"mask-radial-from":C0()}],"mask-image-radial-to-pos":[{"mask-radial-to":C0()}],"mask-image-radial-from-color":[{"mask-radial-from":c()}],"mask-image-radial-to-color":[{"mask-radial-to":c()}],"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":O()}],"mask-image-conic-pos":[{"mask-conic":[Ew]}],"mask-image-conic-from-pos":[{"mask-conic-from":C0()}],"mask-image-conic-to-pos":[{"mask-conic-to":C0()}],"mask-image-conic-from-color":[{"mask-conic-from":c()}],"mask-image-conic-to-color":[{"mask-conic-to":c()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:X0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:w0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",P2,k2]}],filter:[{filter:["","none",P2,k2]}],blur:[{blur:_0()}],brightness:[{brightness:[Ew,P2,k2]}],contrast:[{contrast:[Ew,P2,k2]}],"drop-shadow":[{"drop-shadow":["","none",q,Q70,A70]}],"drop-shadow-color":[{"drop-shadow":c()}],grayscale:[{grayscale:["",Ew,P2,k2]}],"hue-rotate":[{"hue-rotate":[Ew,P2,k2]}],invert:[{invert:["",Ew,P2,k2]}],saturate:[{saturate:[Ew,P2,k2]}],sepia:[{sepia:["",Ew,P2,k2]}],"backdrop-filter":[{"backdrop-filter":["","none",P2,k2]}],"backdrop-blur":[{"backdrop-blur":_0()}],"backdrop-brightness":[{"backdrop-brightness":[Ew,P2,k2]}],"backdrop-contrast":[{"backdrop-contrast":[Ew,P2,k2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",Ew,P2,k2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[Ew,P2,k2]}],"backdrop-invert":[{"backdrop-invert":["",Ew,P2,k2]}],"backdrop-opacity":[{"backdrop-opacity":[Ew,P2,k2]}],"backdrop-saturate":[{"backdrop-saturate":[Ew,P2,k2]}],"backdrop-sepia":[{"backdrop-sepia":["",Ew,P2,k2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":E()}],"border-spacing-x":[{"border-spacing-x":E()}],"border-spacing-y":[{"border-spacing-y":E()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",P2,k2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[Ew,"initial",P2,k2]}],ease:[{ease:["linear","initial",k,P2,k2]}],delay:[{delay:[Ew,P2,k2]}],animate:[{animate:["none",N,P2,k2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[J,P2,k2]}],"perspective-origin":[{"perspective-origin":v()}],rotate:[{rotate:N0()}],"rotate-x":[{"rotate-x":N0()}],"rotate-y":[{"rotate-y":N0()}],"rotate-z":[{"rotate-z":N0()}],scale:[{scale:j0()}],"scale-x":[{"scale-x":j0()}],"scale-y":[{"scale-y":j0()}],"scale-z":[{"scale-z":j0()}],"scale-3d":["scale-3d"],skew:[{skew:M0()}],"skew-x":[{"skew-x":M0()}],"skew-y":[{"skew-y":M0()}],transform:[{transform:[P2,k2,"","none","gpu","cpu"]}],"transform-origin":[{origin:v()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:T0()}],"translate-x":[{"translate-x":T0()}],"translate-y":[{"translate-y":T0()}],"translate-z":[{"translate-z":T0()}],"translate-none":["translate-none"],zoom:[{zoom:[jD,P2,k2]}],accent:[{accent:c()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:c()}],"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",P2,k2]}],"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":c()}],"scrollbar-track-color":[{"scrollbar-track":c()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":E()}],"scroll-mx":[{"scroll-mx":E()}],"scroll-my":[{"scroll-my":E()}],"scroll-ms":[{"scroll-ms":E()}],"scroll-me":[{"scroll-me":E()}],"scroll-mbs":[{"scroll-mbs":E()}],"scroll-mbe":[{"scroll-mbe":E()}],"scroll-mt":[{"scroll-mt":E()}],"scroll-mr":[{"scroll-mr":E()}],"scroll-mb":[{"scroll-mb":E()}],"scroll-ml":[{"scroll-ml":E()}],"scroll-p":[{"scroll-p":E()}],"scroll-px":[{"scroll-px":E()}],"scroll-py":[{"scroll-py":E()}],"scroll-ps":[{"scroll-ps":E()}],"scroll-pe":[{"scroll-pe":E()}],"scroll-pbs":[{"scroll-pbs":E()}],"scroll-pbe":[{"scroll-pbe":E()}],"scroll-pt":[{"scroll-pt":E()}],"scroll-pr":[{"scroll-pr":E()}],"scroll-pb":[{"scroll-pb":E()}],"scroll-pl":[{"scroll-pl":E()}],"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",P2,k2]}],fill:[{fill:["none",...c()]}],"stroke-w":[{stroke:[Ew,Zn,GP,gC1]}],stroke:[{stroke:["none",...c()]}],"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"]}},mdQ=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:B,extend:$={},override:f={}})=>{return wg(A,"cacheSize",Q),wg(A,"prefix",w),wg(A,"experimentalParseClassName",B),w70(A.theme,f.theme),w70(A.classGroups,f.classGroups),w70(A.conflictingClassGroups,f.conflictingClassGroups),w70(A.conflictingClassGroupModifiers,f.conflictingClassGroupModifiers),wg(A,"postfixLookupClassGroups",f.postfixLookupClassGroups),wg(A,"orderSensitiveModifiers",f.orderSensitiveModifiers),B70(A.theme,$.theme),B70(A.classGroups,$.classGroups),B70(A.conflictingClassGroups,$.conflictingClassGroups),B70(A.conflictingClassGroupModifiers,$.conflictingClassGroupModifiers),Pl0(A,$,"postfixLookupClassGroups"),Pl0(A,$,"orderSensitiveModifiers"),A},wg=(A,Q,w)=>{if(w!==void 0)A[Q]=w},w70=(A,Q)=>{if(Q)for(let w in Q)wg(A,w,Q[w])},B70=(A,Q)=>{if(Q)for(let w in Q)Pl0(A,Q,w)},Pl0=(A,Q,w)=>{let B=Q[w];if(B!==void 0)A[w]=A[w]?A[w].concat(B):B},$70=(A,...Q)=>typeof A==="function"?CC1(TC1,A,...Q):CC1(()=>mdQ(TC1(),A),...Q);var udQ=$70({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 j2(...A){return udQ(Qg(A))}var eC1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,Ag1=Qg,LB=(A,Q)=>(w)=>{var B;if((Q===null||Q===void 0?void 0:Q.variants)==null)return Ag1(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:$,defaultVariants:f}=Q,Y=Object.keys($).map((W)=>{let K=w===null||w===void 0?void 0:w[W],U=f===null||f===void 0?void 0:f[W];if(K===null)return null;let G=eC1(K)||eC1(U);return $[W][G]}),X=w&&Object.entries(w).reduce((W,K)=>{let[U,G]=K;if(G===void 0)return W;return W[U]=G,W},{}),H=Q===null||Q===void 0?void 0:(B=Q.compoundVariants)===null||B===void 0?void 0:B.reduce((W,K)=>{let{class:U,className:G,...q}=K;return Object.entries(q).every((b)=>{let[J,V]=b;return Array.isArray(V)?V.includes({...f,...X}[J]):{...f,...X}[J]===V})?[...W,U,G]:W},[]);return Ag1(A,Y,H,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as xl0}from"preact/jsx-dev-runtime";var Qg1=LB("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 Ol0({variant:A,title:Q,children:w,className:B}){return xl0("div",{className:j2(Qg1({variant:A}),B),role:"alert",children:[Q&&xl0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),xl0("div",{className:j2(Q&&"mt-1","text-sm text-current opacity-75"),children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as cdQ}from"preact/jsx-dev-runtime";var wg1=LB("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 zP({variant:A,size:Q,className:w,children:B,ssrOnClick:$,type:f="button",...Y}){return cdQ("button",{type:f,className:j2(wg1({variant:A,size:Q}),w),...Y,...$&&{onclick:$},children:B},void 0,!1,void 0,this)}import{jsxDEV as ldQ}from"preact/jsx-dev-runtime";var Bg1=LB("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 L9({href:A,children:Q,variant:w,size:B,external:$=!1,className:f,"aria-label":Y}){let X=$?{target:"_blank",rel:"noopener noreferrer"}:{};return ldQ("a",{href:A,className:j2(Bg1({variant:w,size:B}),f),"aria-label":Y,...X,children:Q},void 0,!1,void 0,this)}import{jsxDEV as f70}from"preact/jsx-dev-runtime";var $g1=LB("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"}}),pdQ={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Bg({variant:A,size:Q,className:w}){let B=pdQ[Q??"md"];return f70("button",{onclick:"toggleTheme()",type:"button",className:j2($g1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:f70("svg",{className:j2(B,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[f70("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),f70("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 vl0}from"preact/jsx-dev-runtime";var fg1=LB("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function Y70({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:B,children:$}){if(A.length===0&&!$)return null;let f=[...A].sort((Y,X)=>Y.priority-X.priority);return vl0("ul",{className:j2(fg1({orientation:B}),Q),children:[f.map((Y)=>vl0("li",{children:vl0("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),$]},void 0,!0,void 0,this)}import{jsxDEV as vyB}from"preact/jsx-dev-runtime";import{jsxDEV as CyB}from"preact/jsx-dev-runtime";import{createContext as idQ,h as ddQ}from"preact";import{useContext as ndQ}from"preact/hooks";var Rl0=idQ(null);function $g({headCollector:A,children:Q}){return ddQ(Rl0.Provider,{value:A},Q)}function Yg1(){return ndQ(Rl0)}function dQ(A){let Q=Yg1();if(Q)Q.setHeadProps(A);return null}import{createContext as _eQ,h as NeQ}from"preact";import{useContext as PeQ}from"preact/hooks";Cj0();var qS1=Z1(zS1(),1),keQ=new Aw0({gfm:!0,breaks:!0}),LeQ={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 Bi0(A,Q){let{imageRenderer:w}=Q??{},$=(w?new Aw0({gfm:!0,breaks:!0}).use({renderer:{image({href:f,title:Y,text:X}){return w(f,Y,X)??!1}}}):keQ).parse(A);return $=$.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5762
5762
|
<cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),qS1.default($,LeQ)}var bS1=_eQ(null);function Fg({imageRenderer:A,children:Q}){return NeQ(bS1.Provider,{value:A??null},Q)}function VS1(){return PeQ(bS1)}function iq(){let A=VS1();return(Q)=>Bi0(Q,A?{imageRenderer:A}:void 0)}var jeQ=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,MeQ={"&":"&","<":"<",">":">",""":'"',"'":"'"},xeQ=/&(?:amp|lt|gt|quot|#39);/g;function OeQ(A){return A.replace(xeQ,(Q)=>MeQ[Q]??Q)}function $i0(A){return A.replace(jeQ,(Q,w)=>{return`<div class="mermaid">${OeQ(w)}</div>`})}var JS1=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function IS1(A){let Q={};for(let B of A.matchAll(JS1)){let $=B[1]??"";for(let Y of $.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let X=Y[1],H=Y[2];if(X&&H!==void 0)Q[X]=H}let f=$.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(f)for(let Y of f.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let X=Y[1];if(X)Q[X]="true"}}let w=A.replace(JS1,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
|
|
5763
5763
|
|
|
5764
5764
|
`).trim();return{attributes:Q,markdown:w}}var veQ=/<!--\s*\.break\s*-->/;function FS1(A){let Q=A.split(veQ);return Q.length>1?Q:null}import{jsxDEV as CD}from"preact/jsx-dev-runtime";var fi0=({markdown:A,deck:Q})=>{let w=iq(),$=A.split(/^---$/gm).map((K)=>K.trim()).map((K)=>{let{attributes:U,markdown:G}=IS1(K),q=FS1(G),b;if(q)b=`<div class="slide-columns">${q.map((V)=>`<div class="slide-column">${$i0(w(V.trim()))}</div>`).join("")}</div>`;else b=$i0(w(G));return{attributes:U,htmlContent:b}}),f=$.some((K)=>K.htmlContent.includes('class="mermaid"')),Y=Q?.frontmatter?.title??Q?.metadata?.title,X=Q?.frontmatter?.description??Q?.metadata?.description,H=Q?.ogImageUrl??Q?.coverImageUrl,W=$.map(({attributes:K,htmlContent:U},G)=>CD("section",{...K,dangerouslySetInnerHTML:{__html:U}},G,!1,void 0,this));return CD("section",{className:"presentation-section",children:[Y&&CD(dQ,{title:Y,...X?{description:X}:{},...H?{ogImage:H}:{},ogType:"article"},void 0,!1,void 0,this),CD("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),CD("div",{className:"reveal",children:CD("div",{className:"slides",children:W},void 0,!1,void 0,this)},void 0,!1,void 0,this),CD("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),f&&CD("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),CD("script",{dangerouslySetInnerHTML:{__html:`
|
|
@@ -6745,13 +6745,13 @@ ${A.map((f)=>({url:`${Q}${f.path}`,lastmod:w,changefreq:f.path==="/"?"daily":"we
|
|
|
6745
6745
|
`+$:w,Y=dD(this.outputDir,"styles","main.css");await this.cssProcessor.process(f,Y,this.workingDir,this.outputDir,this.logger);let X=await i7.readFile(Y,"utf-8"),H=B.length>0?B:Q;if(H.length>0){let W=H.join(`
|
|
6746
6746
|
`)+`
|
|
6747
6747
|
|
|
6748
|
-
`+X;await i7.writeFile(Y,W,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=dD(process.cwd(),"public");try{await i7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await i7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=dD(A,w.name),$=dD(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await i7.copyFile(B,$),this.logger.debug(`Copied static asset: ${w.name}`)}this.logger.debug("Static assets copied successfully")}async writeInlineStaticAssets(A){if(!A)return;let Q=Object.entries(A);if(Q.length===0)return;this.logger.debug(`Writing ${Q.length} inline static asset(s) from SitePackage`),await Promise.all(Q.map(async([w,B])=>{let $=w.startsWith("/")?w.slice(1):w,f=dD(this.outputDir,$);await i7.mkdir(KZw(f),{recursive:!0}),await i7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await i7.mkdir(Q,{recursive:!0});let w=await i7.readdir(A,{withFileTypes:!0});for(let B of w){let $=dD(A,B.name),f=dD(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await i7.copyFile($,f)}}}function Br0(A){return new Vs1(A)}w9();L0();L0();var UZw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),GZw=Z.object({blurb:Z.string().optional()}),Qy=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:UZw.optional(),sections:Z.record(Z.string(),GZw).optional()});var Js1=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:Qy,layouts:Z.record(Z.string(),Z.any()),themeCSS:Z.string().optional()}),IoB=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});function Is1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function Fs1(A,Q,w){let B=Q.getProfile(),$=w.getNavigationItems("primary"),f=w.getNavigationItems("secondary");return{...A,...B.socialLinks!==void 0&&{socialLinks:B.socialLinks},navigation:{primary:$,secondary:f},copyright:A.copyright??"Powered by Rizom"}}w9();_4();w9();D2();L0();var DZw=Z.looseObject({id:Z.string(),entityType:Z.string(),content:Z.string(),metadata:Z.looseObject({slug:Z.string()})}),zZw=Z.looseObject({content:Z.string(),metadata:Z.looseObject({width:Z.number().optional(),height:Z.number().optional()})});async function yf0(A,Q){let w=Q.urlGenerator??K4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((O)=>yf0(O,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,O])=>yf0(O,{...Q,urlGenerator:w})));for(let O=0;O<$.length;O++){let v=$[O];if(v)B[v[0]]=f[O]}let Y=DZw.safeParse(A);if(!Y.success)return B;let X=Y.data,H=X.entityType,W=X.metadata.slug,K=Q.pipelineContext.entityDisplay?.[H],U=K?K.label:H.charAt(0).toUpperCase()+H.slice(1),G=K?K.pluralName??K.label.toLowerCase()+"s":wK(H),q=`/${G}`,b=G.charAt(0).toUpperCase()+G.slice(1),J=Tu(X),V=await qZw(J,Q),k=M20(X)??J,N=await bZw(k,Q);return{...B,...X,url:w.generateUrl(H,W),typeLabel:U,listUrl:q,listLabel:b,...V,...N&&{ogImageUrl:N}}}async function qZw(A,Q){let w=A?Q.imageBuildService?.get(A):void 0;if(w)return{coverImageUrl:w.src,coverImageWidth:w.width,coverImageHeight:w.height,...w.srcset&&{coverImageSrcset:w.srcset,coverImageSizes:w.sizes}};let B=await Ls1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function bZw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return ks1(w.src,Q.siteUrl);let B=await Ls1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return ks1(B.url,Q.siteUrl)}function ks1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function Ls1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=zZw.safeParse(w);if(!B.success)return;return{url:B.data.content,...B.data.metadata.width&&{width:B.data.metadata.width},...B.data.metadata.height&&{height:B.data.metadata.height}}}async function _s1(A,Q){let w=new Set;try{let B=A.getEntityTypes();for(let $ of B){if($==="image")continue;let f=await A.listEntities({entityType:$});for(let Y of f){let X=Tu(Y);if(X)w.add(X);let H=M20(Y);if(H)w.add(H)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:SA(B)})}return[...w]}async function Ns1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,Y=A.dataQuery?{dataParams:A.dataQuery,fallback:A.content,publishedOnly:w,visibilityScope:B}:{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content,visibilityScope:B},X=await $.pipelineContext.services.resolveTemplateContent(f,Y);if(!X)return null;return yf0(X,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:K4.getInstance()})}function Ps1(A){return{routes:A.routes,siteConfig:{title:A.siteMetadata.title,description:A.siteMetadata.description,...A.siteMetadata.url&&{url:A.siteMetadata.url},...A.siteMetadata.copyright&&{copyright:A.siteMetadata.copyright},...A.siteMetadata.themeMode&&{themeMode:A.siteMetadata.themeMode},...A.siteMetadata.analyticsScript&&{analyticsScript:A.siteMetadata.analyticsScript}},headScripts:A.buildOptions.headScripts,...A.buildOptions.staticAssets&&{staticAssets:A.buildOptions.staticAssets},getContent:async(Q,w)=>{let B=A.parsedOptions.environment==="production";return Ns1(w,Q,B,"public",{pipelineContext:A.pipelineContext,imageBuildService:A.imageBuildService,siteUrl:A.siteMetadata.url})},getViewTemplate:(Q)=>{return A.pipelineContext.services.getViewTemplate(Q)},layouts:A.parsedOptions.layouts,getSiteLayoutInfo:async()=>{return Fs1(A.siteMetadata,A.pipelineContext.profileService,A.pipelineContext.routeRegistry)},...A.parsedOptions.themeCSS!==void 0&&{themeCSS:A.parsedOptions.themeCSS},...A.buildOptions.slots&&{slots:A.buildOptions.slots},imageBuildService:A.imageBuildService}}import{join as VZw}from"path";async function js1(A){let Q=A.parsedOptions.workingDir??VZw(A.parsedOptions.outputDir,".preact-work"),w=A.staticSiteBuilderFactory({logger:A.logger.child("StaticSiteBuilder"),workingDir:Q,outputDir:A.parsedOptions.outputDir});if(A.parsedOptions.cleanBeforeBuild)await w.clean();return w}async function Ms1(A){await new Cf0({logger:A.pipelineContext.logger.child("DynamicRouteGenerator"),entityService:A.pipelineContext.services.entityService,listViewTemplateNames:()=>A.pipelineContext.services.listViewTemplateNames()},A.pipelineContext.routeRegistry,A.pipelineContext.entityDisplay,{visibilityScope:"public",...A.publishedOnly!==void 0&&{publishedOnly:A.publishedOnly}}).generateEntityRoutes()}async function xs1(A){let Q=new hf0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await _s1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function Os1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function vs1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function Rs1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function hs1(A){let Q=Js1.parse(A.buildOptions),w=Kf.from(A.progress),B=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await Ms1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await js1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=Is1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:Y}=f;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let X=await xs1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),H=Ps1({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:X,siteMetadata:Q.siteConfig});return await Os1({staticSiteBuilder:$,buildContext:H,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),vs1({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),Rs1({outputDir:Q.outputDir,errorMessage:f.message})}}class EZ{static instance=null;static defaultStaticSiteBuilderFactory=Br0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){EZ.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return EZ.instance??=new EZ(A,EZ.defaultStaticSiteBuilderFactory,Q,w,B,$),EZ.instance}static resetInstance(){EZ.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new EZ(A,$??EZ.defaultStaticSiteBuilderFactory,Q,w,B,f)}constructor(A,Q,w,B,$,f){this.pipelineContext={logger:A,services:w,routeRegistry:B,profileService:$,entityDisplay:f},this.staticSiteBuilderFactory=Q,K4.getInstance().configure(f)}async build(A,Q){return hs1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class $r0{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,B){this.config=A,this.context=Q,this.pluginId=w,this.logger=B}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new kl0(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async(B)=>{let{entityType:$}=B.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let B of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe(B,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({type:"site-build",data:{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},options:{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}}),this.logger.debug("Site rebuild enqueued")}catch(w){this.logger.error("Failed to enqueue site rebuild",{error:w})}}}w9();function JZw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function Ef0(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?JZw(B.sections,Q):[]})}function Cs1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=be.parse(B.payload),{routes:f,pluginId:Y}=$;return Ef0(f,Y,Q),{success:!0}}catch($){return w.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(B)=>{try{let $=Ve.parse(B.payload),{paths:f,pluginId:Y}=$;if(f)for(let X of f)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return w.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(B)=>{try{let $=Je.parse(B.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return w.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(B)=>{try{let $=Ie.parse(B.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return w.error("Failed to get route",{error:$}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as gs1}from"fs";import{join as ys1}from"path";async function IZw(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=Qr0(B,A.environment);await gs1.writeFile(ys1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=wr0($,B);await gs1.writeFile(ys1(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function Es1(A){let{context:Q,routeRegistry:w,logger:B}=A;Q.messaging.subscribe("site:build:completed",async($)=>{try{let f=$.payload;return B.info(`Received site:build:completed event for ${f.environment} environment - generating SEO files`),await IZw(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}wA();L0();var Ts1=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:Qy.optional()});w9();w9();L0();var FZw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),kZw=Z.object({blurb:Z.string().optional()}),Ss1=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:FZw.optional(),sections:Z.record(Z.string(),kZw).optional()});async function gr(A,Q){try{let w=await A({type:eT,payload:void 0});if("success"in w&&w.success&&w.data){let B=Ss1.safeParse(w.data);if(B.success)return Ss1.parse({...Q,...B.data})}}catch{}return Q}class fr0 extends ew{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:Ts1,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let B=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:B,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${B} environment`});let f=w.createSub({scale:{start:10,end:90}}),Y=await gr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),X=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:Y,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},f.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${X.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:X.routesBuilt,success:X.success}),X.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let H=B==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:B,routesBuilt:X.routesBuilt,siteConfig:{...Y,url:H},generateEntityUrl:(W,K)=>K4.getInstance().generateUrl(W,K)},broadcast:!0})}return{success:X.success,routesBuilt:X.routesBuilt,outputDir:A.outputDir,environment:B,...X.errors&&{errors:X.errors},...X.warnings&&{warnings:X.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}L0();w9();var LZw=Z.object({slot:Z.enum(KV).optional().default("primary"),limit:Z.number().optional()});class Yr0{routeRegistry;logger;id="site:navigation";name="Site Navigation DataSource";description="Provides navigation items for site menus";constructor(A,Q){this.routeRegistry=A,this.logger=Q,this.logger.debug("NavigationDataSource initialized")}async fetch(A,Q,w){let B=LZw.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,Y=f.map((H)=>({label:H.label,href:H.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:Y});let X={navigation:Y};return Q.parse(X)}}w9();wA();L0();var _Zw=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function ms1(A,Q){return[x6(A,"build-site","Build a static site from registered routes. Call this for every user build/rebuild request, including repeated requests like 'build it again' or 'one more build'.",_Zw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}L0();w9();var NZw=Z.object({id:Z.string(),template:Z.string(),content:Z.unknown().optional(),dataQuery:Z.looseObject({entityType:Z.string().optional(),template:Z.string().optional(),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),offset:Z.number().optional()}).optional()}).optional(),order:Z.number().optional()}),PZw=Z.object({show:Z.boolean().default(!1),label:Z.string().optional(),slot:Z.enum(KV).default("primary"),priority:Z.number().min(0).max(100).default(50)}).optional(),jZw=Z.object({id:Z.string(),path:Z.string(),title:Z.string().default(""),pageLabel:Z.string().optional(),description:Z.string().default(""),sections:Z.array(NZw).default([]),layout:Z.string().default("default"),fullscreen:Z.boolean().optional(),pluginId:Z.string().optional(),sourceEntityType:Z.string().optional(),external:Z.boolean().optional(),navigation:PZw}),us1=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:Qy.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(jZw).optional().describe("Routes to register"),layouts:Z.record(Z.string(),Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.string(),Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(KV).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string(),Z.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var cs1={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.163",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 Xr0 extends Aw{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;headScripts=new Map;get routeRegistry(){if(!this._routeRegistry)throw Error("RouteRegistry not initialized - plugin not registered");return this._routeRegistry}constructor(A={}){let Q=A.layouts??{};super("site-builder",cs1,{...A,layouts:Q},us1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new gf0(A.logger),this._slotRegistry=new Hf0,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:Y}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:B,script:$}=w.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new Yr0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=_f.getInstance(A.entityService,A.logger),Cs1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Ef0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,B)=>A.templates.resolve(w,B),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=EZ.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new fr0(this.logger.child("SiteBuildJobHandler"),A.messaging.send,{siteBuilder:this.siteBuilder,layouts:this.layouts,defaultSiteConfig:this.config.siteInfo,sharedImagesDir:this.config.sharedImagesDir,siteUrl:A.siteUrl,previewUrl:A.previewUrl,themeCSS:this.config.themeCSS,slots:this._slotRegistry,getHeadScripts:()=>this.getRegisteredHeadScripts(),...this.config.staticAssets&&{staticAssets:this.config.staticAssets}})),this.rebuildManager=new $r0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(AS,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),Es1({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}getRegisteredHeadScripts(){return Array.from(this.headScripts.values())}async getTools(){if(!this.pluginContext||!this.rebuildManager)throw Error("Plugin context not initialized");let A=this.rebuildManager;return ms1(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 gr(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({id:w.id,path:w.path,title:w.title,description:w.description,sections:w.sections.map((B)=>({id:B.id,template:B.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({name:w.name,description:w.description,hasWebRenderer:!!w.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",w=await gr(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6748
|
+
`+X;await i7.writeFile(Y,W,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=dD(process.cwd(),"public");try{await i7.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await i7.readdir(A,{withFileTypes:!0});for(let w of Q){let B=dD(A,w.name),$=dD(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory(B,$);else await i7.copyFile(B,$),this.logger.debug(`Copied static asset: ${w.name}`)}this.logger.debug("Static assets copied successfully")}async writeInlineStaticAssets(A){if(!A)return;let Q=Object.entries(A);if(Q.length===0)return;this.logger.debug(`Writing ${Q.length} inline static asset(s) from SitePackage`),await Promise.all(Q.map(async([w,B])=>{let $=w.startsWith("/")?w.slice(1):w,f=dD(this.outputDir,$);await i7.mkdir(KZw(f),{recursive:!0}),await i7.writeFile(f,B,"utf-8"),this.logger.debug(`Wrote inline static asset: ${$}`)}))}async copyDirectory(A,Q){await i7.mkdir(Q,{recursive:!0});let w=await i7.readdir(A,{withFileTypes:!0});for(let B of w){let $=dD(A,B.name),f=dD(Q,B.name);if(B.isDirectory())await this.copyDirectory($,f);else await i7.copyFile($,f)}}}function Br0(A){return new Vs1(A)}w9();L0();L0();var UZw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),GZw=Z.object({blurb:Z.string().optional()}),Qy=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:UZw.optional(),sections:Z.record(Z.string(),GZw).optional()});var Js1=Z.object({environment:Z.enum(["preview","production"]),outputDir:Z.string(),workingDir:Z.string().optional(),sharedImagesDir:Z.string().default("./dist/images"),enableContentGeneration:Z.boolean().default(!1),cleanBeforeBuild:Z.boolean().default(!0),siteConfig:Qy,layouts:Z.record(Z.string(),Z.any()),themeCSS:Z.string().optional()}),IoB=Z.object({success:Z.boolean(),outputDir:Z.string(),filesGenerated:Z.number(),routesBuilt:Z.number(),errors:Z.array(Z.string()).optional(),warnings:Z.array(Z.string()).optional()});function Is1(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function Fs1(A,Q,w){let B=Q.getProfile(),$=w.getNavigationItems("primary"),f=w.getNavigationItems("secondary");return{...A,...B.socialLinks!==void 0&&{socialLinks:B.socialLinks},navigation:{primary:$,secondary:f},copyright:A.copyright??"Powered by Rizom"}}w9();_4();w9();D2();L0();var DZw=Z.looseObject({id:Z.string(),entityType:Z.string(),content:Z.string(),metadata:Z.looseObject({slug:Z.string()})}),zZw=Z.looseObject({content:Z.string(),metadata:Z.looseObject({width:Z.number().optional(),height:Z.number().optional()})});async function yf0(A,Q){let w=Q.urlGenerator??K4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((O)=>yf0(O,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let B={},$=Object.entries(A),f=await Promise.all($.map(([,O])=>yf0(O,{...Q,urlGenerator:w})));for(let O=0;O<$.length;O++){let v=$[O];if(v)B[v[0]]=f[O]}let Y=DZw.safeParse(A);if(!Y.success)return B;let X=Y.data,H=X.entityType,W=X.metadata.slug,K=Q.pipelineContext.entityDisplay?.[H],U=K?K.label:H.charAt(0).toUpperCase()+H.slice(1),G=K?K.pluralName??K.label.toLowerCase()+"s":wK(H),q=`/${G}`,b=G.charAt(0).toUpperCase()+G.slice(1),J=Tu(X),V=await qZw(J,Q),k=M20(X)??J,N=await bZw(k,Q);return{...B,...X,url:w.generateUrl(H,W),typeLabel:U,listUrl:q,listLabel:b,...V,...N&&{ogImageUrl:N}}}async function qZw(A,Q){let w=A?Q.imageBuildService?.get(A):void 0;if(w)return{coverImageUrl:w.src,coverImageWidth:w.width,coverImageHeight:w.height,...w.srcset&&{coverImageSrcset:w.srcset,coverImageSizes:w.sizes}};let B=await Ls1(A,Q.pipelineContext.services.entityService);if(!B)return{};return{coverImageUrl:B.url,...B.width&&{coverImageWidth:B.width},...B.height&&{coverImageHeight:B.height}}}async function bZw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return ks1(w.src,Q.siteUrl);let B=await Ls1(A,Q.pipelineContext.services.entityService);if(!B)return;if(B.url.startsWith("data:"))return;return ks1(B.url,Q.siteUrl)}function ks1(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function Ls1(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),B=zZw.safeParse(w);if(!B.success)return;return{url:B.data.content,...B.data.metadata.width&&{width:B.data.metadata.width},...B.data.metadata.height&&{height:B.data.metadata.height}}}async function _s1(A,Q){let w=new Set;try{let B=A.getEntityTypes();for(let $ of B){if($==="image")continue;let f=await A.listEntities({entityType:$});for(let Y of f){let X=Tu(Y);if(X)w.add(X);let H=M20(Y);if(H)w.add(H)}}}catch(B){Q.warn("Failed to collect image IDs for pre-resolution",{error:SA(B)})}return[...w]}async function Ns1(A,Q,w,B,$){if(!A.template)return A.content??null;let f=A.template,Y=A.dataQuery?{dataParams:A.dataQuery,fallback:A.content,publishedOnly:w,visibilityScope:B}:{savedContent:{entityType:"site-content",entityId:`${Q.id}:${A.id}`},fallback:A.content,visibilityScope:B},X=await $.pipelineContext.services.resolveTemplateContent(f,Y);if(!X)return null;return yf0(X,{pipelineContext:$.pipelineContext,imageBuildService:$.imageBuildService,siteUrl:$.siteUrl,urlGenerator:K4.getInstance()})}function Ps1(A){return{routes:A.routes,siteConfig:{title:A.siteMetadata.title,description:A.siteMetadata.description,...A.siteMetadata.url&&{url:A.siteMetadata.url},...A.siteMetadata.copyright&&{copyright:A.siteMetadata.copyright},...A.siteMetadata.themeMode&&{themeMode:A.siteMetadata.themeMode},...A.siteMetadata.analyticsScript&&{analyticsScript:A.siteMetadata.analyticsScript}},headScripts:A.buildOptions.headScripts,...A.buildOptions.staticAssets&&{staticAssets:A.buildOptions.staticAssets},getContent:async(Q,w)=>{let B=A.parsedOptions.environment==="production";return Ns1(w,Q,B,"public",{pipelineContext:A.pipelineContext,imageBuildService:A.imageBuildService,siteUrl:A.siteMetadata.url})},getViewTemplate:(Q)=>{return A.pipelineContext.services.getViewTemplate(Q)},layouts:A.parsedOptions.layouts,getSiteLayoutInfo:async()=>{return Fs1(A.siteMetadata,A.pipelineContext.profileService,A.pipelineContext.routeRegistry)},...A.parsedOptions.themeCSS!==void 0&&{themeCSS:A.parsedOptions.themeCSS},...A.buildOptions.slots&&{slots:A.buildOptions.slots},imageBuildService:A.imageBuildService}}import{join as VZw}from"path";async function js1(A){let Q=A.parsedOptions.workingDir??VZw(A.parsedOptions.outputDir,".preact-work"),w=A.staticSiteBuilderFactory({logger:A.logger.child("StaticSiteBuilder"),workingDir:Q,outputDir:A.parsedOptions.outputDir});if(A.parsedOptions.cleanBeforeBuild)await w.clean();return w}async function Ms1(A){await new Cf0({logger:A.pipelineContext.logger.child("DynamicRouteGenerator"),entityService:A.pipelineContext.services.entityService,listViewTemplateNames:()=>A.pipelineContext.services.listViewTemplateNames()},A.pipelineContext.routeRegistry,A.pipelineContext.entityDisplay,{visibilityScope:"public",...A.publishedOnly!==void 0&&{publishedOnly:A.publishedOnly}}).generateEntityRoutes()}async function xs1(A){let Q=new hf0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await _s1(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function Os1(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function vs1(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function Rs1(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function hs1(A){let Q=Js1.parse(A.buildOptions),w=Kf.from(A.progress),B=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await Ms1({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let $=await js1({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),f=Is1(A.pipelineContext.routeRegistry);B.push(...f.warnings);let{routes:Y}=f;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let X=await xs1({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),H=Ps1({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:X,siteMetadata:Q.siteConfig});return await Os1({staticSiteBuilder:$,buildContext:H,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),vs1({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:B})}catch($){let f=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:f,originalError:$}),Rs1({outputDir:Q.outputDir,errorMessage:f.message})}}class EZ{static instance=null;static defaultStaticSiteBuilderFactory=Br0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){EZ.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,B,$=void 0){return EZ.instance??=new EZ(A,EZ.defaultStaticSiteBuilderFactory,Q,w,B,$),EZ.instance}static resetInstance(){EZ.instance=null}static createFresh(A,Q,w,B,$,f=void 0){return new EZ(A,$??EZ.defaultStaticSiteBuilderFactory,Q,w,B,f)}constructor(A,Q,w,B,$,f){this.pipelineContext={logger:A,services:w,routeRegistry:B,profileService:$,entityDisplay:f},this.staticSiteBuilderFactory=Q,K4.getInstance().configure(f)}async build(A,Q){return hs1({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class $r0{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,B){this.config=A,this.context=Q,this.pluginId=w,this.logger=B}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new kl0(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async(B)=>{let{entityType:$}=B.payload;if(!A.has($))this.logger.debug(`Entity type ${$} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let B of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe(B,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({type:"site-build",data:{environment:A,outputDir:Q,workingDir:this.config.workingDir,enableContentGeneration:!0,metadata:{trigger:"debounced-rebuild",timestamp:new Date().toISOString()}},options:{priority:0,source:this.pluginId,metadata:{operationType:"content_operations"},deduplication:"skip"}}),this.logger.debug("Site rebuild enqueued")}catch(w){this.logger.error("Failed to enqueue site rebuild",{error:w})}}}w9();function JZw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function Ef0(A,Q,w){for(let B of A)w.register({...B,pluginId:Q,sections:B.sections?JZw(B.sections,Q):[]})}function Cs1(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async(B)=>{try{let $=be.parse(B.payload),{routes:f,pluginId:Y}=$;return Ef0(f,Y,Q),{success:!0}}catch($){return w.error("Failed to register routes",{error:$}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async(B)=>{try{let $=Ve.parse(B.payload),{paths:f,pluginId:Y}=$;if(f)for(let X of f)Q.unregister(X);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch($){return w.error("Failed to unregister routes",{error:$}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async(B)=>{try{let $=Je.parse(B.payload);return{success:!0,data:{routes:Q.list($.pluginId?$:void 0)}}}catch($){return w.error("Failed to list routes",{error:$}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async(B)=>{try{let $=Ie.parse(B.payload);return{success:!0,data:{route:Q.get($.path)}}}catch($){return w.error("Failed to get route",{error:$}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as gs1}from"fs";import{join as ys1}from"path";async function IZw(A,Q,w){let B=A.siteConfig.url??"https://example.com",$=Q.list(),f=Qr0(B,A.environment);await gs1.writeFile(ys1(A.outputDir,"robots.txt"),f,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=wr0($,B);await gs1.writeFile(ys1(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${$.length} URLs`)}function Es1(A){let{context:Q,routeRegistry:w,logger:B}=A;Q.messaging.subscribe("site:build:completed",async($)=>{try{let f=$.payload;return B.info(`Received site:build:completed event for ${f.environment} environment - generating SEO files`),await IZw(f,w,B),{success:!0}}catch(f){return B.error("Failed to generate SEO files",f),{success:!1}}})}wA();L0();var Ts1=Z.object({environment:Z.enum(["preview","production"]).optional(),outputDir:Z.string(),workingDir:Z.string().optional(),enableContentGeneration:Z.boolean().optional(),siteConfig:Qy.optional()});w9();w9();L0();var FZw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),kZw=Z.object({blurb:Z.string().optional()}),Ss1=Z.object({title:Z.string(),description:Z.string(),url:Z.string().optional(),copyright:Z.string().optional(),logo:Z.boolean().optional(),themeMode:Z.enum(["light","dark"]).optional(),analyticsScript:Z.string().optional(),cta:FZw.optional(),sections:Z.record(Z.string(),kZw).optional()});async function gr(A,Q){try{let w=await A({type:eT,payload:void 0});if("success"in w&&w.success&&w.data){let B=Ss1.safeParse(w.data);if(B.success)return Ss1.parse({...Q,...B.data})}}catch{}return Q}class fr0 extends ew{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:Ts1,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let B=A.environment??"preview",$=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:B,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${B} environment`});let f=w.createSub({scale:{start:10,end:90}}),Y=await gr(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),X=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:$,environment:B,cleanBeforeBuild:!0,siteConfig:Y,layouts:this.cfg.layouts,themeCSS:this.cfg.themeCSS,slots:this.cfg.slots,headScripts:this.cfg.getHeadScripts?.(),...this.cfg.staticAssets&&{staticAssets:this.cfg.staticAssets}},f.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${X.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:B,routesBuilt:X.routesBuilt,success:X.success}),X.success){this.logger.info(`Emitting site:build:completed event for ${B} environment`);let H=B==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:B,routesBuilt:X.routesBuilt,siteConfig:{...Y,url:H},generateEntityUrl:(W,K)=>K4.getInstance().generateUrl(W,K)},broadcast:!0})}return{success:X.success,routesBuilt:X.routesBuilt,outputDir:A.outputDir,environment:B,...X.errors&&{errors:X.errors},...X.warnings&&{warnings:X.warnings}}}catch(f){throw this.logger.error("Site build job failed",f),f}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}L0();w9();var LZw=Z.object({slot:Z.enum(KV).optional().default("primary"),limit:Z.number().optional()});class Yr0{routeRegistry;logger;id="site:navigation";name="Site Navigation DataSource";description="Provides navigation items for site menus";constructor(A,Q){this.routeRegistry=A,this.logger=Q,this.logger.debug("NavigationDataSource initialized")}async fetch(A,Q,w){let B=LZw.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:B});let $=this.routeRegistry.getNavigationItems(B.slot),f=B.limit?$.slice(0,B.limit):$,Y=f.map((H)=>({label:H.label,href:H.href}));this.logger.debug("NavigationDataSource returning",{slot:B.slot,itemCount:f.length,items:Y});let X={navigation:Y};return Q.parse(X)}}w9();wA();L0();var _Zw=Z.object({environment:Z.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function ms1(A,Q){return[x6(A,"build-site","Build a static site from registered routes. Call this for every user build/rebuild request, including repeated requests like 'build it again' or 'one more build'.",_Zw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}L0();w9();var NZw=Z.object({id:Z.string(),template:Z.string(),content:Z.unknown().optional(),dataQuery:Z.looseObject({entityType:Z.string().optional(),template:Z.string().optional(),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),offset:Z.number().optional()}).optional()}).optional(),order:Z.number().optional()}),PZw=Z.object({show:Z.boolean().default(!1),label:Z.string().optional(),slot:Z.enum(KV).default("primary"),priority:Z.number().min(0).max(100).default(50)}).optional(),jZw=Z.object({id:Z.string(),path:Z.string(),title:Z.string().default(""),pageLabel:Z.string().optional(),description:Z.string().default(""),sections:Z.array(NZw).default([]),layout:Z.string().default("default"),fullscreen:Z.boolean().optional(),pluginId:Z.string().optional(),sourceEntityType:Z.string().optional(),external:Z.boolean().optional(),navigation:PZw}),us1=Z.object({previewOutputDir:Z.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:Z.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:Z.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:Z.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:Qy.default({title:"Brain",description:"A knowledge management system"}),themeCSS:Z.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:Z.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:Z.any().optional().describe("Template definitions to register"),routes:Z.array(jZw).optional().describe("Routes to register"),layouts:Z.record(Z.string(),Z.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:Z.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:Z.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:Z.record(Z.string(),Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:Z.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:Z.boolean().optional().describe("Enable pagination for list pages"),pageSize:Z.number().optional().describe("Items per page (default: 10)"),navigation:Z.object({show:Z.boolean().optional().describe("Show in navigation"),slot:Z.enum(KV).optional().describe("Navigation slot (primary or secondary)"),priority:Z.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:Z.record(Z.string(),Z.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var cs1={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.164",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 Xr0 extends Aw{siteBuilder;pluginContext;_routeRegistry;_slotRegistry;profileService;layouts;rebuildManager;headScripts=new Map;get routeRegistry(){if(!this._routeRegistry)throw Error("RouteRegistry not initialized - plugin not registered");return this._routeRegistry}constructor(A={}){let Q=A.layouts??{};super("site-builder",cs1,{...A,layouts:Q},us1);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new gf0(A.logger),this._slotRegistry=new Hf0,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:B,pluginId:$,render:f,priority:Y}=w.payload;return this._slotRegistry?.register(B,{pluginId:$,render:f,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:B,script:$}=w.payload;return this.headScripts.set(B,$),{success:!0}}),A.entities.registerDataSource(new Yr0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=_f.getInstance(A.entityService,A.logger),Cs1(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)Ef0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,B)=>A.templates.resolve(w,B),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=EZ.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new fr0(this.logger.child("SiteBuildJobHandler"),A.messaging.send,{siteBuilder:this.siteBuilder,layouts:this.layouts,defaultSiteConfig:this.config.siteInfo,sharedImagesDir:this.config.sharedImagesDir,siteUrl:A.siteUrl,previewUrl:A.previewUrl,themeCSS:this.config.themeCSS,slots:this._slotRegistry,getHeadScripts:()=>this.getRegisteredHeadScripts(),...this.config.staticAssets&&{staticAssets:this.config.staticAssets}})),this.rebuildManager=new $r0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(AS,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),Es1({context:A,routeRegistry:this._routeRegistry,logger:this.logger})}getRegisteredHeadScripts(){return Array.from(this.headScripts.values())}async getTools(){if(!this.pluginContext||!this.rebuildManager)throw Error("Plugin context not initialized");let A=this.rebuildManager;return ms1(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 gr(A.messaging.send,this.config.siteInfo);return{contents:[{uri:"brain://site",mimeType:"application/json",text:JSON.stringify({...Q,domain:A.domain,siteUrl:A.siteUrl,previewUrl:A.previewUrl},null,2)}]}}},{uri:"site://routes",name:"Site Routes",description:"All registered routes with sections and templates",mimeType:"application/json",handler:async()=>{let Q=this.routeRegistry.list();return{contents:[{uri:"site://routes",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({id:w.id,path:w.path,title:w.title,description:w.description,sections:w.sections.map((B)=>({id:B.id,template:B.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((w)=>({name:w.name,description:w.description,hasWebRenderer:!!w.renderers.web})),null,2)}]}}}]}getSiteBuilder(){return this.siteBuilder}getSlotRegistry(){return this._slotRegistry}async getInstructions(){let A=this.getContext(),Q="## Site Builder Actions\n- When the user asks to build, rebuild, publish, or build the website/site again, call `site-builder_build-site` immediately.\n- Every repeated build request requires a fresh `site-builder_build-site` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.",w=await gr(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6749
6749
|
${[`**Title:** ${w.title}`,`**Description:** ${w.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
|
|
6750
6750
|
`)}
|
|
6751
6751
|
|
|
6752
6752
|
## Site Builder Actions
|
|
6753
6753
|
- When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
|
|
6754
|
-
- Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),EZ.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function oP(A={}){return new Xr0(A)}wA();wA();L0();var Zr0=Z.object({routeId:Z.string(),sectionId:Z.string()}),xZw=Z.object({routeId:Z.string(),sectionId:Z.string()}),yr=PQ.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:xZw});wA();class ls1 extends E2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:yr,frontmatterSchema:Zr0})}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 Hr0=new ls1;L0();var Tf0=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),HaB=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});L0();var OZw=Z.looseObject({id:Z.string(),template:Z.string().optional(),content:Z.unknown().optional()}),vZw=Z.looseObject({id:Z.string(),title:Z.string().optional(),description:Z.string().optional(),sections:Z.array(OZw)}),RZw=Z.array(vZw);class Wr0{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=RZw.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((K)=>K.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of f)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){B.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let G=this.context.templates.getCapabilities(U.template);if(!G){B.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!G.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:G});continue}}else{B.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let G=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){B.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let H=[],W=[];for(let{route:K,section:U}of Y){let G=`${K.id}:${U.id}`,q=U.template,b={routeId:K.id,sectionId:U.id,entityId:G,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};W.push({type:"shell:content-generation",data:b})}if(W.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(W,K);for(let G=0;G<Y.length;G++){let q=Y[G];if(q)H.push({jobId:`${U}-${G}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:X,queuedSections:H.length,batchId:U}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Kr0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Wr0(A)}async generateContent(A,Q){let w=Tf0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}w9();L0();var hZw=Z.object({namespace:Z.string(),sections:Z.record(Z.string(),Z.any())}),ps1=Z.custom((A)=>hZw.safeParse(A).success),Ur0=Z.object({definitions:Z.union([ps1,Z.array(ps1)]).optional()});wA();function is1(A,Q){return[x6(Q,"generate","Generate content for all routes, a specific route, or a specific section",Tf0,async(w,B)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(w.sectionId&&!w.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let f={rootJobId:`generate-${Date.now()}`,progressToken:B.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:B.interfaceType,channelId:B.channelId},Y=await $.generateContent(w,f);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 ds1={name:"@brains/site-content",version:"0.2.0-alpha.163",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 Gr0 extends Aw{siteContentService;constructor(A={}){super("site-content",ds1,A,Ur0)}async onRegister(A){A.entities.register("site-content",yr,Hr0);for(let Q of qJ(this.config.definitions))A.templates.register(IV(Q),Q.namespace);this.siteContentService=new Kr0(A)}async getTools(){return is1(()=>this.siteContentService,this.id)}}function sP(A={}){return new Gr0(A)}wA();w9();wA();L0();w9();var gZw=Z.object({}),yZw=Z.object({}),Er=PQ.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:yZw});var wy=qq0.omit({url:!0,analyticsScript:!0});wA();L0();var EZw=Z.record(Z.string(),Z.unknown());class nD extends E2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Er,frontmatterSchema:wy,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=wy.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("",EZw.parse(Q))}}class rD{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return rD.instance??=new rD(A,Q,w),rD.instance}static resetInstance(){rD.instance=null}static createFresh(A,Q,w){return new rD(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new nD;let B=rD.getDefaultSiteInfo();this.defaultSiteInfo={...B,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let w=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:w,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}L0();var TZw=new nD,SZw=Z.looseObject({platform:Z.string(),url:Z.string(),label:Z.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),mZw=Z.looseObject({socialLinks:Z.array(SZw).optional()});class Sf0{logger;id="site-info:entities";name="Site Info DataSource";description="Provides site metadata (title, description, CTA) and profile social links";constructor(A){this.logger=A}async fetch(A,Q,w){let{entityService:B}=w,$;try{let X=await B.getEntity({entityType:"site-info",id:"site-info"});$=X?TZw.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let X=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(X){let H=mZw.safeParse(X.metadata);f=H.success?H.data.socialLinks:void 0}}catch{}let Y={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var ns1={name:"@brains/site-info",version:"0.2.0-alpha.163",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 cZw=new nD,lZw="site-info";class Dr0 extends sQ{entityType=lZw;schema=Er;adapter=cZw;defaultSiteInfo;constructor(A){super("site-info",ns1,{},P7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new Sf0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=rD.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(eT,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let $=await Q.getSiteInfo();await A.messaging.send({type:AS,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function aP(A){return new Dr0(A)}var pZw=new nD;async function Tr(A){let w=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!w)throw Error("Site info not found \u2014 create a site-info entity");return pZw.parseSiteInfoBody(w.content)}function rs1(A,Q){let w=A.metadata.publishedAt??A.created,B=Q.metadata.publishedAt??Q.created;return new Date(B).getTime()-new Date(w).getTime()}async function mf0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(rs1).slice(0,Q.count).map(Q.parse)}function zr0(A){if(!A)throw Error("CTA not configured in site-info");return A}L0();var os1=Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}),iZw=Z.object({primary:Z.array(os1),secondary:Z.array(os1)}),dZw=Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")}),nZw=wy.extend({navigation:iZw,copyright:Z.string(),socialLinks:Z.array(dZw).optional().describe("Social media links from profile entity")});wA();TZ();fy();L0();var qr0=Z.object({defaultPrompt:Z.string().default("Write a blog post about my recent work and insights"),paginate:Z.boolean().default(!0),pageSize:Z.number().default(10)});wA();T6();D2();L0();var aZw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),content:Z.string().optional(),excerpt:Z.string().optional(),coverImageId:Z.string().optional(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional(),skipAi:Z.boolean().optional()}),StB=jX.extend({title:Z.string().optional(),slug:Z.string().optional()});class br0 extends J4{constructor(A,Q){super(A,Q,{schema:aZw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:Y}=A,{title:X,content:H,excerpt:W}=A;if(Y){if(!X)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
|
|
6754
|
+
- Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),EZ.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function oP(A={}){return new Xr0(A)}wA();wA();L0();var Zr0=Z.object({routeId:Z.string(),sectionId:Z.string()}),xZw=Z.object({routeId:Z.string(),sectionId:Z.string()}),yr=PQ.extend({entityType:Z.literal("site-content"),template:Z.string().optional(),content:Z.string(),metadata:xZw});wA();class ls1 extends E2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:yr,frontmatterSchema:Zr0})}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 Hr0=new ls1;L0();var Tf0=Z.object({routeId:Z.string().optional().describe("Optional: specific route filter"),sectionId:Z.string().optional().describe("Optional: specific section filter"),dryRun:Z.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:Z.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),HaB=Z.object({jobs:Z.array(Z.object({jobId:Z.string(),routeId:Z.string(),sectionId:Z.string()})),totalSections:Z.number(),queuedSections:Z.number(),skippedSections:Z.number().optional(),batchId:Z.string().optional()});L0();var OZw=Z.looseObject({id:Z.string(),template:Z.string().optional(),content:Z.unknown().optional()}),vZw=Z.looseObject({id:Z.string(),title:Z.string().optional(),description:Z.string().optional(),sections:Z.array(OZw)}),RZw=Z.array(vZw);class Wr0{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=RZw.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let B=this.context.logger.child("SiteContentOperations"),$=await this.fetchRoutes(),f=$;if(A.routeId){if(f=$.filter((K)=>K.id===A.routeId),f.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of f)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){B.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let G=this.context.templates.getCapabilities(U.template);if(!G){B.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!G.canGenerate){B.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:G});continue}}else{B.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let G=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){B.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let X=Y.length;if(A.dryRun)return{jobs:[],totalSections:X,queuedSections:X,batchId:`dry-run-${Date.now()}`};let H=[],W=[];for(let{route:K,section:U}of Y){let G=`${K.id}:${U.id}`,q=U.template,b={routeId:K.id,sectionId:U.id,entityId:G,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};W.push({type:"shell:content-generation",data:b})}if(W.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(W,K);for(let G=0;G<Y.length;G++){let q=Y[G];if(q)H.push({jobId:`${U}-${G}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:X,queuedSections:H.length,batchId:U}}return{jobs:[],totalSections:X,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Kr0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Wr0(A)}async generateContent(A,Q){let w=Tf0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}w9();L0();var hZw=Z.object({namespace:Z.string(),sections:Z.record(Z.string(),Z.any())}),ps1=Z.custom((A)=>hZw.safeParse(A).success),Ur0=Z.object({definitions:Z.union([ps1,Z.array(ps1)]).optional()});wA();function is1(A,Q){return[x6(Q,"generate","Generate content for all routes, a specific route, or a specific section",Tf0,async(w,B)=>{let $=A();if(!$)return{success:!1,error:"Site content service not initialized"};if(w.sectionId&&!w.routeId)return{success:!1,error:"sectionId requires routeId to be specified"};let f={rootJobId:`generate-${Date.now()}`,progressToken:B.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:B.interfaceType,channelId:B.channelId},Y=await $.generateContent(w,f);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 ds1={name:"@brains/site-content",version:"0.2.0-alpha.164",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 Gr0 extends Aw{siteContentService;constructor(A={}){super("site-content",ds1,A,Ur0)}async onRegister(A){A.entities.register("site-content",yr,Hr0);for(let Q of qJ(this.config.definitions))A.templates.register(IV(Q),Q.namespace);this.siteContentService=new Kr0(A)}async getTools(){return is1(()=>this.siteContentService,this.id)}}function sP(A={}){return new Gr0(A)}wA();w9();wA();L0();w9();var gZw=Z.object({}),yZw=Z.object({}),Er=PQ.extend({id:Z.literal("site-info"),entityType:Z.literal("site-info"),metadata:yZw});var wy=qq0.omit({url:!0,analyticsScript:!0});wA();L0();var EZw=Z.record(Z.string(),Z.unknown());class nD extends E2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Er,frontmatterSchema:wy,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=wy.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("",EZw.parse(Q))}}class rD{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return rD.instance??=new rD(A,Q,w),rD.instance}static resetInstance(){rD.instance=null}static createFresh(A,Q,w){return new rD(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new nD;let B=rD.getDefaultSiteInfo();this.defaultSiteInfo={...B,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let w=this.adapter.createSiteInfoContent(this.defaultSiteInfo);await this.entityService.createEntity({entity:{id:"site-info",entityType:"site-info",content:w,metadata:{}}}),this.logger.info("Default site info created successfully")}}catch(A){this.logger.error("Failed to initialize site info",{error:A})}}async getSiteInfo(){try{let A=await this.entityService.getEntity({entityType:"site-info",id:"site-info"});if(A)return this.adapter.parseSiteInfoBody(A.content)}catch(A){this.logger.debug("Site info not found, using defaults",{error:A})}return this.defaultSiteInfo}}L0();var TZw=new nD,SZw=Z.looseObject({platform:Z.string(),url:Z.string(),label:Z.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),mZw=Z.looseObject({socialLinks:Z.array(SZw).optional()});class Sf0{logger;id="site-info:entities";name="Site Info DataSource";description="Provides site metadata (title, description, CTA) and profile social links";constructor(A){this.logger=A}async fetch(A,Q,w){let{entityService:B}=w,$;try{let X=await B.getEntity({entityType:"site-info",id:"site-info"});$=X?TZw.parseSiteInfoBody(X.content):{title:"Brain",description:"A knowledge management system"}}catch{$={title:"Brain",description:"A knowledge management system"}}let f;try{let X=await B.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(X){let H=mZw.safeParse(X.metadata);f=H.success?H.data.socialLinks:void 0}}catch{}let Y={...$,socialLinks:f,copyright:$.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var ns1={name:"@brains/site-info",version:"0.2.0-alpha.164",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 cZw=new nD,lZw="site-info";class Dr0 extends sQ{entityType=lZw;schema=Er;adapter=cZw;defaultSiteInfo;constructor(A){super("site-info",ns1,{},P7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new Sf0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=rD.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(eT,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let $=await Q.getSiteInfo();await A.messaging.send({type:AS,payload:$,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function aP(A){return new Dr0(A)}var pZw=new nD;async function Tr(A){let w=(await A.listEntities({entityType:"site-info",options:{limit:1}}))[0];if(!w)throw Error("Site info not found \u2014 create a site-info entity");return pZw.parseSiteInfoBody(w.content)}function rs1(A,Q){let w=A.metadata.publishedAt??A.created,B=Q.metadata.publishedAt??Q.created;return new Date(B).getTime()-new Date(w).getTime()}async function mf0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(rs1).slice(0,Q.count).map(Q.parse)}function zr0(A){if(!A)throw Error("CTA not configured in site-info");return A}L0();var os1=Z.object({label:Z.string(),href:Z.string(),priority:Z.number()}),iZw=Z.object({primary:Z.array(os1),secondary:Z.array(os1)}),dZw=Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:Z.string().describe("Profile or contact URL"),label:Z.string().optional().describe("Optional display label")}),nZw=wy.extend({navigation:iZw,copyright:Z.string(),socialLinks:Z.array(dZw).optional().describe("Social media links from profile entity")});wA();TZ();fy();L0();var qr0=Z.object({defaultPrompt:Z.string().default("Write a blog post about my recent work and insights"),paginate:Z.boolean().default(!0),pageSize:Z.number().default(10)});wA();T6();D2();L0();var aZw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),content:Z.string().optional(),excerpt:Z.string().optional(),coverImageId:Z.string().optional(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional(),skipAi:Z.boolean().optional()}),StB=jX.extend({title:Z.string().optional(),slug:Z.string().optional()});class br0 extends J4{constructor(A,Q){super(A,Q,{schema:aZw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:B,seriesName:$,seriesIndex:f,skipAi:Y}=A,{title:X,content:H,excerpt:W}=A;if(Y){if(!X)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
|
|
6755
6755
|
|
|
6756
6756
|
Add your introduction here.
|
|
6757
6757
|
|
|
@@ -6971,7 +6971,7 @@ ${w.content}`,templateName:"blog:excerpt"})})}wA();fy();TZ();function FHw(A){let
|
|
|
6971
6971
|
letter-spacing: 0.02em;
|
|
6972
6972
|
}
|
|
6973
6973
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
6974
|
-
`}},void 0,!1,void 0,this),d7("header",{className:"printable-hero",children:[d7("div",{className:"printable-masthead",children:Q.brandLabel&&d7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),d7("div",{children:[d7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&d7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),d7("div",{className:"printable-meta",children:[Q.author&&d7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&d7("span",{children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&d7("figure",{className:"printable-cover-wrap",children:d7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),d7(_9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&d7("footer",{className:"printable-footer",children:[d7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&d7("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 BWw=26214400,$Ww=60000;class Mr0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==pf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=fWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await eHw(wWw(QWw(),"brain-blog-printable-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:qa1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:BWw,timeoutMs:$Ww,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${YWw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await AWw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=D$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function fWw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=D$.parse(w);return{title:$.title,body:B,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.canonicalUrl?{canonicalUrl:$.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function YWw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}import{mkdtemp as KWw,rm as UWw}from"fs/promises";import{tmpdir as GWw}from"os";import{join as DWw}from"path";l9();D2();TZ();L0();import{jsxDEV as WWw}from"preact/jsx-dev-runtime";var pr="og-image",XWw="blog:og-image",ba1=Z.object({title:Z.string().min(1),excerpt:Z.string().optional(),author:Z.string().optional(),publishedAt:Z.string().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Va1={name:XWw,pluginId:"blog",schema:ba1,renderers:{image:HWw}};function ZWw(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 HWw(A){let Q=ba1.parse(A);return WWw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:ZWw(Q.publishedAt)},void 0,!1,void 0,this)}var zWw={width:1200,height:630},qWw=60000;class xr0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??lr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==pr)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=bWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await KWw(DWw(GWw(),"brain-blog-og-image-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Va1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),zWw,{timeoutMs:qWw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${VWw(Q)}-og.png`}}finally{await f.close()}}finally{await UWw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=D$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function bWw(A,Q={}){let{frontmatter:w}=M6(A.content),B=D$.parse(w);return{title:B.title,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function VWw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}var Ja1={name:"@brains/blog",version:"0.2.0-alpha.163",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 Or0 extends sQ{entityType=Zb.entityType;schema=By;adapter=Zb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Ja1,A,qr0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new br0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Qa1()}getDataSources(){return[new Jr0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (ka1(),Fa1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),wa1(A,this.logger),Ba1(A,this.logger),fa1(A,this.logger),Ya1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",pf0,new Mr0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",pr,new xr0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=B8.getInstance().register(kr0()),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:pr,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 vr0(A={}){return new Or0(A)}TZ();fy();wA();L0();q5();wA();L0();var PU=Z.object({title:Z.string(),slug:Z.string(),coverImageId:Z.string().optional()}),FWw=Z.object({title:Z.string(),slug:Z.string()}),kWw=Z.object({title:Z.string(),slug:Z.string()}),LF=PQ.extend({entityType:Z.literal("series"),metadata:kWw}),if0=LF.extend({frontmatter:PU}),LWw=if0.extend({description:Z.string().optional(),postCount:Z.number(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),La1=Z.object({description:Z.string().optional()});function Qj(A){return new $6(La1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}wA();class Rr0 extends E2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:LF,frontmatterSchema:PU,supportsCoverImage:!0,bodyFormatter:Qj("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,PU).coverImageId,w=Qj(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=Qj(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,PU);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,PU);return Qj(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var _F=new Rr0;wA();D2();yX();L0();var _Ww=Z.object({seriesName:Z.string().optional(),seriesIndex:Z.number().optional()});function df0(A){let Q=_Ww.safeParse(A);return Q.success?Q.data:{}}function wj(A){return df0(A.metadata).seriesName}function _a1(A){return df0(A.metadata).seriesIndex}function Na1(A,Q){let w=_a1(A)??Number.MAX_SAFE_INTEGER,B=_a1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class hr0{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),w=new Map(Q.map(($)=>[$.id,$])),B=new Set;for(let $ of A){let f=H1($);B.add(f);let Y=w.get(f),X=Y?.content??this.createSeriesContent($),H=f6(X);if(Y?.contentHash===H)continue;let W={id:f,entityType:"series",content:X,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:H1($)}};await this.entityService.upsertEntity({entity:W}),this.logger.debug(`Upserted series: ${$}`)}for(let $ of Q)if(!B.has($.id))await this.entityService.deleteEntity({entityType:"series",id:$.id}),this.logger.debug(`Deleted orphaned series: ${$.id}`)}async handleEntityChange(A,Q){let w=wj(A);if(w)await this.ensureSeriesExists(w);if(Q&&Q!==w)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=H1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:f6(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:H1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=H1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;if((await this.entityService.listEntities({entityType:w,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;let B=await this.entityService.listEntities({entityType:w});for(let $ of B){let f=wj($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:H1(A)};return F5("",Q)}}wA();L0();var NWw=Z.object({entityType:Z.literal("series"),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional()})}),PWw=Z.object({type:Z.enum(["list","detail"]),seriesName:Z.string().optional()});function jWw(A){let Q=PWw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=NWw.safeParse(A);if(w.success){let{query:B}=w.data;if(B.id)return{type:"detail",seriesSlug:B.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Pa1(A){let Q=r2(A.content,PU);return if0.parse({...A,frontmatter:Q.metadata})}class Cr0{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,w){let B=jWw(A),$=w.entityService;if(B.type==="list")return this.fetchSeriesList(Q,$);if(B.seriesName)return this.fetchSeriesDetail(B.seriesName,Q,$);if(B.seriesSlug)return this.fetchSeriesDetailBySlug(B.seriesSlug,Q,$);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),B=await this.countEntitiesPerSeries(Q),$=w.map((f)=>{let Y=Pa1(f),X=_F.parseBody(f.content);return{...Y,description:X.description,postCount:B.get(f.metadata.title)??0}});return this.logger.debug(`Found ${$.length} series entities`),A.parse({series:$})}async fetchSeriesDetail(A,Q,w,B){if(!B)B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!B)throw Error(`Series not found: ${A}`);let $=Pa1(B),f=_F.parseBody(B.content),Y=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...$,description:f.description,postCount:Y.length},description:f.description})}async fetchSeriesDetailBySlug(A,Q,w){let $=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!$)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail($.metadata.title,Q,w,$)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let B of w){if(B==="series")continue;let $=await A.listEntities({entityType:B});for(let f of $){let Y=wj(f);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],B=Q.getEntityTypes();for(let $ of B){if($==="series")continue;let f=await Q.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}}}});w.push(...f)}return w.sort(Na1),w}}wA();L0();yX();var MWw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),seriesId:Z.string().optional()}),xWw=Z.object({title:Z.string().optional(),excerpt:Z.string().optional()});class nf0{logger;context;constructor(A,Q){this.logger=A,this.context=Q}async process(A){let Q=A.seriesId??A.title;if(!Q)return{success:!1,error:"seriesId or title required"};let w=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!w)return{success:!1,error:`Series not found: ${Q}`};let B=await this.gatherMemberSummaries(w.metadata.title);if(B.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let $=A.prompt??`Series name: ${w.metadata.title}
|
|
6974
|
+
`}},void 0,!1,void 0,this),d7("header",{className:"printable-hero",children:[d7("div",{className:"printable-masthead",children:Q.brandLabel&&d7("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),d7("div",{children:[d7("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&d7("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),d7("div",{className:"printable-meta",children:[Q.author&&d7("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&d7("span",{children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q.coverImageUrl&&d7("figure",{className:"printable-cover-wrap",children:d7("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),d7(_9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&d7("footer",{className:"printable-footer",children:[d7("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&d7("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 BWw=26214400,$Ww=60000;class Mr0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==pf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=fWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await eHw(wWw(QWw(),"brain-blog-printable-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/printable/post/${Q.id}`,template:qa1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:BWw,timeoutMs:$Ww,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${YWw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await AWw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=D$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function fWw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=D$.parse(w);return{title:$.title,body:B,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.canonicalUrl?{canonicalUrl:$.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function YWw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}import{mkdtemp as KWw,rm as UWw}from"fs/promises";import{tmpdir as GWw}from"os";import{join as DWw}from"path";l9();D2();TZ();L0();import{jsxDEV as WWw}from"preact/jsx-dev-runtime";var pr="og-image",XWw="blog:og-image",ba1=Z.object({title:Z.string().min(1),excerpt:Z.string().optional(),author:Z.string().optional(),publishedAt:Z.string().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),Va1={name:XWw,pluginId:"blog",schema:ba1,renderers:{image:HWw}};function ZWw(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 HWw(A){let Q=ba1.parse(A);return WWw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:ZWw(Q.publishedAt)},void 0,!1,void 0,this)}var zWw={width:1200,height:630},qWw=60000;class xr0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??lr}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==pr)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=bWw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await KWw(DWw(GWw(),"brain-blog-og-image-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/og/post/${Q.id}`,template:Va1,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"image",data:await this.screenshotPng(f.urlFor($.urlPath),zWw,{timeoutMs:qWw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${VWw(Q)}-og.png`}}finally{await f.close()}}finally{await UWw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=D$.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function bWw(A,Q={}){let{frontmatter:w}=M6(A.content),B=D$.parse(w);return{title:B.title,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function VWw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}var Ja1={name:"@brains/blog",version:"0.2.0-alpha.164",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 Or0 extends sQ{entityType=Zb.entityType;schema=By;adapter=Zb;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Ja1,A,qr0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new br0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return Qa1()}getDataSources(){return[new Jr0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (ka1(),Fa1));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),wa1(A,this.logger),Ba1(A,this.logger),fa1(A,this.logger),Ya1(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",pf0,new Mr0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",pr,new xr0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=B8.getInstance().register(kr0()),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:pr,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 vr0(A={}){return new Or0(A)}TZ();fy();wA();L0();q5();wA();L0();var PU=Z.object({title:Z.string(),slug:Z.string(),coverImageId:Z.string().optional()}),FWw=Z.object({title:Z.string(),slug:Z.string()}),kWw=Z.object({title:Z.string(),slug:Z.string()}),LF=PQ.extend({entityType:Z.literal("series"),metadata:kWw}),if0=LF.extend({frontmatter:PU}),LWw=if0.extend({description:Z.string().optional(),postCount:Z.number(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),La1=Z.object({description:Z.string().optional()});function Qj(A){return new $6(La1,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}wA();class Rr0 extends E2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:LF,frontmatterSchema:PU,supportsCoverImage:!0,bodyFormatter:Qj("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,PU).coverImageId,w=Qj(A.metadata.title).parse(this.extractBody(A.content))}catch{}let B={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},f=Qj(A.metadata.title).format(w);return this.buildMarkdown(f,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,PU);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,PU);return Qj(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var _F=new Rr0;wA();D2();yX();L0();var _Ww=Z.object({seriesName:Z.string().optional(),seriesIndex:Z.number().optional()});function df0(A){let Q=_Ww.safeParse(A);return Q.success?Q.data:{}}function wj(A){return df0(A.metadata).seriesName}function _a1(A){return df0(A.metadata).seriesIndex}function Na1(A,Q){let w=_a1(A)??Number.MAX_SAFE_INTEGER,B=_a1(Q)??Number.MAX_SAFE_INTEGER;return w-B}class hr0{entityService;logger;constructor(A,Q){this.entityService=A,this.logger=Q}async syncAllSeries(){this.logger.debug("Syncing series from all entity types");let A=await this.collectSeriesNames();this.logger.debug(`Found ${A.size} unique series`);let Q=await this.entityService.listEntities({entityType:"series"}),w=new Map(Q.map(($)=>[$.id,$])),B=new Set;for(let $ of A){let f=H1($);B.add(f);let Y=w.get(f),X=Y?.content??this.createSeriesContent($),H=f6(X);if(Y?.contentHash===H)continue;let W={id:f,entityType:"series",content:X,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:$,slug:H1($)}};await this.entityService.upsertEntity({entity:W}),this.logger.debug(`Upserted series: ${$}`)}for(let $ of Q)if(!B.has($.id))await this.entityService.deleteEntity({entityType:"series",id:$.id}),this.logger.debug(`Deleted orphaned series: ${$.id}`)}async handleEntityChange(A,Q){let w=wj(A);if(w)await this.ensureSeriesExists(w);if(Q&&Q!==w)await this.cleanupOrphanedSeries(Q)}async handleEntityDeleted(){await this.syncAllSeries()}async ensureSeriesExists(A){let Q=H1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let B=this.createSeriesContent(A),$={id:Q,entityType:"series",content:B,contentHash:f6(B),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:H1(A)}};await this.entityService.upsertEntity({entity:$}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=H1(A);if(!await this.entityService.getEntity({entityType:"series",id:Q}))return;if(!await this.hasSeriesReferences(A))await this.entityService.deleteEntity({entityType:"series",id:Q}),this.logger.debug(`Deleted orphaned series: ${A}`)}async hasSeriesReferences(A){let Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;if((await this.entityService.listEntities({entityType:w,options:{filter:{metadata:{seriesName:A}},limit:1}})).length>0)return!0}return!1}async collectSeriesNames(){let A=new Set,Q=this.entityService.getEntityTypes();for(let w of Q){if(w==="series")continue;let B=await this.entityService.listEntities({entityType:w});for(let $ of B){let f=wj($);if(f)A.add(f)}}return A}createSeriesContent(A){let Q={title:A,slug:H1(A)};return F5("",Q)}}wA();L0();var NWw=Z.object({entityType:Z.literal("series"),query:Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional()})}),PWw=Z.object({type:Z.enum(["list","detail"]),seriesName:Z.string().optional()});function jWw(A){let Q=PWw.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=NWw.safeParse(A);if(w.success){let{query:B}=w.data;if(B.id)return{type:"detail",seriesSlug:B.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function Pa1(A){let Q=r2(A.content,PU);return if0.parse({...A,frontmatter:Q.metadata})}class Cr0{logger;id="series:entities";name="Series DataSource";description="Fetches series list and detail data";constructor(A){this.logger=A}async fetch(A,Q,w){let B=jWw(A),$=w.entityService;if(B.type==="list")return this.fetchSeriesList(Q,$);if(B.seriesName)return this.fetchSeriesDetail(B.seriesName,Q,$);if(B.seriesSlug)return this.fetchSeriesDetailBySlug(B.seriesSlug,Q,$);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),B=await this.countEntitiesPerSeries(Q),$=w.map((f)=>{let Y=Pa1(f),X=_F.parseBody(f.content);return{...Y,description:X.description,postCount:B.get(f.metadata.title)??0}});return this.logger.debug(`Found ${$.length} series entities`),A.parse({series:$})}async fetchSeriesDetail(A,Q,w,B){if(!B)B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!B)throw Error(`Series not found: ${A}`);let $=Pa1(B),f=_F.parseBody(B.content),Y=await this.getSeriesMembers(A,w);return this.logger.debug(`Found ${Y.length} entities in series "${A}"`),Q.parse({seriesName:A,posts:Y,series:{...$,description:f.description,postCount:Y.length},description:f.description})}async fetchSeriesDetailBySlug(A,Q,w){let $=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!$)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail($.metadata.title,Q,w,$)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let B of w){if(B==="series")continue;let $=await A.listEntities({entityType:B});for(let f of $){let Y=wj(f);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],B=Q.getEntityTypes();for(let $ of B){if($==="series")continue;let f=await Q.listEntities({entityType:$,options:{filter:{metadata:{seriesName:A}}}});w.push(...f)}return w.sort(Na1),w}}wA();L0();yX();var MWw=Z.object({prompt:Z.string().optional(),title:Z.string().optional(),seriesId:Z.string().optional()}),xWw=Z.object({title:Z.string().optional(),excerpt:Z.string().optional()});class nf0{logger;context;constructor(A,Q){this.logger=A,this.context=Q}async process(A){let Q=A.seriesId??A.title;if(!Q)return{success:!1,error:"seriesId or title required"};let w=await this.context.entityService.getEntity({entityType:"series",id:Q});if(!w)return{success:!1,error:`Series not found: ${Q}`};let B=await this.gatherMemberSummaries(w.metadata.title);if(B.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let $=A.prompt??`Series name: ${w.metadata.title}
|
|
6975
6975
|
|
|
6976
6976
|
Content in this series:
|
|
6977
6977
|
${B.join(`
|
|
@@ -6983,7 +6983,7 @@ Your task is to write a series description (2-3 sentences) that:
|
|
|
6983
6983
|
3. Is engaging and makes readers want to explore the content
|
|
6984
6984
|
4. Works well as a series overview on a website
|
|
6985
6985
|
|
|
6986
|
-
Be concise and focus on what makes this series unique and valuable.`});async function Ca1({entity:A,config:Q}){let w=LF.parse(A),B=_F.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...B.description&&{description:B.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function gr0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:_6["ai.rizom.brain.series"],validate:!1,buildRecord:Ca1}}var ga1={name:"@brains/series",version:"0.2.0-alpha.
|
|
6986
|
+
Be concise and focus on what makes this series unique and valuable.`});async function Ca1({entity:A,config:Q}){let w=LF.parse(A),B=_F.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...B.description&&{description:B.description},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"series",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function gr0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:_6["ai.rizom.brain.series"],validate:!1,buildRecord:Ca1}}var ga1={name:"@brains/series",version:"0.2.0-alpha.164",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 ya1=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source"),entityId:Z.string(),entityType:Z.string(),seriesName:Z.string().optional(),previousSeriesName:Z.string().optional()})]);class yr0 extends sQ{entityType="series";schema=LF;adapter=_F;manager;unregisterAtprotoProjection;constructor(){super("series",ga1,{},P7)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new nf0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Ra1(),description:ha1}}getDataSources(){return[new Cr0(this.logger.child("SeriesDataSource"))]}getDerivedEntityProjections(A){return[{id:"series-projection",targetType:"series",job:{type:"series:project",handler:this.createSeriesProjectionHandler(A)},initialSync:{jobData:{mode:"derive",reason:"initial-sync"},jobOptions:this.getSyncProjectionJobOptions("initial-sync")},sourceChange:{sourceTypes:["*"],events:["entity:created","entity:updated","entity:deleted"],requireInitialSync:!0,jobData:(Q)=>{if(Q.entityType==="series")return null;if(!Q.entity)return null;let w=wj(Q.entity),B=df0(Q.previousMetadata).seriesName;if(!w&&!B)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...w?{seriesName:w}:{},...B&&B!==w?{previousSeriesName:B}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new hr0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=B8.getInstance().register(gr0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=ya1.parse(Q);if(w.mode==="derive")return await this.projectAll(A),{success:!0};let B=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(B)await this.projectSource(B,w.previousSeriesName);else{let $=this.requireManager();for(let f of[w.seriesName,w.previousSeriesName])if(f)await $.cleanupOrphanedSeries(f)}return{success:!0}},validateAndParse:(Q)=>{let w=ya1.safeParse(Q??{});return w.success?w.data:null}}}requireManager(){if(!this.manager)throw Error("SeriesPlugin not registered");return this.manager}getSyncProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-sync:${A}`,metadata:{operationType:"data_processing",operationTarget:"series"}}}getSourceProjectionJobOptions(A){return{source:this.id,deduplication:"coalesce",deduplicationKey:`series-source:${A.entityType}:${A.id}`,metadata:{operationType:"data_processing",operationTarget:`series:${A.entityType}:${A.id}`}}}async projectSource(A,Q){await this.requireManager().handleEntityChange(A,Q)}async projectAll(A){await this.requireManager().syncAllSeries();let Q=new nf0(this.logger.child("SeriesGenerationHandler"),A),w=await A.entityService.listEntities({entityType:"series"});for(let B of w)try{if(!this.adapter.parseBody(B.content).description)this.logger.info(`Generating description for series: ${B.metadata.title}`),await Q.process({seriesId:B.id})}catch($){this.logger.error(`Failed to generate description for series: ${B.id}`,{error:$})}}}function Er0(){return new yr0}wA();L0();wA();D2();L0();wA();var Ea1=Z.enum(["generating","draft","queued","published","failed"]),Ta1=Z.enum(["generating","draft","queued","published","failed"]),Tr0="publishedAt is required when deck status is published",Sr0=(A)=>A.status==="published"&&!A.publishedAt,mr0=(A)=>{if(Sr0(A))throw Error(Tr0)},oD=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:Ea1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),R1$=Z.object({title:Z.string(),description:Z.string().optional(),status:Ea1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Sr0(A))return;Q.addIssue({code:Z.ZodIssueCode.custom,path:["publishedAt"],message:Tr0})}),TWw=Z.object({title:Z.string(),description:Z.string().optional(),status:Ta1,publishedAt:Z.string().datetime().optional(),coverImageId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}).superRefine((A,Q)=>{if(!Sr0(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:Tr0})}),SWw=Z.object({title:Z.string(),slug:Z.string().optional(),description:Z.string().optional(),author:Z.string().optional(),status:Ta1,publishedAt:Z.string().datetime().optional(),event:Z.string().optional(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional()}),Xy=PQ.extend({entityType:Z.literal("deck"),metadata:TWw}),rf0=Xy.extend({frontmatter:SWw,body:Z.string(),ogImageUrl:Z.string().optional()}),ir=rf0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class ur0 extends E2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:Xy,frontmatterSchema:oD,supportsCoverImage:!0})}validateSlideStructure(A){if(!/^---$/gm.test(A))throw Error("Invalid deck: markdown must contain slide separators (---) to be a valid presentation")}toMarkdown(A){let Q=this.extractBody(A.content);this.validateSlideStructure(Q);let w=this.parseFrontMatter(A.content,oD);mr0(w);let B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontmatter(A),w=this.extractBody(A);mr0(Q),this.validateSlideStructure(w);let B=Q.slug??H1(Q.title),$=Q.status;return{entityType:"deck",content:A,metadata:{slug:B,title:Q.title,description:Q.description,status:$,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
|
|
6987
6987
|
`,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var dr=new ur0;L0();xB();var mWw=Z.object({markdown:Z.string().describe("Markdown content with slide separators (---)"),deck:ir.optional()}),cr0=l1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:mWw,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:fi0,fullscreen:!0}});xB();L0();var lr0=Z.object({decks:Z.array(rf0)}),pr0=Z.object({decks:Z.array(ir),pageTitle:Z.string().optional(),pageLabel:Z.string().optional()});import{jsxDEV as ir0}from"preact/jsx-dev-runtime";var uWw="Presentations",dr0=({decks:A,pageLabel:Q})=>{let w=A.map(($)=>({id:$.id,url:$.url,title:$.frontmatter.title,date:$.frontmatter.publishedAt??$.created,description:$.frontmatter.description}));return ir0("div",{className:"deck-list bg-theme",children:ir0("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:ir0(gn,{label:Q&&Q!=="Decks"?Q:uWw,items:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};q5();class of0 extends $6{constructor(){super(lr0,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var nr0=l1({name:"deck-list",description:"List view of all presentation decks",schema:pr0,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new of0,layout:{component:dr0}});L0();wA();var cWw=Z.object({title:Z.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:Z.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:Z.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),Sa1=l1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:cWw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
|
|
6988
6988
|
|
|
6989
6989
|
Your task is to generate a complete slide deck based on the user's prompt.
|
|
@@ -7291,7 +7291,7 @@ ${X}`,templateName:"decks:description"})).description,await this.reportProgress(
|
|
|
7291
7291
|
color: var(--carousel-accent);
|
|
7292
7292
|
font-weight: 600;
|
|
7293
7293
|
}
|
|
7294
|
-
`}},void 0,!1,void 0,this),$.map((W,K)=>n4("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[n4("header",{className:"deck-carousel-header",children:n4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[n4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&n4(rWw,{children:[n4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),n4("span",{className:"wm-secondary",children:f.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),n4("div",{className:"deck-carousel-body",children:n4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(W.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),n4("footer",{className:"deck-carousel-footer",children:[n4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),n4("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[n4("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",n4("span",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as oWw,rm as sWw}from"fs/promises";import{tmpdir as aWw}from"os";import{join as tWw}from"path";l9();D2();var eWw=26214400,AKw=60000,pa1=20;class sr0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let w=QKw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>pa1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${pa1}`);let B=await this.getThemeMode(),$=await oWw(tWw(aWw(),"brain-deck-carousel-"));try{let f=await mZ({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:la1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),Y=await uZ({rootDir:$});try{return{type:"document",data:await this.renderPdf(Y.urlFor(f.urlPath),{maxBytes:eWw,timeoutMs:AKw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${wKw(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await sWw($,{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 QKw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=B.split(/^---$/gm).map((X)=>X.trim()).filter((X)=>X.length>0).map((X)=>({markdown:X}));return{title:$,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function wKw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}L0();import{jsxDEV as fKw}from"preact/jsx-dev-runtime";var sf0="og-image",BKw="decks:og-image",ia1=Z.object({title:Z.string().min(1),description:Z.string().optional(),event:Z.string().optional(),brandLabel:Z.string().optional(),slideCount:Z.number().int().positive().optional(),coverImageUrl:Z.string().optional()}),da1={name:BKw,pluginId:"decks",schema:ia1,renderers:{image:$Kw}};function $Kw(A){let Q=ia1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return fKw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}l9();D2();class ar0{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!==sf0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=M6(Q.content),$=oD.parse(w),f=YKw(B),Y=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),H={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...X?{coverImageUrl:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Aj({mediaPath:`/_media/og/deck/${Q.id}`,template:da1,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:`${XKw(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 YKw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function XKw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}wA();async function na1({entity:A,config:Q}){let w=Xy.parse(A),B=r2(w.content,oD),$=B.metadata;return{$type:"ai.rizom.brain.deck",title:$.title,...$.slug&&{slug:$.slug},...$.description&&{description:$.description},body:B.content,format:"text/markdown",...$.author&&{author:$.author},...$.event&&{event:$.event},...$.publishedAt&&{publishedAt:$.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function tr0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:_6["ai.rizom.brain.deck"],validate:!1,buildRecord:na1}}var ra1={name:"@brains/decks",version:"0.2.0-alpha.
|
|
7294
|
+
`}},void 0,!1,void 0,this),$.map((W,K)=>n4("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[n4("header",{className:"deck-carousel-header",children:n4("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[n4("span",{className:"wm-primary",children:f.primary},void 0,!1,void 0,this),f.secondary!==void 0&&n4(rWw,{children:[n4("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),n4("span",{className:"wm-secondary",children:f.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),n4("div",{className:"deck-carousel-body",children:n4("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(W.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),n4("footer",{className:"deck-carousel-footer",children:[n4("span",{className:"deck-carousel-footer-meta",children:B??Q},void 0,!1,void 0,this),n4("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[n4("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",n4("span",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as oWw,rm as sWw}from"fs/promises";import{tmpdir as aWw}from"os";import{join as tWw}from"path";l9();D2();var eWw=26214400,AKw=60000,pa1=20;class sr0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU,this.getThemeMode=Q.getThemeMode??(async()=>"dark")}async resolve(A){if(A.sourceEntityType!=="deck")return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let w=QKw(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>pa1)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${pa1}`);let B=await this.getThemeMode(),$=await oWw(tWw(aWw(),"brain-deck-carousel-"));try{let f=await mZ({outputDir:$,mediaPath:`/_media/carousel/${Q.id}`,template:la1,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:B},themeCSS:this.context.themeCSS}),Y=await uZ({rootDir:$});try{return{type:"document",data:await this.renderPdf(Y.urlFor(f.urlPath),{maxBytes:eWw,timeoutMs:AKw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${wKw(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await sWw($,{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 QKw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=typeof w.title==="string"?w.title:A.metadata.title,f=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=B.split(/^---$/gm).map((X)=>X.trim()).filter((X)=>X.length>0).map((X)=>({markdown:X}));return{title:$,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...f?{eyebrow:f}:{}}}function wKw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}L0();import{jsxDEV as fKw}from"preact/jsx-dev-runtime";var sf0="og-image",BKw="decks:og-image",ia1=Z.object({title:Z.string().min(1),description:Z.string().optional(),event:Z.string().optional(),brandLabel:Z.string().optional(),slideCount:Z.number().int().positive().optional(),coverImageUrl:Z.string().optional()}),da1={name:BKw,pluginId:"decks",schema:ia1,renderers:{image:$Kw}};function $Kw(A){let Q=ia1.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return fKw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}l9();D2();class ar0{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!==sf0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=M6(Q.content),$=oD.parse(w),f=YKw(B),Y=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),H={title:$.title,...$.description?{description:$.description}:{},...$.event?{event:$.event}:{},...f?{slideCount:f}:{},...X?{coverImageUrl:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Aj({mediaPath:`/_media/og/deck/${Q.id}`,template:da1,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:`${XKw(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 YKw(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function XKw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}wA();async function na1({entity:A,config:Q}){let w=Xy.parse(A),B=r2(w.content,oD),$=B.metadata;return{$type:"ai.rizom.brain.deck",title:$.title,...$.slug&&{slug:$.slug},...$.description&&{description:$.description},body:B.content,format:"text/markdown",...$.author&&{author:$.author},...$.event&&{event:$.event},...$.publishedAt&&{publishedAt:$.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function tr0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:_6["ai.rizom.brain.deck"],validate:!1,buildRecord:na1}}var ra1={name:"@brains/decks",version:"0.2.0-alpha.164",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 HKw=Z.object({prompt:Z.string(),event:Z.string().optional()}),WKw=Z.object({title:Z.string(),content:Z.string()});class er0 extends sQ{deps;entityType=dr.entityType;schema=dr.schema;adapter=dr;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",ra1,{},P7);this.deps=A}createGenerationHandler(A){return new or0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":cr0,"deck-list":nr0,generation:Sa1,description:ma1}}getDataSources(){return[new rr0(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=B8.getInstance().register(tr0()),this.logger.info("Decks plugin registered")}async onShutdown(){this.unregisterCarouselAttachmentProvider?.(),this.unregisterCarouselAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}deferPublishRegistration(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"deck",provider:{name:"internal",publish:async()=>({id:"internal"})},config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="deck")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"deck",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Deck not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=new Date().toISOString(),Y={...$,metadata:{...$.metadata,status:"published",publishedAt:f}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,result:{id:B}}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:SA($)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await Tr(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",ua1,new sr0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",sf0,new ar0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=HKw.parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
|
|
7295
7295
|
|
|
7296
7296
|
Note: This presentation is for "${w.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let w=WKw.parse(Q);return A.ai.generate({prompt:`Title: ${w.title}
|
|
7297
7297
|
|
|
@@ -7448,9 +7448,9 @@ ${w.content}`,templateName:"decks:description"})})}}function rr(){return new er0
|
|
|
7448
7448
|
background: transparent;
|
|
7449
7449
|
}
|
|
7450
7450
|
|
|
7451
|
-
`,$t1=()=>i5("style",{children:qKw},void 0,!1,void 0,this);import{jsxDEV as g2,Fragment as bKw}from"preact/jsx-dev-runtime";var QY0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>g2(bKw,{children:[g2(dQ,{title:A,description:Q},void 0,!1,void 0,this),g2($t1,{},void 0,!1,void 0,this),g2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[g2(wt1,{},void 0,!1,void 0,this),g2("div",{className:`${sD.wrap} ${f}`.trim(),children:[w,$&&g2(Bt1,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ft1=({docsCount:A,sectionsCount:Q,startDoc:w})=>g2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[g2("p",{className:`${sD.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),g2("h1",{className:`${sD.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",g2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g2("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),g2("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:[g2("div",{children:[g2("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),g2("div",{children:[g2("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),g2("div",{children:[g2("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),g2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&g2("a",{className:sD.primaryButton,href:Hy(w),children:"Start reading"},void 0,!1,void 0,this),g2("a",{className:sD.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Yt1=({groups:A})=>g2("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:[g2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),g2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>g2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[g2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Wy(w),"."]},void 0,!0,void 0,this),g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${AY0(w)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Xt1=({group:A,index:Q})=>g2("article",{className:"mb-16 last:mb-0",id:AY0(Q),children:[g2("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:[g2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Wy(Q),"."]},void 0,!0,void 0,this),g2("h2",{className:`${sD.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),g2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>g2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:g2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:Hy(w),children:[g2("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:w.metadata.title},void 0,!1,void 0,this),w.metadata.description&&g2("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:w.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},w.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zt1=({title:A})=>g2("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:[g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),g2("span",{children:"/"},void 0,!1,void 0,this),g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),g2("span",{children:"/"},void 0,!1,void 0,this),g2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ht1=({groups:A,activeGroupIndex:Q,activeSlug:w})=>g2("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:g2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[g2("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),g2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return g2("li",{className:f?"mb-[22px]":"mb-3.5",children:[g2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${f?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${AY0($)}`,children:[g2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Wy($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&g2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((Y)=>{let X=Y.metadata.slug===w;return g2("li",{children:g2("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)] ${X?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:Hy(Y),"aria-current":X?"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)]},B.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Wt1=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return g2("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?g2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:Hy(A),children:[g2("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),g2("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):g2("span",{},void 0,!1,void 0,this),Q&&g2("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:Hy(Q),children:[g2("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),g2("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 Ky}from"preact/jsx-dev-runtime";var Bo0=({docs:A})=>{let Q=or(A),w=ef0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return Ky(QY0,{title:"Documentation",description:"Brains documentation",children:[Ky(ft1,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),Ky("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:[Ky(Yt1,{groups:w},void 0,!1,void 0,this),Ky("div",{children:w.map((f,Y)=>Ky(Xt1,{group:f,index:Y},f.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as cZ}from"preact/jsx-dev-runtime";var $o0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=ef0(Q.length>0?Q:[A]),f=or(Q.length>0?Q:[A]),Y=f.findIndex((H)=>H.metadata.slug===A.metadata.slug),X=Math.max($.findIndex((H)=>H.docs.some((W)=>W.metadata.slug===A.metadata.slug)),0);return cZ(QY0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[cZ(Zt1,{title:A.metadata.title},void 0,!1,void 0,this),cZ("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[cZ(Ht1,{groups:$,activeGroupIndex:X,activeSlug:A.metadata.slug},void 0,!1,void 0,this),cZ("article",{className:"min-w-0",children:[cZ("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[cZ("p",{className:`${sD.label} m-0 mb-6 flex items-baseline gap-3`,children:[cZ("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Wy(X),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${f.length}`:""]},void 0,!0,void 0,this),cZ("h1",{className:`${sD.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&&cZ("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),cZ("div",{className:"docs-article__body",children:cZ(_9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),cZ(Wt1,{prevDoc:w,nextDoc:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var VKw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),JKw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),IKw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),sourcePath:Z.string(),description:Z.string().optional(),slug:Z.string().optional()}),FKw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),description:Z.string().optional(),slug:Z.string()}),sr=Z.object({id:Z.string(),entityType:Z.literal("doc"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:JKw,metadata:FKw,contentHash:Z.string(),frontmatter:IKw,body:Z.string()}),kKw=Z.object({docs:Z.array(sr),pagination:VKw.nullable(),baseUrl:Z.string().optional()}),LKw=Z.object({doc:sr,docs:Z.array(sr),prevDoc:sr.nullable(),nextDoc:sr.nullable()});function Kt1(){return{"doc-list":l1({name:"doc-list",description:"Documentation index template",schema:kKw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Bo0}}),"doc-detail":l1({name:"doc-detail",description:"Documentation page template",schema:LKw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:$o0}})}}var Ut1={name:"@brains/doc",version:"0.2.0-alpha.163",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 fo0 extends sQ{entityType=af0.entityType;schema=Zy;adapter=af0;constructor(){super("docs",Ut1,{},P7)}getTemplates(){return Kt1()}getDataSources(){return[new tf0(this.logger.child("DocDataSource"))]}}function ar(){return new fo0}wA();D2();L0();TB();L0();var Yo0=Z.literal("application/pdf"),Gt1=Z.enum(["pending","draft","failed"]),Xo0=Z.object({title:Z.string().optional(),mimeType:Yo0,filename:Z.string().min(1),pageCount:Z.number().int().min(0).optional(),status:Gt1.optional(),processingJobId:Z.string().optional(),processingError:Z.string().optional(),sourceEntityType:Z.string().min(1).optional(),sourceEntityId:Z.string().min(1).optional(),sourceUploadId:Z.string().optional(),sourceFilename:Z.string().optional(),sourceMediaType:Z.string().optional(),attachmentType:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional()}),Uy=PQ.extend({entityType:Z.literal("document"),content:Z.string().regex(/^data:application\/pdf;base64,.+$/),metadata:Xo0});function tr(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 wY0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function Zo0(A){let Q=Buffer.from(A).toString("latin1"),w=0,B=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let f of Q.matchAll(B)){let Y=parseInt(f[1]??f[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class BY0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Uy;toMarkdown(A){return A.content}fromMarkdown(A){return tr(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...w}=A,{mimeType:B}=tr(Q);return{entityType:"document",content:Q,metadata:{mimeType:B,...w}}}}var Hb=new BY0;async function ro0(A,Q={}){let w=Q.maxBytes??5000000;if(A.byteLength>w)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${w} bytes)`);let $=(await Promise.resolve().then(() => (k02(),F02))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),f=await $.promise;try{let Y=Q.maxPages??50;if(f.numPages>Y)throw Error(`Uploaded PDF has ${f.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let X=[];for(let W=1;W<=f.numPages;W+=1){let G=(await(await f.getPage(W)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(G.length>0)X.push(G)}let H=X.join(`
|
|
7451
|
+
`,$t1=()=>i5("style",{children:qKw},void 0,!1,void 0,this);import{jsxDEV as g2,Fragment as bKw}from"preact/jsx-dev-runtime";var QY0=({title:A,description:Q,children:w,detail:B=!1,footer:$=!1,contentClassName:f=""})=>g2(bKw,{children:[g2(dQ,{title:A,description:Q},void 0,!1,void 0,this),g2($t1,{},void 0,!1,void 0,this),g2("div",{className:`docs-handbook${B?" docs-handbook--detail":""}`,children:[g2(wt1,{},void 0,!1,void 0,this),g2("div",{className:`${sD.wrap} ${f}`.trim(),children:[w,$&&g2(Bt1,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ft1=({docsCount:A,sectionsCount:Q,startDoc:w})=>g2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[g2("p",{className:`${sD.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),g2("h1",{className:`${sD.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",g2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g2("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),g2("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:[g2("div",{children:[g2("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),g2("div",{children:[g2("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),g2("div",{children:[g2("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),g2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&g2("a",{className:sD.primaryButton,href:Hy(w),children:"Start reading"},void 0,!1,void 0,this),g2("a",{className:sD.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Yt1=({groups:A})=>g2("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:[g2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),g2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>g2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[g2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Wy(w),"."]},void 0,!0,void 0,this),g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${AY0(w)}`,children:Q.section},void 0,!1,void 0,this)]},Q.section,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Xt1=({group:A,index:Q})=>g2("article",{className:"mb-16 last:mb-0",id:AY0(Q),children:[g2("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:[g2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Wy(Q),"."]},void 0,!0,void 0,this),g2("h2",{className:`${sD.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),g2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>g2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:g2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:Hy(w),children:[g2("p",{className:"m-0 text-[22px] leading-[1.2] tracking-[-0.005em] transition-colors duration-150 group-hover:text-[var(--docs-accent)]",children:w.metadata.title},void 0,!1,void 0,this),w.metadata.description&&g2("p",{className:"mt-1.5 mb-0 max-w-[70ch] text-sm leading-[1.55] text-[var(--docs-text-muted)]",children:w.metadata.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},w.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Zt1=({title:A})=>g2("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:[g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),g2("span",{children:"/"},void 0,!1,void 0,this),g2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),g2("span",{children:"/"},void 0,!1,void 0,this),g2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Ht1=({groups:A,activeGroupIndex:Q,activeSlug:w})=>g2("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:g2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[g2("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),g2("ol",{className:"m-0 list-none p-0",children:A.map((B,$)=>{let f=$===Q;return g2("li",{className:f?"mb-[22px]":"mb-3.5",children:[g2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${f?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${AY0($)}`,children:[g2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Wy($),"."]},void 0,!0,void 0,this)," ",B.section]},void 0,!0,void 0,this),f&&g2("ol",{className:"mt-0.5 list-none p-0",children:B.docs.map((Y)=>{let X=Y.metadata.slug===w;return g2("li",{children:g2("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)] ${X?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:Hy(Y),"aria-current":X?"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)]},B.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Wt1=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return g2("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?g2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:Hy(A),children:[g2("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),g2("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):g2("span",{},void 0,!1,void 0,this),Q&&g2("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:Hy(Q),children:[g2("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),g2("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 Ky}from"preact/jsx-dev-runtime";var Bo0=({docs:A})=>{let Q=or(A),w=ef0(Q),$=Q.filter((f)=>f.metadata.slug!=="index")[0]??Q[0];return Ky(QY0,{title:"Documentation",description:"Brains documentation",children:[Ky(ft1,{docsCount:A.length,sectionsCount:w.length,startDoc:$},void 0,!1,void 0,this),Ky("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:[Ky(Yt1,{groups:w},void 0,!1,void 0,this),Ky("div",{children:w.map((f,Y)=>Ky(Xt1,{group:f,index:Y},f.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as cZ}from"preact/jsx-dev-runtime";var $o0=({doc:A,docs:Q,prevDoc:w,nextDoc:B})=>{let $=ef0(Q.length>0?Q:[A]),f=or(Q.length>0?Q:[A]),Y=f.findIndex((H)=>H.metadata.slug===A.metadata.slug),X=Math.max($.findIndex((H)=>H.docs.some((W)=>W.metadata.slug===A.metadata.slug)),0);return cZ(QY0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[cZ(Zt1,{title:A.metadata.title},void 0,!1,void 0,this),cZ("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[cZ(Ht1,{groups:$,activeGroupIndex:X,activeSlug:A.metadata.slug},void 0,!1,void 0,this),cZ("article",{className:"min-w-0",children:[cZ("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[cZ("p",{className:`${sD.label} m-0 mb-6 flex items-baseline gap-3`,children:[cZ("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Wy(X),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${f.length}`:""]},void 0,!0,void 0,this),cZ("h1",{className:`${sD.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&&cZ("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),cZ("div",{className:"docs-article__body",children:cZ(_9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),cZ(Wt1,{prevDoc:w,nextDoc:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};var VKw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),JKw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),IKw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),sourcePath:Z.string(),description:Z.string().optional(),slug:Z.string().optional()}),FKw=Z.object({title:Z.string(),section:Z.string(),order:Z.number().int(),description:Z.string().optional(),slug:Z.string()}),sr=Z.object({id:Z.string(),entityType:Z.literal("doc"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:JKw,metadata:FKw,contentHash:Z.string(),frontmatter:IKw,body:Z.string()}),kKw=Z.object({docs:Z.array(sr),pagination:VKw.nullable(),baseUrl:Z.string().optional()}),LKw=Z.object({doc:sr,docs:Z.array(sr),prevDoc:sr.nullable(),nextDoc:sr.nullable()});function Kt1(){return{"doc-list":l1({name:"doc-list",description:"Documentation index template",schema:kKw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Bo0}}),"doc-detail":l1({name:"doc-detail",description:"Documentation page template",schema:LKw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:$o0}})}}var Ut1={name:"@brains/doc",version:"0.2.0-alpha.164",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 fo0 extends sQ{entityType=af0.entityType;schema=Zy;adapter=af0;constructor(){super("docs",Ut1,{},P7)}getTemplates(){return Kt1()}getDataSources(){return[new tf0(this.logger.child("DocDataSource"))]}}function ar(){return new fo0}wA();D2();L0();TB();L0();var Yo0=Z.literal("application/pdf"),Gt1=Z.enum(["pending","draft","failed"]),Xo0=Z.object({title:Z.string().optional(),mimeType:Yo0,filename:Z.string().min(1),pageCount:Z.number().int().min(0).optional(),status:Gt1.optional(),processingJobId:Z.string().optional(),processingError:Z.string().optional(),sourceEntityType:Z.string().min(1).optional(),sourceEntityId:Z.string().min(1).optional(),sourceUploadId:Z.string().optional(),sourceFilename:Z.string().optional(),sourceMediaType:Z.string().optional(),attachmentType:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional()}),Uy=PQ.extend({entityType:Z.literal("document"),content:Z.string().regex(/^data:application\/pdf;base64,.+$/),metadata:Xo0});function tr(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 wY0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function Zo0(A){let Q=Buffer.from(A).toString("latin1"),w=0,B=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let f of Q.matchAll(B)){let Y=parseInt(f[1]??f[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class BY0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Uy;toMarkdown(A){return A.content}fromMarkdown(A){return tr(A),{entityType:"document",content:A}}extractMetadata(A){return A.metadata}parseFrontMatter(A,Q){return Q.parse({})}generateFrontMatter(A){return""}getBodyTemplate(){return""}createDocumentEntity(A){let{dataUrl:Q,...w}=A,{mimeType:B}=tr(Q);return{entityType:"document",content:Q,metadata:{mimeType:B,...w}}}}var Hb=new BY0;async function ro0(A,Q={}){let w=Q.maxBytes??5000000;if(A.byteLength>w)throw Error(`Uploaded PDF is too large for synchronous markdown extraction (${A.byteLength} bytes; max ${w} bytes)`);let $=(await Promise.resolve().then(() => (k02(),F02))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),f=await $.promise;try{let Y=Q.maxPages??50;if(f.numPages>Y)throw Error(`Uploaded PDF has ${f.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let X=[];for(let W=1;W<=f.numPages;W+=1){let G=(await(await f.getPage(W)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(G.length>0)X.push(G)}let H=X.join(`
|
|
7452
7452
|
|
|
7453
|
-
`).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await $.destroy()}}wA();l9();D2();L0();import{createHash as WUw}from"crypto";var KUw=26214400,UUw=20,GUw=60000,L02=80,DUw=10,zUw={renderUrl:Z.url().optional(),sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),documentId:Z.string().min(1).optional(),title:Z.string().min(1).optional(),filename:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),pageCount:Z.number().int().min(0).optional(),maxPageCount:Z.number().int().positive().optional(),maxBytes:Z.number().int().positive().optional(),timeoutMs:Z.number().int().positive().optional(),width:Z.union([Z.string(),Z.number()]).optional(),height:Z.union([Z.string(),Z.number()]).optional(),format:Z.string().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional()},N02=Z.object(zUw),lY0=N02.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 pY0 extends ew{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:lY0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??NU}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,w=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return w?`${Q}:${w.contentHash}`:Q}async process(A,Q,w){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let B=A.maxPageCount??UUw,$=A.maxBytes??KUw,f=A.timeoutMs??GUw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let Y=await this.getDedupKey(A),X=oo0(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let W=await this.findDocumentByDedupKey(Y,H?X:void 0);if(W&&(!H||W.id===X)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,W.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:W.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let W=await this.resolveDocumentAttachment(A,X,{timeoutMs:f,maxBytes:$}),K=W.data;if(K.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${K.byteLength} bytes`);let U=Zo0(K);if(U>B)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${B}`);let G=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?W.filename:`${X}.pdf`),b=Hb.createDocumentEntity({dataUrl:wY0(K),filename:q,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await Lf({entityService:this.context.entityService,entity:{...b,id:X}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,X,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:X,reused:!1}}catch(W){let K=SA(W);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await PG({entityService:this.context.entityService,entityType:"document",id:X,error:K}),W}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(B.type!=="document")throw Error(`Attachment provider returned ${B.type}; expected document`);return B}async findDocumentByDedupKey(A,Q){let w=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if(w.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:w.length,ids:w.map(($)=>$.id),preferredDocumentId:Q});let B=w.filter(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed");return B.find(($)=>$.id===Q)??B[0]}async attachDocumentToTarget(A,Q,w,B){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:f}=M6($.content),Y=Array.isArray(f.documents)?f.documents.filter(bUw):[],X=B.replace?await this.removeReferencesForSameSourceAttachment(Y,w,B):Y,H=X.some((W)=>W.id===w)?X:[...X,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:b4($.content,"documents",H)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let B=[];for(let $ of A){if($.id===Q){B.push($);continue}let f=await this.context.entityService.getEntity({entityType:"document",id:$.id});if(!f||!VUw(f,w))B.push($)}return B}}function oo0(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,B=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,$=A.replace===!0&&A.documentId===void 0?`${B}-${Date.now()}`:B;return qUw($)}function qUw(A){let Q=H1(A.replace(/[/:]+/g," "))||`document-${_02(A)}`;if(Q.length<=L02)return Q;let w=`-${_02(A)}`;return`${Q.slice(0,L02-w.length).replace(/-+$/g,"")}${w}`}function _02(A){return WUw("sha256").update(A).digest("hex").slice(0,DUw)}function bUw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function VUw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var P02={name:"@brains/document-plugin",version:"0.2.0-alpha.
|
|
7453
|
+
`).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await $.destroy()}}wA();l9();D2();L0();import{createHash as WUw}from"crypto";var KUw=26214400,UUw=20,GUw=60000,L02=80,DUw=10,zUw={renderUrl:Z.url().optional(),sourceEntityType:Z.string().min(1),sourceEntityId:Z.string().min(1),attachmentType:Z.string().min(1),documentId:Z.string().min(1).optional(),title:Z.string().min(1).optional(),filename:Z.string().min(1).optional(),dedupKey:Z.string().min(1).optional(),replace:Z.boolean().optional(),pageCount:Z.number().int().min(0).optional(),maxPageCount:Z.number().int().positive().optional(),maxBytes:Z.number().int().positive().optional(),timeoutMs:Z.number().int().positive().optional(),width:Z.union([Z.string(),Z.number()]).optional(),height:Z.union([Z.string(),Z.number()]).optional(),format:Z.string().optional(),targetEntityType:Z.string().min(1).optional(),targetEntityId:Z.string().min(1).optional()},N02=Z.object(zUw),lY0=N02.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 pY0 extends ew{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:lY0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??NU}async getDedupKey(A){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let Q=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,w=await this.context.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return w?`${Q}:${w.contentHash}`:Q}async process(A,Q,w){this.logger.debug("Starting document generation job",{jobId:Q,sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});let B=A.maxPageCount??UUw,$=A.maxBytes??KUw,f=A.timeoutMs??GUw;if(A.pageCount!==void 0&&A.pageCount>B)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${B}`);let Y=await this.getDedupKey(A),X=oo0(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let W=await this.findDocumentByDedupKey(Y,H?X:void 0);if(W&&(!H||W.id===X)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,W.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:W.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let W=await this.resolveDocumentAttachment(A,X,{timeoutMs:f,maxBytes:$}),K=W.data;if(K.byteLength>$)throw Error(`Rendered PDF exceeds maxBytes=${$}: ${K.byteLength} bytes`);let U=Zo0(K);if(U>B)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${B}`);let G=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?W.filename:`${X}.pdf`),b=Hb.createDocumentEntity({dataUrl:wY0(K),filename:q,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await Lf({entityService:this.context.entityService,entity:{...b,id:X}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,X,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:X,reused:!1}}catch(W){let K=SA(W);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await PG({entityService:this.context.entityService,entityType:"document",id:X,error:K}),W}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let B=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!B)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if(B.type!=="document")throw Error(`Attachment provider returned ${B.type}; expected document`);return B}async findDocumentByDedupKey(A,Q){let w=await this.context.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}});if(w.length>1)this.logger.warn("Multiple documents share dedupKey; using first",{dedupKey:A,count:w.length,ids:w.map(($)=>$.id),preferredDocumentId:Q});let B=w.filter(($)=>$.metadata.status!=="pending"&&$.metadata.status!=="failed");return B.find(($)=>$.id===Q)??B[0]}async attachDocumentToTarget(A,Q,w,B){let $=await this.context.entityService.getEntity({entityType:A,id:Q});if(!$)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:f}=M6($.content),Y=Array.isArray(f.documents)?f.documents.filter(bUw):[],X=B.replace?await this.removeReferencesForSameSourceAttachment(Y,w,B):Y,H=X.some((W)=>W.id===w)?X:[...X,{id:w}];await this.context.entityService.updateEntity({entity:{...$,content:b4($.content,"documents",H)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let B=[];for(let $ of A){if($.id===Q){B.push($);continue}let f=await this.context.entityService.getEntity({entityType:"document",id:$.id});if(!f||!VUw(f,w))B.push($)}return B}}function oo0(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,B=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,$=A.replace===!0&&A.documentId===void 0?`${B}-${Date.now()}`:B;return qUw($)}function qUw(A){let Q=H1(A.replace(/[/:]+/g," "))||`document-${_02(A)}`;if(Q.length<=L02)return Q;let w=`-${_02(A)}`;return`${Q.slice(0,L02-w.length).replace(/-+$/g,"")}${w}`}function _02(A){return WUw("sha256").update(A).digest("hex").slice(0,DUw)}function bUw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function VUw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var P02={name:"@brains/document-plugin",version:"0.2.0-alpha.164",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 IUw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
|
|
7454
7454
|
% Pending document placeholder
|
|
7455
7455
|
%%EOF
|
|
7456
7456
|
`).toString("base64")}`,FUw=Z.object({}).catchall(Z.unknown()).transform(()=>({})),so0={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function kUw(A,Q){let w=A.title?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}function LUw(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function _Uw(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 ao0 extends Aw{entityType=Hb.entityType;schema=Uy;adapter=Hb;pluginContext;constructor(){super("document",P02,{},FUw)}async onRegister(A){this.pluginContext=A,A.entities.register(this.entityType,this.schema,this.adapter,{embeddable:!1}),A.entities.registerCreateInterceptor(this.entityType,(Q)=>this.interceptCreate(Q)),A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["application/pdf"],handler:async(Q)=>{let w=await this.promoteUpload({entityType:this.entityType,...Q.title!==void 0?{title:Q.title}:{},from:Q.upload},A);return w.kind==="handled"?w.result:{success:!1,error:"Document upload save was not handled"}}}),A.jobs.registerHandler("generate",new pY0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===so0.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 w=lY0.parse({sourceEntityType:A.from.sourceEntityType,sourceEntityId:A.from.sourceEntityId,attachmentType:A.from.attachmentType,...A.title&&{title:A.title},...A.replace===!0&&{replace:!0},...A.targetEntityType&&{targetEntityType:A.targetEntityType},...A.targetEntityId&&{targetEntityId:A.targetEntityId}}),B=await this.getDedupKey(w,Q),$=w.replace===!0?void 0:await this.findExistingDocument(B,Q),f=$?.id??oo0(w,B);if(!$)await this.createPendingDocument(Q,{id:f,title:w.title??f,filename:`${f}.pdf`,sourceEntityType:w.sourceEntityType,sourceEntityId:w.sourceEntityId,attachmentType:w.attachmentType,dedupKey:B});let Y=await Q.jobs.enqueue({type:"generate",data:{...w,dedupKey:B,documentId:f}}),X=`${f}.pdf`;return{kind:"handled",result:{success:!0,data:{entityId:f,jobId:Y,status:"generating",attachment:{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${encodeURIComponent(f)}`,downloadUrl:`/api/chat/attachments/document?id=${encodeURIComponent(f)}&download=1`,filename:X,source:{entityType:"document",entityId:f,attachmentType:w.attachmentType}}}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==so0.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let B;try{B=await Q.uploads.scoped(so0).read(w.id)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(B.record.mediaType!=="application/pdf")return{kind:"handled",result:{success:!1,error:"Only PDF uploads can be promoted to document entities"}};let $=kUw(A,B.record.filename),f=H1($);if(!f)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(),X=Hb.createDocumentEntity({dataUrl:LUw(B.record.mediaType,B.content),filename:B.record.filename,title:$,status:"draft",sourceUploadId:w.id,sourceFilename:B.record.filename,sourceMediaType:B.record.mediaType,attachmentType:"uploaded",dedupKey:`upload:${w.kind}:${w.id}`}),H=await Q.entityService.createEntity({entity:{id:f,...X,created:Y,updated:Y},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"created",attachment:_Uw({entityId:H.entityId,filename:B.record.filename})}}}}async createPendingDocument(A,Q){let w=new Date().toISOString(),B=Hb.createDocumentEntity({dataUrl:IUw,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await LL({entityService:A.entityService,entity:{id:Q.id,...B,created:w,updated:w}})}async getDedupKey(A,Q){if(A.dedupKey!==void 0)return A.dedupKey;if(A.renderUrl!==void 0)return`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl}`;let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:resolved-attachment`,B=await Q.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return B?`${w}:${B.contentHash}`:w}async findExistingDocument(A,Q){return(await Q.entityService.listEntities({entityType:"document",options:{filter:{metadata:{dedupKey:A}}}}))[0]}async getInstructions(){return"Document entities store durable file artifacts such as PDFs. Uploaded PDFs are raw document files, not decks. Source-derived document artifacts are durable documents backed by registered attachment providers such as carousel or printable. Generate saved PDF artifacts through system_generate with source.kind attachment; preserve raw uploaded PDFs with system_create source.kind upload and transform preserve."}async getTools(){return[]}}function to0(){return new ao0}wA();L0();wA();L0();var j02=Z.enum(["generating","failed"]),NUw=Z.enum(["generating","failed"]),vF=Z.object({title:Z.string().optional(),status:j02.optional(),error:Z.string().optional()}),PUw=Z.object({title:Z.string(),status:j02.optional(),error:Z.string().optional()}),jUw=Z.object({title:Z.string(),status:NUw.optional(),error:Z.string().optional()}),RF=PQ.extend({entityType:Z.literal("note"),metadata:jUw}),MUw=RF.extend({frontmatter:vF,body:Z.string()});wA();L0();var xUw=Z.record(Z.string(),Z.unknown());class eo0 extends E2{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:RF,frontmatterSchema:vF})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,vF);if(Object.values(w).some((B)=>B!==void 0))return this.buildMarkdown(Q,w)}catch{}return Q}fromMarkdown(A){let Q=this.parseMarkdownFrontmatter(A),w=Q.title??this.extractH1(A)??"Untitled";return{content:A,entityType:"note",metadata:{title:w,...Q.status&&{status:Q.status},...Q.error&&{error:Q.error}}}}parseNoteFrontmatter(A){return this.parseMarkdownFrontmatter(A.content)}parseMarkdownFrontmatter(A){try{return this.parseFrontMatter(A,vF)}catch{return{}}}buildStub(A){let Q={title:A.title,status:"generating"};return{content:this.buildMarkdown("",Q),metadata:{title:A.title,status:"generating"}}}createNoteContent(A,Q){try{let w=this.parseFrontMatter(Q,xUw);if(Object.keys(w).length===0)return Q;let B={...w,title:w.title??A},$=this.extractBody(Q);return this.buildMarkdown($,B)}catch{return Q}}extractH1(A){return A.match(/^#\s+(.+)$/m)?.[1]?.trim()??null}}var Gb=new eo0;L0();var As0=Z.object({defaultPrompt:Z.string().default("Create a note summarizing key concepts from my knowledge base")});L0();wA();var M02=Z.object({title:Z.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:Z.string().describe("Note content in markdown format with clear organization and structure")}),Qs0=l1({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:M02,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
|
|
@@ -7468,7 +7468,7 @@ title: ${JSON.stringify(A)}
|
|
|
7468
7468
|
---
|
|
7469
7469
|
|
|
7470
7470
|
${Q.trim()}
|
|
7471
|
-
`}var CUw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},gUw=Z.object({uploadId:Z.string().min(1),entityId:Z.string().min(1),title:Z.string().optional()});class Bs0 extends ew{context;constructor(A,Q){super(A,{schema:gUw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(CUw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await R02({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),Y=Gb.fromMarkdown($.content),X=await Lf({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:$.content,metadata:{title:$.title,...Y.metadata},created:f,updated:f}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:X.entityId,status:"created"}}catch(B){return await this.markStubFailed(A.entityId,SA(B)),f$.failure(B)}}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:b4(b4(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}}})}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}}}wA();async function h02({entity:A,config:Q}){let w=RF.parse(A),B=r2(w.content,vF);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function $s0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:_6["ai.rizom.brain.note"],validate:!1,buildRecord:h02}}var C02={name:"@brains/note",version:"0.2.0-alpha.
|
|
7471
|
+
`}var CUw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},gUw=Z.object({uploadId:Z.string().min(1),entityId:Z.string().min(1),title:Z.string().optional()});class Bs0 extends ew{context;constructor(A,Q){super(A,{schema:gUw,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let B=await this.context.uploads.scoped(CUw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let $=await R02({upload:B,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let f=new Date().toISOString(),Y=Gb.fromMarkdown($.content),X=await Lf({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:$.content,metadata:{title:$.title,...Y.metadata},created:f,updated:f}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:X.entityId,status:"created"}}catch(B){return await this.markStubFailed(A.entityId,SA(B)),f$.failure(B)}}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:b4(b4(w.content,"status","failed"),"error",Q),metadata:{...w.metadata,status:"failed",error:Q}}})}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}}}wA();async function h02({entity:A,config:Q}){let w=RF.parse(A),B=r2(w.content,vF);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"note",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function $s0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:_6["ai.rizom.brain.note"],validate:!1,buildRecord:h02}}var C02={name:"@brains/note",version:"0.2.0-alpha.164",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 g02={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},EUw=Z.object({prompt:Z.string()});class fs0 extends sQ{entityType=Gb.entityType;schema=RF;adapter=Gb;unregisterAtprotoProjection;constructor(A={}){super("note",C02,A,As0)}async interceptCreate(A,Q,w){if(A.from?.kind!==g02.refKind)return{kind:"continue",input:A};if(A.transform!=="extract-markdown")return{kind:"handled",result:{success:!1,error:'Importing an upload as a note requires transform: "extract-markdown"'}};let B=A.from.id,$;try{$=await w.uploads.scoped(g02).readRecord(B)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!v02($.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let f=ws0({filename:$.filename,...A.title!==void 0?{title:A.title}:{}}),Y=Gb.buildStub({id:f.id,title:f.title}),X=new Date().toISOString(),H=await w.entityService.createEntity({entity:{id:f.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:X,updated:X},options:{deduplicateId:!0}}),W=await w.jobs.enqueue({type:"upload-import",data:{uploadId:B,entityId:H.entityId,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"generating",jobId:W}}}}catch(f){return{kind:"handled",result:{success:!1,error:f instanceof Error?f.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new iY0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:Qs0}}async onRegister(A){A.jobs.registerHandler("upload-import",new Bs0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=EUw.parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=B8.getInstance().register($s0())}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 Wj(A={}){return new fs0(A)}wA();L0();wA();var y02=Z.object({ref:Z.string(),label:Z.string()}),E02=Z.enum(["pending","draft","published"]),TUw=Z.enum(["pending","draft","published"]),_o=Z.object({status:E02,title:Z.string(),url:Z.string().url(),description:Z.string().optional(),domain:Z.string(),capturedAt:Z.string().datetime(),source:y02}),SUw=_o.pick({title:!0,status:!0}),mUw=Z.object({title:Z.string(),status:TUw}),Kj=PQ.extend({entityType:Z.literal("link"),metadata:mUw});D2();L0();L0();var Ys0=Z.object({enableSummarization:Z.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:Z.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});wA();class hF extends E2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:Kj,frontmatterSchema:_o})}createLinkContent(A){let Q={status:A.status,title:A.title,url:A.url,description:A.description,domain:A.domain,capturedAt:A.capturedAt,source:A.source},w=A.summary??"";return this.buildMarkdown(w,Q)}parseLinkContent(A){return{frontmatter:this.parseFrontMatter(A,_o),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 Py=new hF;wA();L0();var uUw=Z.object({success:Z.boolean().describe("Set to true if you can extract meaningful content. Set to false only if the provided content is empty, just an error message, or otherwise unusable."),error:Z.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:Z.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:Z.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:Z.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),T02=l1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:uUw,basePrompt:`You are an expert at extracting key information from webpage content.
|
|
7472
7472
|
|
|
7473
7473
|
You will receive webpage content in markdown format. Your job is to extract structured information from it.
|
|
7474
7474
|
|
|
@@ -7490,7 +7490,7 @@ Accuracy rules:
|
|
|
7490
7490
|
|
|
7491
7491
|
`))return{success:!1,error:Y.trim(),errorType:"fetch_failed"};return{success:!0,content:Y}}catch(w){return this.handleFetchError(w,A)}}handleHttpError(A,Q){if(A===400)return{success:!1,error:`Invalid or non-existent URL: ${Q}`,errorType:"url_not_found"};if(A===404)return{success:!1,error:`Page not found: ${Q}`,errorType:"url_not_found"};if(A>=500)return{success:!1,error:`Server error while fetching ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`HTTP ${A} error while fetching ${Q}`,errorType:"fetch_failed"}}handleFetchError(A,Q){if(A instanceof Error){if(A.name==="AbortError")return{success:!1,error:`Request timeout while fetching ${Q}`,errorType:"url_unreachable"};if(A.message.includes("ENOTFOUND")||A.message.includes("getaddrinfo"))return{success:!1,error:`Domain not found: ${new URL(Q).hostname}`,errorType:"url_not_found"};if(A.message.includes("ECONNREFUSED")||A.message.includes("ETIMEDOUT"))return{success:!1,error:`Could not connect to ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`Failed to fetch ${Q}: ${A.message}`,errorType:"fetch_failed"}}return{success:!1,error:`Unknown error fetching ${Q}`,errorType:"fetch_failed"}}}import{createHash as nUw}from"crypto";class CF{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(CF.URL_PATTERN)??[];return[...new Set(Q)]}static normalizeUrl(A){try{let Q=new URL(A),w=Q.pathname.replace(/\/$/,"")||"/";return`${Q.protocol}//${Q.host}${w}`}catch{return A}}static generateEntityId(A){let Q=this.normalizeUrl(A),w=nUw("sha256").update(Q).digest("hex");try{return`${new URL(Q).hostname.replace(/\./g,"-")}-${w.substring(0,6)}`}catch{return w.substring(0,12)}}static isValidUrl(A){try{let Q=new URL(A);return["http:","https:"].includes(Q.protocol)}catch{return!1}}}wA();L0();T6();var rUw=Z.object({interfaceId:Z.string().optional(),userId:Z.string().optional(),channelId:Z.string().optional(),channelName:Z.string().optional(),timestamp:Z.string().optional()}),oUw=Z.object({url:Z.url(),metadata:rUw.optional()}),C$$=Z.object({success:Z.boolean(),entityId:Z.string().optional(),title:Z.string().optional(),url:Z.string().optional(),status:Z.enum(["pending","draft","published"]).optional(),error:Z.string().optional()});class nY0 extends ew{context;linkAdapter;urlFetcher;constructor(A,Q,w){super(A,{schema:oUw,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new hF,this.urlFetcher=new jy(w?.jinaApiKey?{jinaApiKey:w.jinaApiKey}:void 0)}async process(A,Q,w){let{url:B,metadata:$}=A;try{await w.report({progress:oQ.START,total:100,message:"Starting link capture"});let f=CF.generateEntityId(B);await w.report({progress:oQ.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity({entityType:"link",id:f});if(Y){let{frontmatter:q}=this.linkAdapter.parseLinkContent(Y.content),b=Y.metadata.status;if(b!=="pending")return this.logger.info("Link already captured, returning existing",{url:B,entityId:f}),{success:!0,entityId:Y.id,title:q.title,url:B,status:b};this.logger.info("Pending link exists, completing extraction",{url:B,entityId:f})}let X=this.resolveSource($),H=new Date().toISOString();await w.report({progress:oQ.FETCH,total:100,message:"Fetching webpage content"});let W=await this.urlFetcher.fetch(B);if(!W.success){if(W.errorType==="url_not_found"||W.errorType==="url_unreachable"){this.logger.warn("Link URL not accessible",{url:B,errorType:W.errorType,error:W.error});let q=new URL(B).hostname,b=`Could not capture link: ${W.error}`,J=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:b,summary:b,domain:q,capturedAt:H,source:X});return await Lf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:J,metadata:{status:"pending",title:q}}}),{success:!1,entityId:f,title:q,url:B,status:"pending",error:b}}}await w.report({progress:oQ.PROCESS,total:100,message:"Extracting content with AI"});let K=await this.context.ai.generate({templateName:"link:extraction",prompt:W.success?`Extract structured information from this webpage content:
|
|
7492
7492
|
|
|
7493
|
-
${W.content}`:`The URL ${B} could not be fetched. Return success: false with error: "${W.error}"`,data:{url:B,hasContent:W.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:oQ.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:oQ.SAVE,total:100,message:"Saving link as pending"});let b=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:H,source:X}),J=await Lf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:b,metadata:{status:"pending",title:q}}});return await w.report({progress:oQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:J.entityId,title:q,url:B,status:"pending"}}await w.report({progress:oQ.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:H,source:X}),G=await Lf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:oQ.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:G.entityId,title:K.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),f$.failure(f)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let B=A?.interfaceId??"cli";return{ref:`${B}:local`,label:B.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function u02({entity:A,config:Q}){let w=Kj.parse(A),{frontmatter:B,summary:$}=Py.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:B.title,url:B.url,...B.description&&{description:B.description},...$&&{summary:$},domain:B.domain,capturedAt:B.capturedAt,source:B.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Us0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:_6["ai.rizom.brain.link"],validate:!1,buildRecord:u02}}var c02={name:"@brains/link",version:"0.2.0-alpha.
|
|
7493
|
+
${W.content}`:`The URL ${B} could not be fetched. Return success: false with error: "${W.error}"`,data:{url:B,hasContent:W.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:oQ.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL(B).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:B}),await w.report({progress:oQ.SAVE,total:100,message:"Saving link as pending"});let b=this.linkAdapter.createLinkContent({status:"pending",title:q,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:H,source:X}),J=await Lf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:b,metadata:{status:"pending",title:q}}});return await w.report({progress:oQ.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:J.entityId,title:q,url:B,status:"pending"}}await w.report({progress:oQ.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:B,description:K.description,summary:K.summary,domain:new URL(B).hostname,capturedAt:H,source:X}),G=await Lf({entityService:this.context.entityService,entity:{id:f,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:oQ.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:G.entityId,title:K.title,url:B,status:"draft"}}catch(f){return this.logger.error("Link capture job failed",{error:f,jobId:Q,data:A}),f$.failure(f)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let B=A?.interfaceId??"cli";return{ref:`${B}:local`,label:B.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function u02({entity:A,config:Q}){let w=Kj.parse(A),{frontmatter:B,summary:$}=Py.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:B.title,url:B.url,...B.description&&{description:B.description},...$&&{summary:$},domain:B.domain,capturedAt:B.capturedAt,source:B.source,...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"link",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Us0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:_6["ai.rizom.brain.link"],validate:!1,buildRecord:u02}}var c02={name:"@brains/link",version:"0.2.0-alpha.164",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 aUw=Z.object({url:Z.url()});class Gs0 extends sQ{entityType=Py.entityType;schema=Kj;adapter=Py;shell;unregisterAtprotoProjection;constructor(A={}){super("link",c02,A,Ys0)}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 nY0(this.logger.child("LinkCaptureJobHandler"),this.context,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0),this.id),Q}async interceptCreate(A,Q,w){if(A.content)try{let f=this.adapter.fromMarkdown(A.content).metadata,Y=typeof f?.title==="string"?f.title:void 0,X=typeof f?.status==="string"?f.status:void 0,H=this.extractFirstUrl(A.content);if(Y&&X&&H){let W=H1(H)||H1(Y)||`${A.entityType}-${Date.now()}`,K=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await w.entityService.createEntity({entity:{id:W,entityType:A.entityType,content:A.content,metadata:{title:Y,status:X},created:K,updated:K}})).entityId,status:"created"}}}}}catch{}let B=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if(B){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let $=await this.createPendingLink(B,A.title,Q,w),f=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:B,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:$,status:"generating",jobId:f}}}}catch($){return{kind:"handled",result:{success:!1,error:$ instanceof Error?$.message:"Failed to queue link capture job"}}}}if(A.content)return{kind:"handled",result:{success:!1,error:"Direct link creation requires full link markdown/frontmatter, or provide a URL to capture."}};if(A.prompt)return{kind:"handled",result:{success:!1,error:"Link creation requires a URL in the prompt, content, or title, or full link markdown content for direct creation."}};return{kind:"continue",input:A}}createGenerationHandler(A){return new nY0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:T02,"link-list":S02,"link-detail":m02}}getDataSources(){return[new Ks0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=B8.getInstance().register(Us0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=aUw.parse(Q),$=await new jy(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(w);if(!$.success)return{success:!1,error:$.error,errorType:$.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
|
|
7494
7494
|
|
|
7495
7495
|
${$.content}`,data:{url:w,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,w,B){let $=CF.generateEntityId(A),f=new URL(A),Y=new Date().toISOString(),X=Q?.trim()?Q.trim():f.hostname,H=this.adapter.createLinkContent({status:"pending",title:X,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:f.hostname,capturedAt:Y,source:this.resolveSource(w)});return(await LL({entityService:B.entityService,entity:{id:$,entityType:"link",content:H,metadata:{status:"pending",title:X},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[w]=CF.extractUrls(Q);if(w)return w}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function l02(A={}){return new Gs0(A)}var Uj=l02;L0();var tUw=Z.object({conversationId:Z.string().optional(),interfaceId:Z.string().optional(),userId:Z.string().optional(),messageId:Z.string().optional(),timestamp:Z.string().optional()}),Z8$=Z.object({id:Z.string().optional(),metadata:tUw.optional()});wA();L0();xB();L0();wA();var p02=Z.enum(["generating","draft","published","failed"]),i02=Z.enum(["generating","draft","published","failed"]),G7=Z.object({title:Z.string(),slug:Z.string().optional(),status:p02,publishedAt:Z.string().datetime().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.string().url().optional()}),eUw=G7.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:Z.string(),error:Z.string().optional()}),AGw=Z.object({title:Z.string(),status:i02,publishedAt:Z.string().datetime().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),QGw=Z.object({title:Z.string(),slug:Z.string().optional(),status:i02,publishedAt:Z.string().datetime().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.string().url().optional()}),gF=PQ.extend({entityType:Z.literal("project"),metadata:AGw}),rY0=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),Po=gF.extend({frontmatter:QGw,body:Z.string(),structuredContent:rY0.optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional()}),wGw=Po.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),BGw=Po.extend({url:Z.string(),typeLabel:Z.string(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();D2();q5();class Ds0 extends $6{constructor(){super(rY0,{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 zs0=new Ds0;class qs0 extends E2{constructor(){super({entityType:"project",purpose:"A project record in the user's portfolio.",schema:gF,frontmatterSchema:G7,supportsCoverImage:!0,bodyFormatter:zs0})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,G7),B={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,B)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,G7),w=Q.slug??H1(Q.title);return{content:A,entityType:"project",metadata:{title:Q.title,slug:w,status:Q.status,publishedAt:Q.publishedAt,year:Q.year}}}parseProjectFrontmatter(A){return this.parseFrontMatter(A.content,G7)}parseStructuredContent(A){return zs0.parse(this.extractBody(A.content))}createProjectContent(A,Q){let w=zs0.format(Q);return this.buildMarkdown(w,A)}buildStub(A){let Q=new Date().getUTCFullYear(),w={title:A.title,slug:A.id,status:"generating",description:"",year:Q};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:A.id,status:"generating",year:Q}}}}var Gj=new qs0;L0();var bs0=Z.looseObject({});import{jsxDEV as sZ,Fragment as fGw}from"preact/jsx-dev-runtime";var $Gw=({project:A})=>{let{frontmatter:Q,url:w,coverImageUrl:B}=A;return sZ(z6,{href:w,children:[B&&sZ("img",{src:B,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),sZ(Z7,{children:Q.title},void 0,!1,void 0,this),sZ("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},Vs0=({projects:A,pageTitle:Q,pagination:w,baseUrl:B="/projects"})=>{let $=Q??"Projects",f=w?.totalItems??A.length,Y=`Browse all ${f} ${f===1?"project":"projects"}`;return sZ(fGw,{children:[sZ(dQ,{title:$,description:Y},void 0,!1,void 0,this),sZ("div",{className:"project-list bg-theme",children:sZ("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[sZ("h1",{className:"text-4xl font-bold text-heading mb-12",children:$},void 0,!1,void 0,this),sZ("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((X)=>sZ($Gw,{project:X},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&sZ("div",{className:"mt-12",children:sZ(oq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as n6,Fragment as d02}from"preact/jsx-dev-runtime";var YGw=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return n6("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:n6("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?n6(z6,{href:A.url,variant:"compact",children:[n6("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),n6("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):n6("div",{},void 0,!1,void 0,this),Q&&n6(z6,{href:Q.url,variant:"compact",className:"md:text-right",children:[n6("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),n6("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)},oY0=({title:A,content:Q})=>{if(!Q)return null;return n6("section",{className:"mb-12",children:[n6("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),n6(_9,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},Js0=({project:A,prevProject:Q,nextProject:w})=>{let{frontmatter:B,structuredContent:$,metadata:f,coverImageUrl:Y}=A,X=A.ogImageUrl??Y;return n6(d02,{children:[n6(dQ,{title:B.title,description:B.description,...X?{ogImage:X}:{},ogType:"article"},void 0,!1,void 0,this),n6("article",{className:"project-detail",children:n6("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:n6("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&n6(nq,{src:Y,alt:B.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),n6("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:B.title},void 0,!1,void 0,this),n6("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[n6("span",{className:"text-sm",children:f.year},void 0,!1,void 0,this),B.url&&n6(d02,{children:[n6("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),n6("a",{href:B.url,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:"View Project"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),n6("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:B.description},void 0,!1,void 0,this),$&&n6("div",{className:"case-study",children:[n6(oY0,{title:"Context",content:$.context},void 0,!1,void 0,this),n6(oY0,{title:"Problem",content:$.problem},void 0,!1,void 0,this),n6(oY0,{title:"Solution",content:$.solution},void 0,!1,void 0,this),n6(oY0,{title:"Outcome",content:$.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n6(YGw,{prevProject:Q,nextProject:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};L0();wA();var XGw=Z.object({title:Z.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:Z.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:Z.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:Z.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:Z.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:Z.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),Is0=l1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:XGw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
|
|
7496
7496
|
|
|
@@ -7666,7 +7666,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7666
7666
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7667
7667
|
}
|
|
7668
7668
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
7669
|
-
`}},void 0,!1,void 0,this),O9("section",{className:"project-shell",children:[O9("header",{className:"project-hero",children:[O9("div",{className:"project-index",children:[Q.brandLabel&&O9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&O9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),O9("div",{className:"project-title-panel",children:[O9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),O9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&O9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),O9("div",{className:"printable-meta",children:[Q.year&&O9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&O9("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&&O9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),O9(_9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&O9("footer",{className:"printable-footer",children:[O9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?O9("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 qGw=26214400,bGw=60000;class Ls0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==tY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=VGw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await UGw(zGw(DGw(),"brain-project-printable-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:o02,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:qGw,timeoutMs:bGw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${JGw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await GGw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=G7.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function VGw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=G7.parse(w);return{title:$.title,body:B,...$.description?{description:$.description}:{},year:$.year,...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.url?{url:$.url,canonicalUrl:$.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function JGw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}l9();D2();L0();import{jsxDEV as kGw}from"preact/jsx-dev-runtime";var eY0="og-image",IGw="portfolio:og-image",s02=Z.object({title:Z.string().min(1),description:Z.string().optional(),year:Z.number().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),a02={name:IGw,pluginId:"portfolio",schema:s02,renderers:{image:FGw}};function FGw(A){let Q=s02.parse(A);return kGw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class _s0{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!==eY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=M6(Q.content),B=G7.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),Y={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await Aj({mediaPath:`/_media/og/project/${Q.id}`,template:a02,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:`${LGw(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 LGw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}var t02={name:"@brains/portfolio",version:"0.2.0-alpha.163",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 NGw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),PGw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),e02=Z.enum(["generating","draft","published","failed"]),jGw=Z.object({title:Z.string(),slug:Z.string().optional(),status:e02,publishedAt:Z.string().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.url().optional()}),MGw=Z.object({title:Z.string(),status:e02,publishedAt:Z.string().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),xGw=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),AX0=Z.object({id:Z.string(),entityType:Z.literal("project"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:PGw,metadata:MGw,contentHash:Z.string(),frontmatter:jGw,body:Z.string(),structuredContent:xGw.optional(),url:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),OGw=Z.object({projects:Z.array(AX0),pageTitle:Z.string().optional(),pagination:NGw.nullable(),baseUrl:Z.string().optional()}),vGw=Z.object({prompt:Z.string(),year:Z.number()});function RGw(A,Q){for(let w of[A,Q]){let B=w?.match(/\b(19\d{2}|20\d{2})\b/);if(B?.[1])return Number(B[1])}return null}class Ns0 extends sQ{entityType="project";schema=gF;adapter=Gj;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",t02,A,bs0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=RGw(A.title,A.prompt);if(!B)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await w.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:B},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new sY0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":l1({name:"project-list",description:"Portfolio project list page template",schema:OGw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Vs0}}),"project-detail":l1({name:"project-detail",description:"Individual project case study template",schema:Z.object({project:AX0,prevProject:AX0.nullable(),nextProject:AX0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Js0}}),generation:Is0}}getDataSources(){return[new aY0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",tY0,new Ls0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",eY0,new _s0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=B8.getInstance().register(ks0())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let w=vGw.parse(Q);return A.ai.generate({prompt:Fs0(w),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="project")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"project",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Project not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=r2($.content,G7),Y=new Date().toISOString(),X=F5(f.content,{...f.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...$,content:X,metadata:{...$.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:Y}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:SA($)}})}return{success:!0}})}}function Ps0(A={}){return new Ns0(A)}wA();L0();xB();L0();wA();var AA2=Z.enum(["available","early access","coming soon","planned"]),QA2=Z.enum(["available","early access","coming soon","planned"]),wA2=Z.object({title:Z.string(),description:Z.string()}),OW=Z.object({name:Z.string(),availability:AA2,order:Z.number(),ogImageId:Z.string().optional()}),QX0=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(wA2).min(1).max(6),story:Z.string()}),Y9$=OW.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),hGw=Z.object({name:Z.string(),availability:QA2,order:Z.number(),slug:Z.string()}),CGw=Z.object({name:Z.string(),availability:QA2,order:Z.number(),ogImageId:Z.string().optional()}),My=PQ.extend({entityType:Z.literal("product"),metadata:hGw}),wX0=My.extend({frontmatter:CGw,body:QX0,labels:Z.record(Z.string(),Z.string()),ogImageUrl:Z.string().optional()}),gGw=wX0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()});wA();D2();q5();class xy extends $6{constructor(){super(QX0,{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 js0 extends E2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:My,frontmatterSchema:OW,bodyFormatter:new xy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,OW);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,OW),w=H1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var BX0=new js0;L0();wA();var BA2=Z.object({title:Z.string(),description:Z.string()}),$A2=Z.object({title:Z.string(),description:Z.string()}),yGw=Z.object({title:Z.string(),description:Z.string()}),fA2=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),yF=Z.object({headline:Z.string(),tagline:Z.string()}),EGw=Z.object({title:Z.string(),description:Z.string()}),$X0=Z.object({vision:Z.string(),pillars:Z.array(BA2).min(1).max(6),approach:Z.array(EGw).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(yGw).min(1).max(6),benefits:Z.array($A2).min(1).max(6),cta:fA2}),TGw=yF.pick({headline:!0}).extend({slug:Z.string()}),SGw=Z.object({headline:Z.string(),slug:Z.string()}),mGw=Z.object({headline:Z.string(),tagline:Z.string()}),Oy=PQ.extend({entityType:Z.literal("products-overview"),metadata:SGw}),Ms0=Oy.extend({frontmatter:mGw,body:$X0,labels:Z.record(Z.string(),Z.string())});wA();D2();q5();class vy extends $6{constructor(){super($X0,{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 xs0 extends E2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Oy,frontmatterSchema:yF,bodyFormatter:new vy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,yF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,yF),w=H1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Os0=new xs0;wA();L0();var uGw=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function YA2(A,Q){let w=r2(A.content,OW),B=Q.parse(w.content),$=Q.getLabels();return wX0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function XA2(A,Q){let w=r2(A.content,yF),B=Q.parse(w.content),$=Q.getLabels();return Ms0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class fX0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new vy;productFormatter=new xy;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=uGw.parse(A),$=w.entityService;if(B.entityType==="products-overview"){let W=(await $.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!W)throw Error("Products overview entity not found");let K=XA2(W,this.overviewFormatter);return Q.parse(K)}if(B.query?.id){let W=(await $.listEntities({entityType:"product",options:{filter:{metadata:{slug:B.query.id}},limit:1}}))[0];if(!W)throw Error(`Product not found: ${B.query.id}`);return Q.parse({product:YA2(W,this.productFormatter)})}let[f,Y]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),X=f[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:XA2(X,this.overviewFormatter),products:Y.map((H)=>YA2(H,this.productFormatter))})}}import{jsxDEV as G1,Fragment as pGw}from"preact/jsx-dev-runtime";var ZA2=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return G1(pGw,{children:[G1(dQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),G1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[G1("style",{children:`
|
|
7669
|
+
`}},void 0,!1,void 0,this),O9("section",{className:"project-shell",children:[O9("header",{className:"project-hero",children:[O9("div",{className:"project-index",children:[Q.brandLabel&&O9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&O9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),O9("div",{className:"project-title-panel",children:[O9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),O9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&O9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),O9("div",{className:"printable-meta",children:[Q.year&&O9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&O9("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&&O9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),O9(_9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&O9("footer",{className:"printable-footer",children:[O9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?O9("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 qGw=26214400,bGw=60000;class Ls0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==tY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=VGw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),B=await UGw(zGw(DGw(),"brain-project-printable-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/printable/project/${Q.id}`,template:o02,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:qGw,timeoutMs:bGw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${JGw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await GGw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}async resolveCoverImageUrl(A){let{frontmatter:Q}=M6(A.content),w=G7.parse(Q);if(!w.coverImageId)return;let B=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return B?.content.startsWith("data:image/")?B.content:void 0}}function VGw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=G7.parse(w);return{title:$.title,body:B,...$.description?{description:$.description}:{},year:$.year,...$.publishedAt?{publishedAt:$.publishedAt}:{},...$.url?{url:$.url,canonicalUrl:$.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function JGw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}l9();D2();L0();import{jsxDEV as kGw}from"preact/jsx-dev-runtime";var eY0="og-image",IGw="portfolio:og-image",s02=Z.object({title:Z.string().min(1),description:Z.string().optional(),year:Z.number().optional(),brandLabel:Z.string().optional(),coverImageUrl:Z.string().optional()}),a02={name:IGw,pluginId:"portfolio",schema:s02,renderers:{image:FGw}};function FGw(A){let Q=s02.parse(A);return kGw(dq,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class _s0{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!==eY0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=M6(Q.content),B=G7.parse(w),$=this.resolveBrandLabel(),f=await this.resolveCoverImageUrl(B.coverImageId),Y={title:B.title,...B.description?{description:B.description}:{},year:B.year,...f?{coverImageUrl:f}:{},...$?{brandLabel:$}:{}};return{type:"image",data:await Aj({mediaPath:`/_media/og/project/${Q.id}`,template:a02,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:`${LGw(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 LGw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.title)}var t02={name:"@brains/portfolio",version:"0.2.0-alpha.164",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 NGw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),PGw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),e02=Z.enum(["generating","draft","published","failed"]),jGw=Z.object({title:Z.string(),slug:Z.string().optional(),status:e02,publishedAt:Z.string().optional(),description:Z.string(),year:Z.number(),coverImageId:Z.string().optional(),ogImageId:Z.string().optional(),url:Z.url().optional()}),MGw=Z.object({title:Z.string(),status:e02,publishedAt:Z.string().optional(),year:Z.number(),slug:Z.string(),error:Z.string().optional()}),xGw=Z.object({context:Z.string(),problem:Z.string(),solution:Z.string(),outcome:Z.string()}),AX0=Z.object({id:Z.string(),entityType:Z.literal("project"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:PGw,metadata:MGw,contentHash:Z.string(),frontmatter:jGw,body:Z.string(),structuredContent:xGw.optional(),url:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),OGw=Z.object({projects:Z.array(AX0),pageTitle:Z.string().optional(),pagination:NGw.nullable(),baseUrl:Z.string().optional()}),vGw=Z.object({prompt:Z.string(),year:Z.number()});function RGw(A,Q){for(let w of[A,Q]){let B=w?.match(/\b(19\d{2}|20\d{2})\b/);if(B?.[1])return Number(B[1])}return null}class Ns0 extends sQ{entityType="project";schema=gF;adapter=Gj;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",t02,A,bs0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let B=RGw(A.title,A.prompt);if(!B)return{kind:"continue",input:A};return{kind:"handled",result:{success:!0,data:{status:"generating",jobId:await w.jobs.enqueue({type:"project:generation",data:{prompt:A.prompt,...A.title?{title:A.title}:{},year:B},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new sY0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":l1({name:"project-list",description:"Portfolio project list page template",schema:OGw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Vs0}}),"project-detail":l1({name:"project-detail",description:"Individual project case study template",schema:Z.object({project:AX0,prevProject:AX0.nullable(),nextProject:AX0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Js0}}),generation:Is0}}getDataSources(){return[new aY0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",tY0,new Ls0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",eY0,new _s0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=B8.getInstance().register(ks0())}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0,this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}registerEvalHandlers(A){A.eval.registerHandler("generateProject",async(Q)=>{let w=vGw.parse(Q);return A.ai.generate({prompt:Fs0(w),templateName:"portfolio:generation"})})}deferPublishRegistration(A){let Q={name:"internal",publish:async()=>({id:"internal"})};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"project",provider:Q,config:{executionMode:"provider"}}}),{success:!0}})}subscribeToPublishExecute(A){A.messaging.subscribe("publish:execute",async(Q)=>{let{entityType:w,entityId:B}=Q.payload;if(w!=="project")return{success:!0};try{let $=await A.entityService.getEntity({entityType:"project",id:B});if(!$)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:`Project not found: ${B}`}}),{success:!0};if($.metadata.status==="published")return{success:!0};let f=r2($.content,G7),Y=new Date().toISOString(),X=F5(f.content,{...f.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...$,content:X,metadata:{...$.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:B,publishedAt:Y}})}catch($){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:B,error:SA($)}})}return{success:!0}})}}function Ps0(A={}){return new Ns0(A)}wA();L0();xB();L0();wA();var AA2=Z.enum(["available","early access","coming soon","planned"]),QA2=Z.enum(["available","early access","coming soon","planned"]),wA2=Z.object({title:Z.string(),description:Z.string()}),OW=Z.object({name:Z.string(),availability:AA2,order:Z.number(),ogImageId:Z.string().optional()}),QX0=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(wA2).min(1).max(6),story:Z.string()}),Y9$=OW.pick({name:!0,availability:!0,order:!0}).extend({slug:Z.string()}),hGw=Z.object({name:Z.string(),availability:QA2,order:Z.number(),slug:Z.string()}),CGw=Z.object({name:Z.string(),availability:QA2,order:Z.number(),ogImageId:Z.string().optional()}),My=PQ.extend({entityType:Z.literal("product"),metadata:hGw}),wX0=My.extend({frontmatter:CGw,body:QX0,labels:Z.record(Z.string(),Z.string()),ogImageUrl:Z.string().optional()}),gGw=wX0.extend({url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()});wA();D2();q5();class xy extends $6{constructor(){super(QX0,{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 js0 extends E2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:My,frontmatterSchema:OW,bodyFormatter:new xy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,OW);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,OW),w=H1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var BX0=new js0;L0();wA();var BA2=Z.object({title:Z.string(),description:Z.string()}),$A2=Z.object({title:Z.string(),description:Z.string()}),yGw=Z.object({title:Z.string(),description:Z.string()}),fA2=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),yF=Z.object({headline:Z.string(),tagline:Z.string()}),EGw=Z.object({title:Z.string(),description:Z.string()}),$X0=Z.object({vision:Z.string(),pillars:Z.array(BA2).min(1).max(6),approach:Z.array(EGw).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(yGw).min(1).max(6),benefits:Z.array($A2).min(1).max(6),cta:fA2}),TGw=yF.pick({headline:!0}).extend({slug:Z.string()}),SGw=Z.object({headline:Z.string(),slug:Z.string()}),mGw=Z.object({headline:Z.string(),tagline:Z.string()}),Oy=PQ.extend({entityType:Z.literal("products-overview"),metadata:SGw}),Ms0=Oy.extend({frontmatter:mGw,body:$X0,labels:Z.record(Z.string(),Z.string())});wA();D2();q5();class vy extends $6{constructor(){super($X0,{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 xs0 extends E2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:Oy,frontmatterSchema:yF,bodyFormatter:new vy})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,yF);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,yF),w=H1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var Os0=new xs0;wA();L0();var uGw=Z.object({entityType:Z.string(),query:Z.object({id:Z.string().optional()}).optional()});function YA2(A,Q){let w=r2(A.content,OW),B=Q.parse(w.content),$=Q.getLabels();return wX0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}function XA2(A,Q){let w=r2(A.content,yF),B=Q.parse(w.content),$=Q.getLabels();return Ms0.parse({...A,frontmatter:w.metadata,body:B,labels:$})}class fX0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new vy;productFormatter=new xy;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let B=uGw.parse(A),$=w.entityService;if(B.entityType==="products-overview"){let W=(await $.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!W)throw Error("Products overview entity not found");let K=XA2(W,this.overviewFormatter);return Q.parse(K)}if(B.query?.id){let W=(await $.listEntities({entityType:"product",options:{filter:{metadata:{slug:B.query.id}},limit:1}}))[0];if(!W)throw Error(`Product not found: ${B.query.id}`);return Q.parse({product:YA2(W,this.productFormatter)})}let[f,Y]=await Promise.all([$.listEntities({entityType:"products-overview",options:{limit:1}}),$.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),X=f[0];if(!X)throw Error("Products overview entity not found");return Q.parse({overview:XA2(X,this.overviewFormatter),products:Y.map((H)=>YA2(H,this.productFormatter))})}}import{jsxDEV as G1,Fragment as pGw}from"preact/jsx-dev-runtime";var ZA2=({overview:A,products:Q})=>{let{frontmatter:w,body:B,labels:$}=A;return G1(pGw,{children:[G1(dQ,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),G1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[G1("style",{children:`
|
|
7670
7670
|
@keyframes wave-drift {
|
|
7671
7671
|
from { transform: translateX(0); }
|
|
7672
7672
|
to { transform: translateX(-50%); }
|
|
@@ -7861,7 +7861,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7861
7861
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7862
7862
|
}
|
|
7863
7863
|
`}},void 0,!1,void 0,this),aZ("section",{className:"product-shell",children:[aZ("header",{className:"product-hero",children:[Q.brandLabel&&aZ("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),aZ("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&aZ("div",{className:"printable-meta",children:aZ("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aZ("div",{className:"product-body-wrap",children:[aZ("aside",{className:"product-rail","aria-hidden":"true",children:aZ("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),aZ(_9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&aZ("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 tGw=26214400,eGw=60000;class Rs0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??NU}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==YX0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let w=ADw(Q,{brandLabel:this.resolveBrandLabel()}),B=await rGw(aGw(sGw(),"brain-product-printable-"));try{let $=await mZ({outputDir:B,mediaPath:`/_media/printable/product/${Q.id}`,template:KA2,format:"pdf",content:w,siteConfig:{title:w.name,themeMode:"light"},themeCSS:this.context.themeCSS}),f=await uZ({rootDir:B});try{return{type:"document",data:await this.renderPdf(f.urlFor($.urlPath),{maxBytes:tGw,timeoutMs:eGw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${QDw(Q)}-printable.pdf`}}finally{await f.close()}}finally{await oGw(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name.trim();return Q.length>0?Q:void 0}}function ADw(A,Q={}){let{frontmatter:w,content:B}=M6(A.content),$=OW.parse(w);return{name:$.name,body:B,availability:$.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function QDw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.name)}l9();D2();L0();import{jsxDEV as $Dw}from"preact/jsx-dev-runtime";var XX0="og-image",wDw="products:og-image",UA2=Z.object({name:Z.string().min(1),tagline:Z.string().optional(),availability:Z.string().optional(),brandLabel:Z.string().optional()}),GA2={name:wDw,pluginId:"products",schema:UA2,renderers:{image:BDw}};function BDw(A){let Q=UA2.parse(A);return $Dw(dq,{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 hs0{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!==XX0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:B}=M6(Q.content),$=OW.parse(w),f=fDw(B,"Tagline"),Y=this.resolveBrandLabel(),X={name:$.name,availability:$.availability,...f?{tagline:f}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Aj({mediaPath:`/_media/og/product/${Q.id}`,template:GA2,content:X,title:X.name,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-product-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${YDw(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 fDw(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((Y)=>Y.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(B===-1)return;let $=[];for(let Y of w.slice(B+1)){if(Y.trim().startsWith("## "))break;$.push(Y)}let f=$.join(`
|
|
7864
|
-
`).trim();return f.length>0?f:void 0}function YDw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.name)}var DA2={name:"@brains/products",version:"0.2.0-alpha.
|
|
7864
|
+
`).trim();return f.length>0?f:void 0}function YDw(A){let Q=A.metadata.slug;return Q.length>0?Q:H1(A.metadata.name)}var DA2={name:"@brains/products",version:"0.2.0-alpha.164",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 ZDw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),zA2=Z.object({id:Z.string(),entityType:Z.string(),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:ZDw,metadata:Z.record(Z.string(),Z.unknown()),contentHash:Z.string()}),qA2=Z.enum(["available","early access","coming soon","planned"]),HDw=Z.object({title:Z.string(),description:Z.string()}),WDw=Z.object({name:Z.string(),availability:qA2,order:Z.number(),ogImageId:Z.string().optional()}),KDw=Z.object({tagline:Z.string(),promise:Z.string(),role:Z.string(),purpose:Z.string(),audience:Z.string(),values:Z.array(Z.string()).min(1),features:Z.array(HDw).min(1).max(6),story:Z.string()}),UDw=Z.object({name:Z.string(),availability:qA2,order:Z.number(),slug:Z.string()}),bA2=zA2.extend({entityType:Z.literal("product"),metadata:UDw,frontmatter:WDw,body:KDw,labels:Z.record(Z.string(),Z.string()),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),ogImageUrl:Z.string().optional()}),ZX0=Z.object({title:Z.string(),description:Z.string()}),GDw=Z.object({heading:Z.string(),buttonText:Z.string(),link:Z.string()}),DDw=Z.object({headline:Z.string(),tagline:Z.string()}),zDw=Z.object({vision:Z.string(),pillars:Z.array(ZX0).min(1).max(6),approach:Z.array(ZX0).min(1).max(6),productsIntro:Z.string(),technologies:Z.array(ZX0).min(1).max(6),benefits:Z.array(ZX0).min(1).max(6),cta:GDw}),qDw=Z.object({headline:Z.string(),slug:Z.string()}),bDw=zA2.extend({entityType:Z.literal("products-overview"),metadata:qDw,frontmatter:DDw,body:zDw,labels:Z.record(Z.string(),Z.string())}),VDw=Z.object({overview:bDw,products:Z.array(bA2)}),JDw=Z.object({product:bA2});class Cs0 extends sQ{entityType=BX0.entityType;schema=My;adapter=BX0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",DA2,A,vs0)}getTemplates(){return{"product-list":l1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:VDw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:ZA2}}),"product-detail":l1({name:"product-detail",description:"Individual product detail page",schema:JDw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:HA2}})}}getDataSources(){return[new fX0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",YX0,new Rs0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",XX0,new hs0(A)),A.entities.register("products-overview",Oy,Os0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function jo(A={}){return new Cs0(A)}wA();L0();L0();var IDw=Z.enum(["public","shared","restricted"]),VA2=Z.object({includeEntityTypes:Z.array(Z.string()).default([]),minRelevanceScore:Z.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:Z.number().min(0).max(1).default(0.85),autoMerge:Z.boolean().default(!0),extractableStatuses:Z.array(Z.string()).default(["published"]),enableAutoExtraction:Z.boolean().default(!0),extractionVisibility:IDw.default("public"),sourceChangeBatchDelayMs:Z.number().int().min(0).default(1000)});wA();L0();wA();var p7$=Z.object({}),FDw=Z.record(Z.string(),Z.unknown()).transform(()=>({})),Ry=PQ.extend({entityType:Z.literal("topic"),metadata:FDw}),i7$=Z.object({content:Z.string()}),JA2=Z.object({title:Z.string().describe("Topic title")});var Dj="topics",r6="topic",gs0="topics-projection",IA2="topic:project",HX0="topics-plugin",FA2="topics:batch-completed",kA2="topics-source-batch";class xU extends E2{constructor(){super({entityType:r6,purpose:"A recurring theme or subject derived from the user's content.",schema:Ry,frontmatterSchema:JA2})}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:r6}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),B=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return B?B[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),formatted:A,title:Q.title}}catch{return{content:A,formatted:A,title:"Unknown Topic"}}return{content:A,formatted:A,title:"Unknown Topic"}}createTopicBody(A){return this.buildMarkdown(A.content,this.buildFrontmatter(A.title))}}wA();L0();L0();var kDw=Z.object({title:Z.string().max(100),content:Z.string(),relevanceScore:Z.number().min(0).max(1)}),LA2=Z.array(kDw);var LDw=Z.object({topics:LA2}),_A2=l1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:LDw,basePrompt:`You are an expert at analyzing content and extracting key topics.
|
|
7865
7865
|
|
|
7866
7866
|
Analyze the provided content and extract meaningful topics discussed.
|
|
7867
7867
|
|
|
@@ -7964,13 +7964,13 @@ ${A.incomingTopic.content}`})}}function gDw(A){if(A.length===0)return"";return A
|
|
|
7964
7964
|
|
|
7965
7965
|
${Q.content}`}).join(`
|
|
7966
7966
|
|
|
7967
|
-
`)}async function zj(A,Q,w,B={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let $=B.minRelevanceScore??0,f=B.autoMerge??!1,Y=B.mergeSimilarityThreshold??0.85,X=B.targetVisibility??"public",H=gA2(A),W=new OU(Q.entityService,w),K=B.topicMergeSynthesizer??new us0(Q,w),U=await DX0(Q.entityService,void 0,X),G=new Map,q=0,b=0,J=0;for(let k of H){w.info(`Processing batch of ${k.length} entities`);let N=gDw(k),L=zX0({entityTitle:`Batch of ${k.length} entities`,entityType:"batch",content:N,existingTopicTitles:U});try{let v=(await Q.ai.generate({prompt:L,templateName:"topics:extraction"})).topics.filter((h)=>h.relevanceScore>=$);for(let h of v)try{if(f){let S=await W.findMergeCandidate({incoming:h,threshold:Y,additionalCandidates:Array.from(G.values()),targetVisibility:X});if(S){let p=await K.synthesize({existingTopic:S.topic,incomingTopic:h}),e=await W.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...p,title:S.title},visibility:X});if(!e)throw Error(`Failed to merge topic: ${h.title}`);G.set(e.id,e),b++;continue}}let j=W.getTopicIdForTitle(h.title,X);if(G.has(j)){J++;continue}let E=await W.createTopicOptimistic({title:h.title,content:h.content,visibility:X});if(E.topic)G.set(E.topic.id,E.topic);if(E.created)q++;else J++}catch(j){w.error("Topic batch item failed",{title:h.title,error:SA(j)})}}catch(O){w.error("Batch topic extraction failed",{batchSize:k.length,promptChars:L.length,error:SA(O)})}}let V={created:q,merged:b,skipped:J,batches:H.length};if(q>0||b>0)await Q.messaging.send({type:FA2,payload:V,broadcast:!0});return V}wA();L0();var yDw=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("rebuild"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source-batch"),minRelevanceScore:Z.number().min(0).max(1).optional()})]);class cs0{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 uA2(A){let{context:Q,logger:w,config:B}=A;return{process:async($)=>{if($.mode==="derive")return await A.extractAllTopics(),{success:!0};if($.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return EDw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=yDw.safeParse($??{});return f.success?f.data:null}}}async function EDw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(W)=>({ref:W,entity:await A.context.entityService.getEntity({entityType:W.entityType,id:W.entityId})}))),B=0,$=0,f=0,Y=0,X=[];for(let{ref:W,entity:K}of w){if(!K){$++;continue}if(K.contentHash!==W.contentHash){B++;continue}if(!A.isEntityPublished(K)){f++;continue}if(!hV(K.visibility,A.config.extractionVisibility)){Y++;continue}X.push(K)}if(X.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:Y};let H=await zj(X,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:B,missing:$,unpublished:f,hidden:Y}}function cA2(){return{priority:5,source:HX0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Dj}}}async function lA2(A){let Q=await iA2(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let w=await zj(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",w)}async function pA2(A){let Q=await iA2(A),w=await ls0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function ls0(A,Q,w,B){let $=new OU(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let X of f)await $.deleteTopic(X.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let Y=await zj(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...Y}}async function iA2(A){let Q=TDw(A),w=[];for(let B of Q){let $=await A.context.entityService.listEntities({entityType:B,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let f of $){if(!A.isEntityPublished(f))continue;w.push(f)}}return w}function TDw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var gy=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),SDw=gy.extend({minRelevanceScore:Z.number().optional()}),mDw=Z.object({contentA:gy,contentB:gy,minRelevanceScore:Z.number().optional(),threshold:Z.number().min(0).max(1).optional()}),vo=Z.object({title:Z.string(),content:Z.string()}),uDw=Z.object({existingTopics:Z.array(vo),incomingTopic:vo,threshold:Z.number().optional()}),cDw=Z.object({existingTopics:Z.array(vo).default([]),incomingTopic:vo.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()}),lDw=Z.object({entities:Z.array(gy).min(1),minRelevanceScore:Z.number().optional()}),pDw=Z.object({existingTopics:Z.array(vo).optional(),entities:Z.array(gy)}),iDw=Z.object({entities:Z.array(gy)});function Cy(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:f6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function dA2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function dDw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function nDw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:dDw(Q)}]}}async function qj(A){let Q=await A.entityService.listEntities({entityType:r6});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:r6,id:w.id})))}async function rDw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function nA2(A){let{context:Q,logger:w,config:B}=A,$=new ms0(Q,w),f=async(Y,X,H="")=>{let W=Cy(Y,H);return $.extractFromEntity(W,X)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await qj(Q);let X=SDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=Cy(X);return(await $.extractFromEntity(W,H)).map((U)=>nDw(U,W))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await qj(Q);let X=mDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=X.threshold??B.mergeSimilarityThreshold,[K,U]=await Promise.all([f(X.contentA,H,"-a"),f(X.contentB,H,"-b")]),G=new OU(Q.entityService,w),q=[];for(let V of K){let k=await G.createTopic(V);if(k)q.push(k)}let b=(await Promise.all(U.map(async(V)=>{let k=await G.findMergeCandidate({incoming:V,threshold:W,additionalCandidates:q});if(!k)return null;return{incomingTitle:V.title,candidateTitle:k.title,candidateScore:k.score}}))).filter((V)=>V!==null),J=b.map((V)=>V.candidateTitle);return{topicsA:K.map(dA2),topicsB:U.map(dA2),matchingTitles:J,mergeCandidates:b,wouldMerge:b.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await qj(Q);let X=uDw.parse(Y),H=X.threshold??B.mergeSimilarityThreshold,W=new OU(Q.entityService,w),K=[];for(let G of X.existingTopics){let q=await W.createTopic(G);if(q)K.push(q)}let U=await W.findMergeCandidate({incoming:{title:X.incomingTopic.title},threshold:H,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await qj(Q);let X=cDw.parse(Y),H=new OU(Q.entityService,w);for(let G of X.existingTopics)await H.createTopic({title:G.title,content:G.content});await rDw(Q);let W=Cy({entityType:"post",content:X.incomingTopic.content,metadata:{title:X.incomingTopic.title}},"-source"),K=await zj([W],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:X.threshold??B.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:r6});return{...K,topicCount:U.length,topics:U.map(Ts0)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await qj(Q);let X=pDw.parse(Y),H=new OU(Q.entityService,w);for(let G of X.existingTopics??[])await H.createTopic(G);let W=X.entities.map((G,q)=>Cy(G,`-rebuild-${q}`)),K=await ls0(W,Q,w,B),U=await Q.entityService.listEntities({entityType:r6});return{...K,topicCount:U.length,topics:U.map(Ts0)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await qj(Q);let X=lDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=new OU(Q.entityService,w),K=[];for(let[G,q]of X.entities.entries()){let b=Cy(q,`-sequential-${G}`),J=await $.extractFromEntity(b,H);for(let V of J)await W.createTopic({title:V.title,content:V.content});K.push({extractedTitles:J.map((V)=>V.title)})}let U=await Q.entityService.listEntities({entityType:r6});return{totalTopics:U.length,perEntity:K,topics:U.map(hy)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await qj(Q);let H=iDw.parse(Y).entities.map((U,G)=>Cy(U,`-batch-${G}`)),W=await zj(H,Q,w,{minRelevanceScore:B.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:r6});return{...W,topics:K.map(hy)}})}var oDw=new xU;async function rA2({entity:A,config:Q}){let w=Ry.parse(A),B=oDw.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:B.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function ps0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:_6["ai.rizom.brain.topic"],validate:!1,buildRecord:rA2}}var oA2={name:"@brains/topics",version:"0.2.0-alpha.163",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 aDw=new xU,tDw=Z.looseObject({status:Z.unknown().optional()});class sA2 extends sQ{entityType=r6;schema=Ry;adapter=aDw;unregisterAtprotoProjection;sourceBatch=new cs0;constructor(A={}){super(Dj,oA2,A,VA2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:_A2,"merge-synthesis":NA2,"topic-list":PA2,"topic-detail":jA2}}getDataSources(){return[new Ss0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:gs0,targetType:r6,job:{type:IA2,handler:uA2({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 kL(A,r6,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:cA2()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let w=Q.entity;if(!w)return null;if(!this.shouldProcessEntityType(w.entityType,A.entityService))return null;if(!this.isEntityPublished(w))return null;if(!hV(w.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:w.id,entityType:w.entityType,contentHash:w.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:HX0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:kA2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Dj}})}}]}async onRegister(A){A.insights.register("topic-distribution",OA2()),vA2({context:A,pluginId:this.id}),nA2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=B8.getInstance().register(ps0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(gs0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===r6)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=tDw.safeParse(A.metadata),w=Q.success?Q.data.status:void 0;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await lA2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await pA2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function qX0(A={}){return new sA2(A)}wA();L0();wA();var is0=Z.enum(["linkedin"]),aA2=Z.enum(["linkedin"]),ds0=Z.enum(["generating","draft","queued","published","failed"]),tA2=Z.enum(["generating","draft","queued","published","failed"]),eA2=Z.enum(["post","deck"]),eDw=Z.enum(["post","deck"]),A12=Z.object({id:Z.string().min(1).describe("Document entity ID")}),A3w=Z.object({id:Z.string().min(1)}),vU=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:is0.describe("Target platform"),status:ds0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),documents:Z.array(A12).optional().describe("Document attachments for publishing"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:eA2.optional().describe("Source entity type (post, deck)")}),Q12=vU.extend({platform:is0.optional(),status:ds0.optional()}),Q3w=vU.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}"),error:Z.string().optional()}),w3w=Z.object({title:Z.string(),platform:aA2,status:tA2,publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),B3w=Z.object({title:Z.string(),platform:aA2,status:tA2,coverImageId:Z.string().optional(),documents:Z.array(A3w).optional(),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:eDw.optional()}),EF=PQ.extend({entityType:Z.literal("social-post"),metadata:w3w}),bX0=EF.extend({frontmatter:B3w,body:Z.string()}),$3w=bX0.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();D2();class ns0 extends E2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:EF,frontmatterSchema:vU,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,vU),Q=this.extractBody(A.content)}catch{Q=A.content}let B={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Q12),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${H1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:$,platform:w,status:B,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,vU)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let w={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:`linkedin-${H1(A.title)}`,platform:"linkedin",status:"generating"}}}}var r7=new ns0;wA();wA();L0();var f3w=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),Y3w=Z.looseObject({entityType:Z.string().optional(),query:f3w.optional()});function w12(A){let Q=r2(A.content,vU);return bX0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class VX0 extends L5{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=Y3w.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return w12(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,w){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:w.baseUrl}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.nextInQueue)return this.fetchNextInQueue(Q,$);if(B.id){let{item:K}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(K,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let Y=Object.keys(f).length>0,X=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:H,pagination:W}=await this.fetchList(B,$,{...Y&&{filter:{metadata:f}},sortFields:X});return Q.parse(this.buildListResult(H,W,B))}async fetchNextInQueue(A,Q){let B=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],$=B?w12(B):null;return A.parse({post:$})}}L0();var B12=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional(),apiVersion:Z.string().regex(/^\d{6}$/).optional()}),rs0=Z.object({linkedin:B12.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});wA();D2();L0();T6();ss0();import{jsxDEV as Q5,Fragment as H3w}from"preact/jsx-dev-runtime";function X3w(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Z3w(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var IX0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,Y=`Browse all ${f} social ${f===1?"post":"posts"}`;return Q5(H3w,{children:[Q5(dQ,{title:$,description:Y},void 0,!1,void 0,this),Q5("div",{className:"social-post-list bg-theme",children:Q5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[Q5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?Q5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):Q5("ul",{className:"space-y-6",children:A.map((X)=>Q5("li",{children:Q5(z6,{href:X.url,variant:"horizontal",children:Q5("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&Q5("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),Q5("div",{className:"flex-1 min-w-0",children:[Q5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[Q5("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),Q5("time",{className:"text-sm text-theme-muted shrink-0",children:Z3w(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q5("div",{className:"flex items-center gap-2 mb-3",children:[Q5(oY,{status:X.frontmatter.status},void 0,!1,void 0,this),Q5("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),Q5("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q5("p",{className:"text-theme leading-relaxed",children:X3w(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&Q5(oq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as w5,Fragment as W3w}from"preact/jsx-dev-runtime";function $12(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var FX0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),B=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return w5(W3w,{children:[w5(dQ,{title:Q,description:w},void 0,!1,void 0,this),w5("section",{className:"social-post-detail",children:w5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:w5("div",{className:"max-w-3xl mx-auto",children:[w5(gD,{items:B},void 0,!1,void 0,this),w5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),w5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[w5(oY,{status:A.frontmatter.status},void 0,!1,void 0,this),w5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),w5("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&&w5(nq,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),w5(z6,{className:"p-8 mb-8",children:w5("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),w5("div",{className:"space-y-4 text-sm text-theme-muted",children:[w5("div",{children:[w5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",$12(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&w5("div",{children:[w5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",$12(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&w5("div",{children:w5("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 Ro(A){return`social-media:${A}`}var K3w=Z.union([Z.boolean(),Z.object({generate:Z.boolean().optional(),prompt:Z.string().optional()})]),as0=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post"),coverImage:K3w.optional().describe("Generic cover image generation request")}),U3w=jX.extend({slug:Z.string().optional()});class bj extends J4{constructor(A,Q){super(A,Q,{schema:as0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:Y}=A,{content:X,title:H}=A;if(X&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let V=await this.context.ai.generate({prompt:X,templateName:Ro(w)});H=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let V=await this.context.entityService.getEntity({entityType:f,id:Y});if(!V)this.failEarly(`Source entity not found: ${f}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let N=Z.looseObject({slug:Z.string()}).safeParse(V.metadata),L=N.success?N.data.slug:Y,O=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
|
|
7967
|
+
`)}async function zj(A,Q,w,B={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let $=B.minRelevanceScore??0,f=B.autoMerge??!1,Y=B.mergeSimilarityThreshold??0.85,X=B.targetVisibility??"public",H=gA2(A),W=new OU(Q.entityService,w),K=B.topicMergeSynthesizer??new us0(Q,w),U=await DX0(Q.entityService,void 0,X),G=new Map,q=0,b=0,J=0;for(let k of H){w.info(`Processing batch of ${k.length} entities`);let N=gDw(k),L=zX0({entityTitle:`Batch of ${k.length} entities`,entityType:"batch",content:N,existingTopicTitles:U});try{let v=(await Q.ai.generate({prompt:L,templateName:"topics:extraction"})).topics.filter((h)=>h.relevanceScore>=$);for(let h of v)try{if(f){let S=await W.findMergeCandidate({incoming:h,threshold:Y,additionalCandidates:Array.from(G.values()),targetVisibility:X});if(S){let p=await K.synthesize({existingTopic:S.topic,incomingTopic:h}),e=await W.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...p,title:S.title},visibility:X});if(!e)throw Error(`Failed to merge topic: ${h.title}`);G.set(e.id,e),b++;continue}}let j=W.getTopicIdForTitle(h.title,X);if(G.has(j)){J++;continue}let E=await W.createTopicOptimistic({title:h.title,content:h.content,visibility:X});if(E.topic)G.set(E.topic.id,E.topic);if(E.created)q++;else J++}catch(j){w.error("Topic batch item failed",{title:h.title,error:SA(j)})}}catch(O){w.error("Batch topic extraction failed",{batchSize:k.length,promptChars:L.length,error:SA(O)})}}let V={created:q,merged:b,skipped:J,batches:H.length};if(q>0||b>0)await Q.messaging.send({type:FA2,payload:V,broadcast:!0});return V}wA();L0();var yDw=Z.discriminatedUnion("mode",[Z.object({mode:Z.literal("derive"),reason:Z.string().optional()}),Z.object({mode:Z.literal("rebuild"),reason:Z.string().optional()}),Z.object({mode:Z.literal("source-batch"),minRelevanceScore:Z.number().min(0).max(1).optional()})]);class cs0{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 uA2(A){let{context:Q,logger:w,config:B}=A;return{process:async($)=>{if($.mode==="derive")return await A.extractAllTopics(),{success:!0};if($.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return EDw({context:Q,logger:w,config:B,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:$.minRelevanceScore??B.minRelevanceScore})},validateAndParse:($)=>{let f=yDw.safeParse($??{});return f.success?f.data:null}}}async function EDw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(W)=>({ref:W,entity:await A.context.entityService.getEntity({entityType:W.entityType,id:W.entityId})}))),B=0,$=0,f=0,Y=0,X=[];for(let{ref:W,entity:K}of w){if(!K){$++;continue}if(K.contentHash!==W.contentHash){B++;continue}if(!A.isEntityPublished(K)){f++;continue}if(!hV(K.visibility,A.config.extractionVisibility)){Y++;continue}X.push(K)}if(X.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:B,missing:$,unpublished:f,hidden:Y};let H=await zj(X,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:B,missing:$,unpublished:f,hidden:Y}}function cA2(){return{priority:5,source:HX0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:Dj}}}async function lA2(A){let Q=await iA2(A);if(Q.length===0){A.logger.info("No entities to extract topics from");return}A.logger.info(`Batch topic extraction: ${Q.length} entities`);let w=await zj(Q,A.context,A.logger,{minRelevanceScore:A.config.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});A.logger.info("Batch topic extraction complete",w)}async function pA2(A){let Q=await iA2(A),w=await ls0(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function ls0(A,Q,w,B){let $=new OU(Q.entityService,w),f=await $.listTopics({visibility:B.extractionVisibility});for(let X of f)await $.deleteTopic(X.id);if(A.length===0)return{deleted:f.length,created:0,merged:0,skipped:0,batches:0};let Y=await zj(A,Q,w,{minRelevanceScore:B.minRelevanceScore,autoMerge:B.autoMerge,mergeSimilarityThreshold:B.mergeSimilarityThreshold,targetVisibility:B.extractionVisibility});return{deleted:f.length,...Y}}async function iA2(A){let Q=TDw(A),w=[];for(let B of Q){let $=await A.context.entityService.listEntities({entityType:B,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let f of $){if(!A.isEntityPublished(f))continue;w.push(f)}}return w}function TDw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var gy=Z.object({entityType:Z.string(),content:Z.string(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),SDw=gy.extend({minRelevanceScore:Z.number().optional()}),mDw=Z.object({contentA:gy,contentB:gy,minRelevanceScore:Z.number().optional(),threshold:Z.number().min(0).max(1).optional()}),vo=Z.object({title:Z.string(),content:Z.string()}),uDw=Z.object({existingTopics:Z.array(vo),incomingTopic:vo,threshold:Z.number().optional()}),cDw=Z.object({existingTopics:Z.array(vo).default([]),incomingTopic:vo.extend({relevanceScore:Z.number().min(0).max(1).optional()}),threshold:Z.number().optional()}),lDw=Z.object({entities:Z.array(gy).min(1),minRelevanceScore:Z.number().optional()}),pDw=Z.object({existingTopics:Z.array(vo).optional(),entities:Z.array(gy)}),iDw=Z.object({entities:Z.array(gy)});function Cy(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:f6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function dA2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function dDw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function nDw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:dDw(Q)}]}}async function qj(A){let Q=await A.entityService.listEntities({entityType:r6});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:r6,id:w.id})))}async function rDw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function nA2(A){let{context:Q,logger:w,config:B}=A,$=new ms0(Q,w),f=async(Y,X,H="")=>{let W=Cy(Y,H);return $.extractFromEntity(W,X)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await qj(Q);let X=SDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=Cy(X);return(await $.extractFromEntity(W,H)).map((U)=>nDw(U,W))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await qj(Q);let X=mDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=X.threshold??B.mergeSimilarityThreshold,[K,U]=await Promise.all([f(X.contentA,H,"-a"),f(X.contentB,H,"-b")]),G=new OU(Q.entityService,w),q=[];for(let V of K){let k=await G.createTopic(V);if(k)q.push(k)}let b=(await Promise.all(U.map(async(V)=>{let k=await G.findMergeCandidate({incoming:V,threshold:W,additionalCandidates:q});if(!k)return null;return{incomingTitle:V.title,candidateTitle:k.title,candidateScore:k.score}}))).filter((V)=>V!==null),J=b.map((V)=>V.candidateTitle);return{topicsA:K.map(dA2),topicsB:U.map(dA2),matchingTitles:J,mergeCandidates:b,wouldMerge:b.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await qj(Q);let X=uDw.parse(Y),H=X.threshold??B.mergeSimilarityThreshold,W=new OU(Q.entityService,w),K=[];for(let G of X.existingTopics){let q=await W.createTopic(G);if(q)K.push(q)}let U=await W.findMergeCandidate({incoming:{title:X.incomingTopic.title},threshold:H,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await qj(Q);let X=cDw.parse(Y),H=new OU(Q.entityService,w);for(let G of X.existingTopics)await H.createTopic({title:G.title,content:G.content});await rDw(Q);let W=Cy({entityType:"post",content:X.incomingTopic.content,metadata:{title:X.incomingTopic.title}},"-source"),K=await zj([W],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:X.threshold??B.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:r6});return{...K,topicCount:U.length,topics:U.map(Ts0)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await qj(Q);let X=pDw.parse(Y),H=new OU(Q.entityService,w);for(let G of X.existingTopics??[])await H.createTopic(G);let W=X.entities.map((G,q)=>Cy(G,`-rebuild-${q}`)),K=await ls0(W,Q,w,B),U=await Q.entityService.listEntities({entityType:r6});return{...K,topicCount:U.length,topics:U.map(Ts0)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await qj(Q);let X=lDw.parse(Y),H=X.minRelevanceScore??B.minRelevanceScore,W=new OU(Q.entityService,w),K=[];for(let[G,q]of X.entities.entries()){let b=Cy(q,`-sequential-${G}`),J=await $.extractFromEntity(b,H);for(let V of J)await W.createTopic({title:V.title,content:V.content});K.push({extractedTitles:J.map((V)=>V.title)})}let U=await Q.entityService.listEntities({entityType:r6});return{totalTopics:U.length,perEntity:K,topics:U.map(hy)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await qj(Q);let H=iDw.parse(Y).entities.map((U,G)=>Cy(U,`-batch-${G}`)),W=await zj(H,Q,w,{minRelevanceScore:B.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:r6});return{...W,topics:K.map(hy)}})}var oDw=new xU;async function rA2({entity:A,config:Q}){let w=Ry.parse(A),B=oDw.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:B.title,body:B.content,format:"text/markdown",...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"topic",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function ps0(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:_6["ai.rizom.brain.topic"],validate:!1,buildRecord:rA2}}var oA2={name:"@brains/topics",version:"0.2.0-alpha.164",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 aDw=new xU,tDw=Z.looseObject({status:Z.unknown().optional()});class sA2 extends sQ{entityType=r6;schema=Ry;adapter=aDw;unregisterAtprotoProjection;sourceBatch=new cs0;constructor(A={}){super(Dj,oA2,A,VA2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:_A2,"merge-synthesis":NA2,"topic-list":PA2,"topic-detail":jA2}}getDataSources(){return[new Ss0(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:gs0,targetType:r6,job:{type:IA2,handler:uA2({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 kL(A,r6,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:cA2()},sourceChange:{sourceTypes:this.config.includeEntityTypes,requireInitialSync:!0,jobData:(Q)=>{let w=Q.entity;if(!w)return null;if(!this.shouldProcessEntityType(w.entityType,A.entityService))return null;if(!this.isEntityPublished(w))return null;if(!hV(w.visibility,this.config.extractionVisibility))return null;return this.sourceBatch.add({entityId:w.id,entityType:w.entityType,contentHash:w.contentHash}),{mode:"source-batch"}},jobOptions:()=>({priority:5,source:HX0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:kA2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:Dj}})}}]}async onRegister(A){A.insights.register("topic-distribution",OA2()),vA2({context:A,pluginId:this.id}),nA2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=B8.getInstance().register(ps0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(gs0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===r6)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=tDw.safeParse(A.metadata),w=Q.success?Q.data.status:void 0;if(w===void 0||w===null)return!0;if(typeof w!=="string")return!1;return this.config.extractableStatuses.includes(w)}async extractAllTopics(A){await lA2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await pA2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function qX0(A={}){return new sA2(A)}wA();L0();wA();var is0=Z.enum(["linkedin"]),aA2=Z.enum(["linkedin"]),ds0=Z.enum(["generating","draft","queued","published","failed"]),tA2=Z.enum(["generating","draft","queued","published","failed"]),eA2=Z.enum(["post","deck"]),eDw=Z.enum(["post","deck"]),A12=Z.object({id:Z.string().min(1).describe("Document entity ID")}),A3w=Z.object({id:Z.string().min(1)}),vU=Z.object({title:Z.string().describe("Short descriptive title (3-6 words) for file naming"),platform:is0.describe("Target platform"),status:ds0,coverImageId:Z.string().optional().describe("Image entity ID for post image"),documents:Z.array(A12).optional().describe("Document attachments for publishing"),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional().describe("ID from platform after publishing"),sourceEntityId:Z.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:eA2.optional().describe("Source entity type (post, deck)")}),Q12=vU.extend({platform:is0.optional(),status:ds0.optional()}),Q3w=vU.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:Z.string().describe("URL-friendly identifier: {platform}-{title}"),error:Z.string().optional()}),w3w=Z.object({title:Z.string(),platform:aA2,status:tA2,publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),B3w=Z.object({title:Z.string(),platform:aA2,status:tA2,coverImageId:Z.string().optional(),documents:Z.array(A3w).optional(),publishedAt:Z.string().datetime().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:eDw.optional()}),EF=PQ.extend({entityType:Z.literal("social-post"),metadata:w3w}),bX0=EF.extend({frontmatter:B3w,body:Z.string()}),$3w=bX0.extend({url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});wA();D2();class ns0 extends E2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:EF,frontmatterSchema:vU,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,vU),Q=this.extractBody(A.content)}catch{Q=A.content}let B={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,B)}fromMarkdown(A){let Q=this.parseFrontMatter(A,Q12),w=Q.platform??"linkedin",B=Q.status??"draft",$=`${w}-${H1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:$,platform:w,status:B,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,vU)}getPostContent(A){return this.extractBody(A.content)}createPostContent(A,Q){return this.buildMarkdown(Q,A)}buildStub(A){let w={title:A.title,platform:"linkedin",status:"generating"};return{content:this.buildMarkdown("",w),metadata:{title:A.title,slug:`linkedin-${H1(A.title)}`,platform:"linkedin",status:"generating"}}}}var r7=new ns0;wA();wA();L0();var f3w=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:Z.boolean().optional(),nextInQueue:Z.boolean().optional()}),Y3w=Z.looseObject({entityType:Z.string().optional(),query:f3w.optional()});function w12(A){let Q=r2(A.content,vU);return bX0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class VX0 extends L5{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=Y3w.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return w12(A)}buildDetailResult(A,Q){return{post:A}}buildListResult(A,Q,w){return{posts:A,totalCount:Q?.totalItems??A.length,pagination:Q,baseUrl:w.baseUrl}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.nextInQueue)return this.fetchNextInQueue(Q,$);if(B.id){let{item:K}=await this.fetchDetail(B.id,$);return Q.parse(this.buildDetailResult(K,null))}let f={};if(B.platform)f.platform=B.platform;if(B.status)f.status=B.status;let Y=Object.keys(f).length>0,X=B.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:H,pagination:W}=await this.fetchList(B,$,{...Y&&{filter:{metadata:f}},sortFields:X});return Q.parse(this.buildListResult(H,W,B))}async fetchNextInQueue(A,Q){let B=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],$=B?w12(B):null;return A.parse({post:$})}}L0();var B12=Z.object({accessToken:Z.string().optional(),refreshToken:Z.string().optional(),organizationId:Z.string().optional(),apiVersion:Z.string().regex(/^\d{6}$/).optional()}),rs0=Z.object({linkedin:B12.optional(),publishInterval:Z.number().default(3600000),enabled:Z.boolean().default(!0),defaultPrompt:Z.string().default("Create an engaging social media post that drives engagement"),maxRetries:Z.number().default(3),autoGenerateOnBlogPublish:Z.boolean().default(!1)});wA();D2();L0();T6();ss0();import{jsxDEV as Q5,Fragment as H3w}from"preact/jsx-dev-runtime";function X3w(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function Z3w(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var IX0=({posts:A,pageTitle:Q,pagination:w,baseUrl:B="/social-posts"})=>{let $=Q??"Social Posts",f=w?.totalItems??A.length,Y=`Browse all ${f} social ${f===1?"post":"posts"}`;return Q5(H3w,{children:[Q5(dQ,{title:$,description:Y},void 0,!1,void 0,this),Q5("div",{className:"social-post-list bg-theme",children:Q5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[Q5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:$},void 0,!1,void 0,this),A.length===0?Q5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):Q5("ul",{className:"space-y-6",children:A.map((X)=>Q5("li",{children:Q5(z6,{href:X.url,variant:"horizontal",children:Q5("div",{className:"flex flex-col sm:flex-row gap-4",children:[X.coverImageUrl&&Q5("img",{src:X.coverImageUrl,alt:X.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),Q5("div",{className:"flex-1 min-w-0",children:[Q5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[Q5("h2",{className:"text-lg font-semibold text-heading",children:X.frontmatter.title},void 0,!1,void 0,this),Q5("time",{className:"text-sm text-theme-muted shrink-0",children:Z3w(X.frontmatter.publishedAt??X.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q5("div",{className:"flex items-center gap-2 mb-3",children:[Q5(oY,{status:X.frontmatter.status},void 0,!1,void 0,this),Q5("span",{className:"text-xs text-theme-muted uppercase",children:X.frontmatter.platform},void 0,!1,void 0,this),Q5("span",{className:"text-xs text-theme-muted font-mono",children:X.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q5("p",{className:"text-theme leading-relaxed",children:X3w(X.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},X.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&Q5(oq,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as w5,Fragment as W3w}from"preact/jsx-dev-runtime";function $12(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var FX0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),B=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return w5(W3w,{children:[w5(dQ,{title:Q,description:w},void 0,!1,void 0,this),w5("section",{className:"social-post-detail",children:w5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:w5("div",{className:"max-w-3xl mx-auto",children:[w5(gD,{items:B},void 0,!1,void 0,this),w5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),w5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[w5(oY,{status:A.frontmatter.status},void 0,!1,void 0,this),w5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),w5("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&&w5(nq,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),w5(z6,{className:"p-8 mb-8",children:w5("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),w5("div",{className:"space-y-4 text-sm text-theme-muted",children:[w5("div",{children:[w5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",$12(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&w5("div",{children:[w5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",$12(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&w5("div",{children:w5("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 Ro(A){return`social-media:${A}`}var K3w=Z.union([Z.boolean(),Z.object({generate:Z.boolean().optional(),prompt:Z.string().optional()})]),as0=Z.object({prompt:Z.string().optional(),platform:Z.enum(["linkedin"]).optional(),sourceEntityType:Z.enum(["post","deck"]).optional(),sourceEntityId:Z.string().optional(),title:Z.string().optional().describe("Required when content is provided directly"),content:Z.string().optional(),addToQueue:Z.boolean().optional(),generateImage:Z.boolean().optional().describe("Auto-generate cover image for post"),coverImage:K3w.optional().describe("Generic cover image generation request")}),U3w=jX.extend({slug:Z.string().optional()});class bj extends J4{constructor(A,Q){super(A,Q,{schema:as0,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",B=A.addToQueue??!1,{prompt:$,sourceEntityType:f,sourceEntityId:Y}=A,{content:X,title:H}=A;if(X&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(X&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let V=await this.context.ai.generate({prompt:X,templateName:Ro(w)});H=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&f){await this.reportProgress(Q,{progress:10,message:`Fetching source ${f}`});let V=await this.context.entityService.getEntity({entityType:f,id:Y});if(!V)this.failEarly(`Source entity not found: ${f}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let N=Z.looseObject({slug:Z.string()}).safeParse(V.metadata),L=N.success?N.data.slug:Y,O=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${f}:
|
|
7968
7968
|
|
|
7969
7969
|
Source: ${f}/${L}
|
|
7970
7970
|
|
|
7971
7971
|
${V.content}`,templateName:Ro(w)});H=O.title,X=O.content,await this.reportProgress(Q,{progress:50,message:"Social post generated from source"})}else if($){await this.reportProgress(Q,{progress:10,message:"Generating social post with AI"});let V=await this.context.ai.generate({prompt:$,templateName:Ro(w)});H=V.title,X=V.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!X||!H)this.failEarly("Content or title was not generated");let K={title:H,platform:w,status:B?"queued":"draft",...Y&&{sourceEntityId:Y},...f&&{sourceEntityType:f}},U=r7.createPostContent(K,X),q=r7.fromMarkdown(U).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let b=await DK({entityType:"social-post",title:H,deriveId:(V)=>`${w}-${H1(V)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),J=U;if(b!==H){q.title=b,q.slug=`${w}-${H1(b)}`;let V={...K,title:b};J=r7.createPostContent(V,X)}return{id:q.slug,content:J,metadata:q,title:b,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,B){if(A.generateImage){await this.reportProgress(w,{progress:90,message:"Queueing image generation"});let $=B.title??"Social Post";await this.context.jobs.enqueue({type:"image:image-generate",data:{prompt:`Social media graphic for: ${$}`,title:`${$} Image`,aspectRatio:"16:9",targetEntityType:"social-post",targetEntityId:Q},toolContext:{interfaceType:"job",userId:"system"}})}await this.context.messaging.send({type:"generate:report:success",payload:{entityType:"social-post",entityId:Q}})}summarizeDataForLog(A){return{platform:A.platform??"linkedin",hasPrompt:!!A.prompt,sourceEntityType:A.sourceEntityType,addToQueue:A.addToQueue??!1,generateImage:A.generateImage??!1,coverImage:!!A.coverImage}}}L0();var f12=200,Y12="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function ho(A){if(A.length<=f12)return A;return`${A.slice(0,f12)}\u2026 (truncated, ${A.length} bytes)`}var G3w=Z.looseObject({sub:Z.string()}),D3w=Z.looseObject({id:Z.string()}),z3w=Z.looseObject({value:Z.looseObject({asset:Z.string(),uploadMechanism:Z.looseObject({[Y12]:Z.looseObject({uploadUrl:Z.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[Y12].uploadUrl,assetUrn:A.value.asset})),q3w=Z.looseObject({value:Z.looseObject({uploadUrl:Z.url(),document:Z.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function b3w(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function V3w(A){let Q=z3w.safeParse(A);return Q.success?Q.data:null}function J3w(A){let Q=q3w.safeParse(A);return Q.success?Q.data:null}var I3w="202604";class ts0{config;logger;name="linkedin";apiBaseUrl="https://api.linkedin.com/v2";restApiBaseUrl="https://api.linkedin.com/rest";fetch;cachedUserId=null;constructor(A,Q,w={}){this.config=A,this.logger=Q,this.fetch=w.fetch??globalThis.fetch.bind(globalThis)}async publish(A,Q,w,B){if(!this.config.accessToken)throw Error("LinkedIn access token not configured");let $=await this.getAuthor(),f=B?.[0];if(B&&B.length>1)this.logger.warn("LinkedIn document publishing supports one PDF",{count:B.length});let Y=null;if(f){let U=await this.uploadDocument($,f);return this.publishDocumentPost($,A,U,f.filename)}else if(w){let U=await this.uploadImage($,w);if(U)Y={category:"IMAGE",urn:U}}let X={shareCommentary:{text:A},shareMediaCategory:Y?.category??"NONE",...Y&&{media:[b3w(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:$,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":X},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!H.ok){let U=ho(await H.text());throw this.logger.error("LinkedIn API error",{status:H.status,error:U}),Error(`LinkedIn API error: ${H.status} - ${U}`)}let W=H.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:W,mediaCategory:Y?.category??"NONE"});let K={id:W};if(W)K.url=`https://www.linkedin.com/feed/update/${W}`;return K}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??I3w,"X-Restli-Protocol-Version":"2.0.0"}}async uploadImage(A,Q){try{let w=await this.fetch(`${this.apiBaseUrl}/assets?action=registerUpload`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({registerUploadRequest:{recipes:["urn:li:digitalmediaRecipe:feedshare-image"],owner:A,serviceRelationships:[{relationshipType:"OWNER",identifier:"urn:li:userGeneratedContent"}]}})});if(!w.ok){let X=ho(await w.text());return this.logger.warn("LinkedIn image upload registration failed",{status:w.status,error:X}),null}let B=V3w(await w.json());if(!B)return this.logger.warn("LinkedIn image upload registration was malformed"),null;let{uploadUrl:$,assetUrn:f}=B,Y=await this.fetch($,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!Y.ok)return this.logger.warn("LinkedIn image binary upload failed",{status:Y.status}),null;return this.logger.info("LinkedIn image uploaded",{assetUrn:f}),f}catch(w){return this.logger.warn("LinkedIn image upload error",{error:w}),null}}async uploadDocument(A,Q){let w=await this.fetch(`${this.restApiBaseUrl}/documents?action=initializeUpload`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({initializeUploadRequest:{owner:A}})});if(!w.ok){let f=ho(await w.text());throw Error(`LinkedIn document upload initialization failed: ${w.status} - ${f}`)}let B=J3w(await w.json());if(!B)throw Error("LinkedIn document upload initialization was malformed");let $=await this.fetch(B.uploadUrl,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!$.ok)throw Error(`LinkedIn document binary upload failed: ${$.status}`);return this.logger.info("LinkedIn document uploaded",{documentUrn:B.documentUrn,filename:Q.filename}),B.documentUrn}async publishDocumentPost(A,Q,w,B){let $=await this.fetch(`${this.restApiBaseUrl}/posts`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({author:A,commentary:Q,visibility:"PUBLIC",distribution:{feedDistribution:"MAIN_FEED",targetEntities:[],thirdPartyDistributionChannels:[]},content:{media:{id:w,title:B}},lifecycleState:"PUBLISHED",isReshareDisabledByAuthor:!1})});if(!$.ok){let X=ho(await $.text());throw this.logger.error("LinkedIn document post API error",{status:$.status,error:X}),Error(`LinkedIn document post API error: ${$.status} - ${X}`)}let f=$.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn document post created",{postId:f,documentUrn:w});let Y={id:f};if(f)Y.url=`https://www.linkedin.com/feed/update/${f}`;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 w=await this.fetch("https://api.linkedin.com/v2/userinfo",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(w.ok){let B=G3w.safeParse(await w.json());if(B.success)return this.cachedUserId=`urn:li:person:${B.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 w=ho(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${w}`)}let Q=D3w.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function es0(A,Q,w={}){return new ts0(A,Q,w)}L0();xB();ss0();var F3w=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),k3w=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),X12=Z.enum(["linkedin"]),Z12=Z.enum(["generating","draft","queued","published","failed"]),L3w=Z.enum(["post","deck"]),_3w=Z.object({id:Z.string().min(1)}),N3w=Z.object({title:Z.string(),platform:X12,status:Z12,coverImageId:Z.string().optional(),documents:Z.array(_3w).optional(),publishedAt:Z.string().optional(),platformPostId:Z.string().optional(),sourceEntityId:Z.string().optional(),sourceEntityType:L3w.optional()}),P3w=Z.object({title:Z.string(),platform:X12,status:Z12,publishedAt:Z.string().optional(),platformPostId:Z.string().optional(),slug:Z.string(),error:Z.string().optional()}),H12=Z.object({id:Z.string(),entityType:Z.literal("social-post"),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:k3w,metadata:P3w,contentHash:Z.string(),frontmatter:N3w,body:Z.string(),url:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),typeLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()}),j3w=Z.object({posts:Z.array(H12),totalCount:Z.number().optional(),pagination:F3w.nullable(),baseUrl:Z.string().optional()}),M3w=Z.object({post:H12});function W12(){return{linkedin:JX0,"social-post-list":l1({name:"social-post-list",description:"Social post list page template",schema:j3w,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:IX0}}),"social-post-detail":l1({name:"social-post-detail",description:"Individual social post template",schema:M3w,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:FX0}})}}L0();var x3w=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),platform:Z.enum(["linkedin"]).default("linkedin")}),O3w=Z.object({prompt:Z.string().optional(),content:Z.string().optional(),title:Z.string().optional(),platform:Z.enum(["linkedin"]).optional()});function K12(A){A.eval.registerHandler("generation",async(Q)=>{let w=x3w.parse(Q),B=w.content?`Create an engaging LinkedIn post to share this content:
|
|
7972
7972
|
|
|
7973
|
-
${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:B,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=O3w.parse(Q),B=[],$=Kf.from(async(W)=>{let K={progress:W.progress};if(W.message!==void 0)K.message=W.message;B.push(K)});if(!$)throw Error("Failed to create progress reporter");let Y=await new bj(A.logger,A).process(w,`eval-${Date.now()}`,$),X=!1,H;if(Y.success&&Y.entityId){let W=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});X=!!W,H=W?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:H,progressSteps:B}})}wA();class Co{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:w}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:w});try{let B=await this.entityService.getEntity({entityType:"social-post",id:w});if(!B){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let $=B;if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let f=$.metadata.platform,Y=this.providers.get(f);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let X=r2($.content,vU),H;if(X.metadata.coverImageId)H=await this.fetchImageData(X.metadata.coverImageId);let W=X.metadata.documents??[],K=await this.fetchDocumentData(W);try{if(W.length>0&&K.length===0)throw Error(`Refusing to publish: ${W.length} document(s) referenced but none could be fetched`);let U=W.length===0?await this.resolveSourceAttachment(X.metadata):[],G=K.length>0?K:U,q=G.length?await Y.publish(X.content,$.metadata,H,G):await Y.publish(X.content,$.metadata,H),b=new Date().toISOString(),J=q.id||void 0,V={...X.metadata,status:"published",publishedAt:b,...J&&{platformPostId:J}},k=r7.createPostContent(V,X.content);await this.entityService.updateEntity({entity:{...$,content:k,metadata:{...$.metadata,status:"published",publishedAt:b,platformPostId:J}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:J})}catch(U){let G=U instanceof Error?U.message:String(U),q={...X.metadata,status:"failed"},b=r7.createPostContent(q,X.content);await this.entityService.updateEntity({entity:{...$,content:b,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:G})}}catch(B){let $=SA(B);this.logger.error("Unexpected error in publish handler",{entityId:w,error:$}),await this.reportFailure(Q,w,$)}}async reportSuccess(A,Q,w){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:w}}})}async reportFailure(A,Q,w){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:w}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let w of A){let B=await this.fetchSingleDocumentData(w.id);if(B)Q.push(B)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let w=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!w?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let B=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:B}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let B=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!B?.[1]||!B[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=B[1],f=B[2];return{data:Buffer.from(f,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function U12(A,Q,w){if(Q.size===0){w.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let B=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:B,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function G12(A,Q,w){let B=new Co({sendMessage:A.messaging.send,logger:w.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async($)=>{return await B.handle($.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function D12(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:B,entityId:$,entity:f}=w.payload;if(B!=="post")return{success:!0};if(f.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:$}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${$}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:B,sourceEntityId:$,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(X){let H=SA(X);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function z12(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let Y=await A.jobs.enqueue({type:`${r7.entityType}:generation`,data:{sourceEntityType:B,sourceEntityId:$,platform:f,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${B}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let X=SA(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function q12(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:B}=w.payload;if(B!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let f=null;for(let X of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1}})).length===0){f=X;break}if(!f)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${r7.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:f.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:f.id}),{success:!0}}catch($){let f=SA($);return Q.error("Failed to handle generate:execute:",{error:f}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:f}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function b12({entity:A,config:Q}){let w=EF.parse(A),B=r7.parsePostFrontmatter(w),$=r7.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:B.title,platform:B.platform,body:$,format:"text/markdown",status:B.status,...B.publishedAt&&{publishedAt:B.publishedAt},...B.platformPostId&&{platformPostId:B.platformPostId},...B.sourceEntityType&&{sourceLocalEntityType:B.sourceEntityType},...B.sourceEntityId&&{sourceLocalEntityId:B.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Aa0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:_6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:b12}}var V12={name:"@brains/social-media",version:"0.2.0-alpha.163",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 Qa0 extends sQ{entityType=r7.entityType;schema=EF;adapter=r7;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",V12,A,rs0)}createGenerationHandler(A){return new bj(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return W12()}getDataSources(){return[new VX0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),U12(A,this.providers,this.logger),G12(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)D12(A,this.logger),z12(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");q12(A,this.logger),K12(A),this.unregisterAtprotoProjection=B8.getInstance().register(Aa0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=es0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function go(A={}){return new Qa0(A)}L0();var R3w=Z.enum(["draft","queued","published","failed"]),J12=Z.object({status:R3w.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class wa0{name="internal";async publish(A,Q){return{id:"internal"}}}var yo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},AY={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"},TF={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"},I12={REGISTER:"publish-assets:register"};L0();var h3w=Z.enum(["provider"]),F12=Z.object({executionMode:h3w.optional(),publishResultIdField:Z.string().min(1).optional(),publishTimestampField:Z.string().min(1).optional(),enabled:Z.boolean().optional()}).strict();var C3w=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),k12=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),C3w).optional()});class $3{static instance=null;queues=new Map;static getInstance(){return $3.instance??=new $3,$3.instance}static resetInstance(){$3.instance=null}static createFresh(){return new $3}constructor(){}async add(A,Q,w=yo){let B=this.getOrCreateQueue(A),$=B.find((X)=>X.entityId===Q);if($)return{position:$.position};let f=B.length+1,Y={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(Y),{position:f}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let B=w.findIndex(($)=>$.entityId===Q);if(B===-1)return;w.splice(B,1),this.recalculatePositions(w)}async reorder(A,Q,w){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((X)=>X.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let Y=Math.max(0,Math.min(w-1,B.length));B.splice(Y,0,f),this.recalculatePositions(B)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let w=Q[0];if(!w)continue;if(!A||w.queuedAt<A.queuedAt)A=w}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift()??null;if(w)this.recalculatePositions(Q);return w}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,w]of this.queues.entries())if(w.length>0)A.push(Q);return A}getOrCreateQueue(A){let Q=this.queues.get(A);if(!Q)Q=[],this.queues.set(A,Q);return Q}recalculatePositions(A){A.forEach((Q,w)=>{Q.position=w+1})}}class f3{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new wa0;static getInstance(){return f3.instance??=new f3,f3.instance}static resetInstance(){f3.instance=null}static createFresh(){return new f3}constructor(){}register(A,Q,w){let B=this.providers.get(A);if(B&&B.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,w?.executionMode??"provider"),w?.publishResultIdField)this.publishResultIdFields.set(A,w.publishResultIdField);else this.publishResultIdFields.delete(A);if(w?.publishTimestampField)this.publishTimestampFields.set(A,w.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function L12(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await g3w(A,Q)}async function g3w(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let B={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:AY.FAILED,payload:B,sender:"publish-service",broadcast:!0});Q.onFailed?.(B);return}Ba0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=SA(w);Q.retryTracker.recordFailure(A.entityId,B);let $=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:B,retryCount:$?.retryCount??1,willRetry:!1})}}function Ba0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:AY.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});B.onPublish?.({entityType:A,entityId:Q,result:w})}function _12(A,Q,w,B){B.retryTracker.recordFailure(Q,w);let $=B.retryTracker.getRetryInfo(Q),f={entityType:A,entityId:Q,error:w,retryCount:$?.retryCount??1,willRetry:!1};if(B.messageBus)B.messageBus.send({type:AY.FAILED,payload:f,sender:"publish-service",broadcast:!0});B.onFailed?.(f)}async function N12(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,w);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:TF.SKIPPED,payload:{entityType:A,reason:$.reason??"Conditions not met"},sender:"content-pipeline"});return}}let B={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:TF.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function P12(A,Q,w){if(w)w.send({type:TF.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function j12(A,Q,w){if(w)w.send({type:TF.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var y3w=1000;class $a0{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,w)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(y3w,()=>this.processUnscheduledTypes())}stop(){if(E3w(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await L12(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function E3w(A){for(let Q of A.values())Q.stop();A.clear()}class fa0{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){T3w(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await N12(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function T3w(A){for(let Q of A.values())Q.stop();A.clear()}class RU{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return RU.instance??=new RU(A),RU.instance}static resetInstance(){if(RU.instance)RU.instance.stop();RU.instance=null}static createFresh(A){return new RU(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new $a0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new fa0({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){Ba0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){_12(A,Q,w,this.publishDeps)}completeGeneration(A,Q){P12(A,Q,this.config.messageBus)}failGeneration(A,Q){j12(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,w){try{this.config.backend.validateCron(Q)}catch(B){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${SA(B)}`,{cause:B})}}}class Y3{static instance=null;retries=new Map;static getInstance(){return Y3.instance??=new Y3,Y3.instance}static resetInstance(){Y3.instance=null}static createFresh(){return new Y3}constructor(){}recordFailure(A,Q){let B=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:B,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}function Eo(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function Ya0(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function S3w(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let B=A.substring(9);return B.includes("Z")||B.includes("+")||B.includes("-")?Za0(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):Za0(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function M12(A,Q,w){return v12(S3w(A,Q),w)}function v12(A,Q){let w=new Date(Eo(A)),B=To(w,A.tz),$=Eo(A),f=Eo(B),Y=$-f,X=new Date(w.getTime()+Y),H=To(X,A.tz);if(Ya0(H,A)){let U=new Date(X.getTime()-3600000),G=To(U,A.tz);return Ya0(G,A)?U:X}let W=new Date(X.getTime()+Eo(A)-Eo(H)),K=To(W,A.tz);if(Ya0(K,A))return W;if(Q)throw Error("Invalid date passed to fromTZ()");return X.getTime()>W.getTime()?X:W}function To(A,Q){let w,B;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),B=w.formatToParts(A)}catch(f){let Y=f instanceof Error?f.message:String(f);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let $={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let f of B)(f.type==="year"||f.type==="month"||f.type==="day"||f.type==="hour"||f.type==="minute"||f.type==="second")&&($[f.type]=parseInt(f.value,10));if(isNaN($.year)||isNaN($.month)||isNaN($.day)||isNaN($.hour)||isNaN($.minute)||isNaN($.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify($)}`);return $.hour===24&&($.hour=0),{y:$.year,m:$.month,d:$.day,h:$.hour,i:$.minute,s:$.second,tz:Q}}function Za0(A,Q,w,B,$,f,Y){return{y:A,m:Q,d:w,h:B,i:$,s:f,tz:Y}}var R12=[1,2,4,8,16],x12=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let B;switch(this.mode){case"5-part":B=5;break;case"6-part":B=6;break;case"7-part":B=7;break;case"5-or-6-parts":B=[5,6];break;case"6-or-7-parts":B=[6,7];break;default:B=0}if(!(Array.isArray(B)?B.includes(Q):Q===B)){let $=Array.isArray(B)?B.join(" or "):B.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${$} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!f&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let X=Q.split(",");if(X.length>1)for(let H=0;H<X.length;H++)this.partToArray(A,X[H],w,B);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,B):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,B):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,B):Q!==""&&this.handleNumber(Q,A,w,B)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,B){let $=this.extractNth(A,Q),f=A.toUpperCase().includes("W");if(Q!=="day"&&f)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");f&&(Q="nearestWeekdays");let Y=parseInt($[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,$[1]||B)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,B,$){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+$+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[B].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[B].length+")")}}handleRangeWithStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let $=this.extractNth(A,Q),f=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(f===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,H]=f,W=parseInt(Y,10)+w,K=parseInt(X,10)+w,U=parseInt(H,10);this.validateNotNaN(W,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(W,K,U,Q,A);for(let G=W;G<=K;G+=U)this.setPart(Q,G,$[1]||B)}extractNth(A,Q){let w=A,B;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");B=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");B="L",w=w.slice(0,-1)}return[w,B]}handleRange(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(f[0],10)+w,X=parseInt(f[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(X,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,X,void 0,Q,A);for(let H=Y;H<=X;H++)this.setPart(Q,H,$[1]||B)}handleStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)f[0]===""&&(f[0]="*");else{if(f[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(f[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;f[0]!=="*"&&(Y=parseInt(f[0],10)+w);let X=parseInt(f[1],10);this.validateNotNaN(X,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,X,Q,A);for(let H=Y;H<this[Q].length;H+=X)this.setPart(Q,H,$[1]||B)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|R12[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},Xa0=[31,28,31,30,31,30,31,31,30,31,30,31],z$=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],o7=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?Xa0[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let B=this.getLastDayOfMonth(Q,w),$=new Date(Date.UTC(Q,w,B)).getUTCDay();return $===0?B-2:$===6?B-1:B}getNearestWeekday(Q,w,B){let $=this.getLastDayOfMonth(Q,w);if(B>$)return-1;let f=new Date(Date.UTC(Q,w,B)).getUTCDay();return f===0?B===$?B-2:B+1:f===6?B===1?B+2:B-1:B}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),Y=0;for(let X=1;X<=B;X++)new Date(Date.UTC(Q,w,X)).getUTCDay()===f&&Y++;if($&63&&R12[Y-1]&$)return!0;if($&32){let X=this.getLastDayOfMonth(Q,w);for(let H=B+1;H<=X;H++)if(new Date(Date.UTC(Q,w,H)).getUTCDay()===f)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=To(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let B=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${B}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>Xa0[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=M12(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(M12(Q,this.tz))}findNext(Q,w,B,$){return this._findMatch(Q,w,B,$,1)}_findMatch(Q,w,B,$,f){let Y=this[w],X;B.lastDayOfMonth&&(X=this.getLastDayOfMonth(this.year,this.month));let H=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,W=this[w]+$,K=f===1?(U)=>U<B[w].length:(U)=>U>=0;for(let U=W;K(U);U+=f){let G=B[w][U];if(w==="day"&&!G){for(let q=0;q<B.nearestWeekdays.length;q++)if(B.nearestWeekdays[q]){let b=this.getNearestWeekday(this.year,this.month,q-$);if(b===-1)continue;if(b===U-$){G=1;break}}}if(w==="day"&&B.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-$===q&&(G=1)}if(w==="day"&&B.lastDayOfMonth&&U-$==X&&(G=1),w==="day"&&!B.starDOW){let q=B.dayOfWeek[(H+(U-$-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-$,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);B.useAndLogic?G=G&&q:!Q.domAndDow&&!B.starDOM?G=G||q:G=G&&q}if(G)return this[w]=U-$,Y!==this[w]?2:1}return 3}recurse(Q,w,B){if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let f=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){f=Y;break}if(f===-1)return null;this.year=f,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let $=this.findNext(w,z$[B][0],Q,z$[B][2]);if($>1){let f=B+1;for(;f<z$.length;)this[z$[f][0]]=-z$[f][2],f++;if($===3){if(this[z$[B][1]]++,this[z$[B][0]]=-z$[B][2],this.apply(),B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=z$.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,B)}increment(Q,w,B){return this.second+=w.interval!==void 0&&w.interval>1&&B?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,B,$=0){if($>1e4)return null;if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let X=this.year-1;X>=0;X--)if(Q.year[X]===1){Y=X;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let f=this.findPrevious(w,z$[B][0],Q,z$[B][2]);if(f>1){let Y=B+1;for(;Y<z$.length;){let X=z$[Y][0],H=z$[Y][2],W=this.getMaxPatternValue(X,Q,H);this[X]=W,Y++}if(f===3){if(this[z$[B][1]]--,B===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if(B===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let G=U!==1?Xa0[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>G&&(this.day=G)}this.apply();let X=z$[B][0],H=z$[B][2],W=this.getMaxPatternValue(X,Q,H);if(X==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[X]=Math.min(W,K)}else this[X]=W;if(this.apply(),B===0){let K=z$[1][2],U=this.getMaxPatternValue("day",Q,K),G=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,G);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,z$[2][2]),this.minute=this.getMaxPatternValue("minute",Q,z$[3][2]),this.second=this.getMaxPatternValue("second",Q,z$[4][2]))}if(B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,$+1)}else if(this.apply())return this.recurseBackward(Q,w,B-1,$+1)}return B+=1,B>=z$.length?this:this.year<0?null:this.recurseBackward(Q,w,B,$+1)}getMaxPatternValue(Q,w,B){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let $=w[Q].length-1;$>=0;$--)if(w[Q][$])return $-B;return w[Q].length-1-B}findPrevious(Q,w,B,$){return this._findMatch(Q,w,B,$,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):v12(Za0(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let B=0;B<z$.length;B++){let $=z$[B][0],f=z$[B][2],Y=this[$];if(Y+f<0||Y+f>=Q[$].length)return!1;let X=Q[$][Y+f];if($==="day"){if(!X){for(let H=0;H<Q.nearestWeekdays.length;H++)if(Q.nearestWeekdays[H]){let W=this.getNearestWeekday(this.year,this.month,H-f);if(W!==-1&&W===Y){X=1;break}}}if(Q.lastWeekday){let H=this.getLastWeekday(this.year,this.month);Y===H&&(X=1)}if(Q.lastDayOfMonth){let H=this.getLastDayOfMonth(this.year,this.month);Y===H&&(X=1)}if(!Q.starDOW){let H=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),W=Q.dayOfWeek[(H+(Y-1))%7];W&&W&63&&(W=this.isNthWeekdayOfMonth(this.year,this.month,Y,W)?1:0),Q.useAndLogic?X=X&&W:!w.domAndDow&&!Q.starDOM?X=X||W:X=X&&W}}if(!X)return!1}return!0}};function m3w(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new o7(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new o7(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function So(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function u3w(A){return So(A)}function c3w(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var O12=30000,kX0=[],Ha0=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let B,$;if(So(Q))$=Q;else if(typeof Q=="object")B=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(So(w))$=w;else if(typeof w=="object")B=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=B?.name,this.options=m3w(B),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:B?B.maxRuns:void 0,paused:B?B.paused:!1,pattern:new x12("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new o7(A,this.getTz()):this._states.pattern=new x12(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(kX0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");kX0.push(this)}return $!==void 0&&u3w($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let B=[],$=Q?new o7(Q,this.getTz()):null,f=w==="next"?this._next:this._previous;for(;A--;){let Y=f.call(this,$);if(!Y)break;let X=Y.getDate(!1);B.push(this.applyDayOffset(X)),$=Y}return B}match(A){if(this._states.once){let w=new o7(A,this.getTz());w.ms=0;let B=new o7(this._states.once,this.getTz());return B.ms=0,w.getTime()===B.getTime()}let Q=new o7(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,B=!this._states.kill;return Q&&w&&B&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof o7||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new o7(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=kX0.indexOf(this);A>=0&&kX0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>O12&&(Q=O12),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&c3w(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new o7(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(So(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new o7(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),B=this._states.blocking&&this.options.protect;w&&!B?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&B&&So(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new o7(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new o7(A,this.getTz());return!w&&B!==this._states.once&&(B=B.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||B===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&B.getTime()>=this.options.stopAt.getTime()?null:B}_previous(A){let Q=new o7(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new o7(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new o7(void 0,this.getTz()),B=A;if(this.options.startAt.getTime()<=w.getTime()){B=this.options.startAt;let $=B.getTime()+this.options.interval*1000;for(;$<=w.getTime();)B=new o7(B,this.getTz()).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class LX0{scheduleCron(A,Q){let w=new Ha0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new Ha0(A).stop()}}L0();var h12=Z.union([Z.string().min(1),Z.object({location:Z.enum(["metadata","frontmatter"]),field:Z.string().min(1)})]),_X0=Z.object({entityType:Z.string().min(1),attachmentType:Z.string().min(1),mediaEntityType:Z.enum(["image","document"]),targetEntityField:h12.optional(),requiredWhen:Z.object({status:Z.string().min(1).optional(),visibility:Z.string().min(1).optional()}).optional(),autoGenerate:Z.boolean().optional(),requiredForPublish:Z.boolean().optional(),jobType:Z.string().min(1).optional()});function Wa0(A){return`${A.entityType}:${A.attachmentType}`}class X3{static instance=null;definitions=new Map;static getInstance(){return X3.instance??=new X3,X3.instance}static resetInstance(){X3.instance=null}static createFresh(){return new X3}constructor(){}register(A){let Q=_X0.parse(A),w=Wa0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(Wa0({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter((w)=>w.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(Wa0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}l9();D2();class NX0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter(($)=>$.autoGenerate===!0).filter(($)=>!Q.attachmentType||$.attachmentType===Q.attachmentType),B={checked:w.length,enqueued:0,skipped:0};for(let $ of w)if(await this.ensureDefinition(A,$))B.enqueued+=1;else B.skipped+=1;return B}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let w=this.resolveJobType(Q);if(!w)return!1;let B=this.getPredictedMediaId(A,Q),$=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:B,dedupKey:$,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:$}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:w}),!0}matchesPolicy(A,Q){let{requiredWhen:w}=Q;if(!w)return!0;if(w.status&&A.metadata.status!==w.status)return!1;if(w.visibility&&A.visibility!==w.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return Ka0(A.metadata[Q]);if(Q.location==="metadata")return Ka0(A.metadata[Q.field]);let{frontmatter:w}=M6(A.content);return Ka0(w[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let w=Q.attachmentType==="og-image"?"og":Q.attachmentType;return H1(`${w}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function Ka0(A){return typeof A==="string"?A.length>0:A!==void 0}wA();L0();var l3w=Z.object({id:Z.string().min(1)});async function g12(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:Y}=p3w(Q.content),X=B?await n3w(A,B):void 0,H;if($&&$.length>0){let K=await r3w(A,$);if(K.length>0)H=K}H??=await d3w(A,f,Y);let W={bodyContent:w};if(X)W.imageData=X;if(H&&H.length>0)W.documentData=H;return W}function p3w(A){try{let Q=r2(A,Z.record(Z.string(),Z.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=i3w(Q.metadata.documents),f=C12(Q.metadata.sourceEntityType),Y=C12(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function i3w(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=l3w.safeParse(Q);return w.success?[w.data]:[]})}function C12(A){return typeof A==="string"&&A.length>0?A:void 0}async function d3w(A,Q,w){if(!Q||!w)return;let B=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return B?[B]:void 0}async function n3w(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=y12(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function r3w(A,Q){return(await Promise.all(Q.map((B)=>o3w(A,B)))).filter((B)=>B!==void 0)}async function o3w(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=y12(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:s3w(w,Q.id)}}function y12(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function s3w(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}l9();var a3w=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function Ua0(A,Q,w,B={}){let $=B.publishTimestampField??"publishedAt",f=Q.metadata[$],Y=B.publishedAt??(typeof f==="string"?f:void 0)??new Date().toISOString(),X={...Q.metadata,status:"published",[$]:Y,platformId:w.id,...t3w(w.id,B.publishResultIdField)},H={...Q,content:E12(Q.content,Y,w.id,B.publishResultIdField,$),metadata:X};return await A.entityService.updateEntity({entity:H}),H}function E12(A,Q,w,B,$="publishedAt"){if(!a3w.test(A))return A;let f=b4(b4(A,"status","published"),$,Q);if(!w||!B)return f;return b4(f,B,w)}function t3w(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class yy{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:B}=A;if(!w&&!B)return{error:"Either 'id' or 'slug' must be provided"};let $=await this.findPublishableEntity(Q,w,B);if(!$)return{error:`Entity not found: ${Q}:${w??B}`};if($.visibility!=="public")return{error:`Cannot publish ${Q}:${$.id} to a public provider because visibility is ${$.visibility}`};if($.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:$}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:B}=A,$=this.deps.providerRegistry.get(B),{bodyContent:f,imageData:Y,documentData:X}=await g12(this.deps.context,w),H=await $.publish(f,w.metadata,Y,X),W=this.deps.providerRegistry.getPublishResultIdField(B),K=this.deps.providerRegistry.getPublishTimestampField(B),U=await Ua0(this.deps.context,w,H,{...W?{publishResultIdField:W}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,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,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}wA();L0();var Ga0=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),Da0=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),e3w=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(Da0).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),Azw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),za0=Z.union([e3w,Azw]);function PX0(A,Q,w){return{...x6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",Ga0,async($,f)=>{let{action:Y,entityType:X,entityId:H,position:W}=$;switch(Y){case"list":return Qzw(w,X);case"add":return wzw(A,w,X,H,f);case"remove":return Bzw(A,w,X,H,f);case"reorder":return $zw(A,w,X,H,W,f);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:za0}}async function Qzw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let Y=await A.list(f);w.push(...Y)}w.sort((f,Y)=>new Date(f.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(w.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:w.map(($,f)=>({position:f+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${w.length} items in queue`}}async function wzw(A,Q,w,B,$){let f=qa0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let Y=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function Bzw(A,Q,w,B,$){let f=qa0("remove",w,B);if(!f.success)return f.error;return A.permissions.assertEntityActionAllowed(f.entityType,"update",$??{}),await Q.remove(f.entityType,f.entityId),{success:!0,data:{entityType:f.entityType,entityId:f.entityId},message:"Removed from queue"}}async function $zw(A,Q,w,B,$,f){let Y=qa0("reorder",w,B);if(!Y.success)return Y.error;let X=fzw($);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",f??{}),await Q.reorder(Y.entityType,Y.entityId,X.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:X.position},message:`Moved to position ${X.position}`}}function qa0(A,Q,w){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!w)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:w}}function fzw(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}}L0();import{createHash as Yzw}from"crypto";var ba0=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish"),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),Xzw=Z.object({entityType:Z.string(),id:Z.string().optional(),slug:Z.string().optional(),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),Zzw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),Hzw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),Wzw=Z.object({success:Z.literal(!1).optional(),error:Z.string().optional(),needsConfirmation:Z.literal(!0),toolName:Z.string(),summary:Z.string(),preview:Z.string().optional(),args:Z.unknown()}),Va0=Z.union([Zzw,Hzw,Wzw]),Kzw=900000;function jX0(A,Q,w,B){let $=B??new yy({context:A,providerRegistry:w}),f=`${Q}_publish`;return{name:f,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). 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:ba0.shape,outputSchema:Va0,visibility:"anchor",sideEffects:"external",handler:async(Y,X)=>{let H=Xzw.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join(", ")}`};let W=H.data,{entityType:K,id:U,slug:G}=W;try{A.permissions.assertEntityActionAllowed(K,"publish",X)}catch(J){return{success:!1,error:J instanceof Error?J.message:String(J)}}let q=await $.resolveCandidate({entityType:K,id:U,slug:G});if("error"in q)return{success:!1,error:q.error};let{entity:b}=q;if(W.confirmed){let J=Gzw(f,W,b);if(J!==null)return J;let V;try{V=await $.publish({entityType:K,id:b.id})}catch(L){return{success:!1,error:L instanceof Error?L.message:String(L)}}if("error"in V)return{success:!1,error:V.error};let{entity:k,result:N}=V;return{success:!0,data:{entityType:K,entityId:k.id,platformId:N.id,url:N.url},message:`Published ${K}:${k.id}`}}return Uzw(f,W,b)}}}function Uzw(A,Q,w){let B=new Date(Date.now()+Kzw).toISOString(),$=T12(A,w,B),f=Dzw(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${f}"?`,preview:`This will publish ${w.entityType}:${w.id} to its registered public publish provider.`,args:{...Q,id:w.id,slug:void 0,confirmed:!0,confirmationToken:$,contentHash:w.contentHash,expiresAt:B}}}function Gzw(A,Q,w){let{confirmationToken:B,contentHash:$,expiresAt:f}=Q;if(!B||!f)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(f);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($&&$!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if(B!==T12(A,w,f))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function T12(A,Q,w){return Yzw("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update(w).digest("hex")}function Dzw(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let w=A.metadata.subject;if(typeof w==="string"&&w.length>0)return w;let B=A.metadata.slug;if(typeof B==="string"&&B.length>0)return B;return A.id}wA();L0();var Ja0=Z.object({entityType:Z.string().min(1).describe("Entity type to reconcile"),status:Z.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:Z.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Ia0=Z.object({success:Z.literal(!0),data:Z.object({entityType:Z.string(),assetType:Z.string().optional(),checkedEntities:Z.number(),checkedAssets:Z.number(),enqueued:Z.number(),skipped:Z.number()}),message:Z.string().optional()});function MX0(A,Q,w,B){return{...x6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",Ja0,async(f,Y)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",Y),w.list(f.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!f.assetType||G.attachmentType===f.assetType).length===0)return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${f.entityType}`};let H=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),W=0,K=0,U=0;for(let G of H){let q=await B.ensureForEntity(G,{...f.assetType&&{attachmentType:f.assetType}});W+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:H.length,checkedAssets:W,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Ia0}}wA();function S12(A,Q){zzw(A,Q),qzw(A,Q),bzw(A,Q),Vzw(A,Q)}function zzw(A,Q){A.messaging.subscribe(AY.REGISTER,async(w)=>Jzw(Q,w.payload)),A.messaging.subscribe(AY.QUEUE,async(w)=>Lzw(A,Q,w.payload)),A.messaging.subscribe(AY.DIRECT,async(w)=>_zw(A,Q,w.payload)),A.messaging.subscribe(AY.REMOVE,async(w)=>Nzw(Q,w.payload)),A.messaging.subscribe(AY.REORDER,async(w)=>Pzw(Q,w.payload)),A.messaging.subscribe(AY.LIST,async(w)=>jzw(A,Q,w.payload)),A.messaging.subscribe(AY.REPORT_SUCCESS,async(w)=>Mzw(Q,w.payload)),A.messaging.subscribe(AY.REPORT_FAILURE,async(w)=>xzw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function qzw(A,Q){A.messaging.subscribe(TF.REPORT_SUCCESS,async(w)=>Ozw(Q,w.payload)),A.messaging.subscribe(TF.REPORT_FAILURE,async(w)=>vzw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function bzw(A,Q){A.messaging.subscribe(I12.REGISTER,async(w)=>Izw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Vzw(A,Q){let w=async(B)=>Fzw(A,Q,B.payload);A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function Jzw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?F12.safeParse($):void 0;if(f&&!f.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:f.error.message}),{success:!1};if(B)A.providerRegistry.register(w,B,f?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:B.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(f){let Y=SA(f);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Izw(A,Q){let w=_X0.safeParse(Q);if(!w.success)return A.logger.warn("Invalid publish asset registration",{error:w.error.message}),{success:!1};return A.publishAssetRegistry.register(w.data),A.logger.info("Registered publish asset",{entityType:w.data.entityType,attachmentType:w.data.attachmentType,mediaEntityType:w.data.mediaEntityType}),{success:!0}}async function Fzw(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let B=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!kzw(B))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(B),{success:!0}}catch(B){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:SA(B)}),{success:!1}}}function kzw(A){if(!A)return!1;let Q=J12.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Lzw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??yo;A.permissions.assertEntityActionAllowed(B,"publish",f);let Y=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:AY.QUEUED,payload:{entityType:B,entityId:$,position:Y.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:Y.position}),{success:!0}}catch(f){let Y=SA(f);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function _zw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??yo;try{if(A.permissions.assertEntityActionAllowed(B,"publish",f),!Q.providerRegistry.has(B))return Q.scheduler.failPublish(B,$,`No publish provider registered for ${B}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in Y)return Q.scheduler.failPublish(B,$,Y.error),{success:!1};return Q.scheduler.completePublish(B,$,Y.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(Y){let X=SA(Y);return Q.logger.error(`Failed direct publish request: ${X}`),{success:!1}}}async function Nzw(A,Q){let{entityType:w,entityId:B}=Q;try{return await A.queueManager.remove(w,B),A.logger.debug(`Entity removed from queue: ${B}`,{entityType:w}),{success:!0}}catch($){let f=SA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function Pzw(A,Q){let{entityType:w,entityId:B,position:$}=Q;try{return await A.queueManager.reorder(w,B,$),A.logger.debug(`Entity reordered: ${B}`,{entityType:w,newPosition:$}),{success:!0}}catch(f){let Y=SA(f);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function jzw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:AY.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=SA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function Mzw(A,Q){let{entityType:w,entityId:B,result:$}=Q;return A.scheduler.completePublish(w,B,$),A.logger.info(`Publish reported success: ${B}`,{entityType:w}),{success:!0}}async function xzw(A,Q){let{entityType:w,entityId:B,error:$}=Q;A.scheduler.failPublish(w,B,$);let f=A.retryTracker.getRetryInfo(B);return A.logger.info(`Publish reported failure: ${B}`,{entityType:w,error:$,retryCount:f?.retryCount}),{success:!0}}async function Ozw(A,Q){let{entityType:w,entityId:B}=Q;return A.scheduler.completeGeneration(w,B),A.logger.info("Generation completed",{entityType:w,entityId:B}),{success:!0}}async function vzw(A,Q){let{entityType:w,error:B}=Q;return A.scheduler.failGeneration(w,B),A.logger.warn("Generation failed",{entityType:w,error:B}),{success:!0}}async function m12(A,Q,w,B){try{if(B.skipIfDraftExists!==!1){if((await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(B.maxUnpublishedDrafts!==void 0){let $=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:B.maxUnpublishedDrafts+1}});if($.length>=B.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${B.maxUnpublishedDrafts})`}}if(B.minSourceEntities!==void 0&&B.sourceEntityType){let $=await A.listEntities({entityType:B.sourceEntityType,options:{publishedOnly:!0,limit:B.minSourceEntities}});if($.length<B.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${B.minSourceEntities} ${B.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:w,error:SA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${SA($)}`}}}function u12(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:Y,logger:X}=A,H=Rzw(Q);return RU.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:X,backend:new LX0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(W,K)=>m12(Q.entityService,X,W,K)})}function Rzw(A){return{send:async($)=>{return A.messaging.send({type:$.type,payload:$.payload,...$.target!==void 0?{target:$.target}:{},...$.metadata!==void 0?{metadata:$.metadata}:{},...$.broadcast!==void 0?{broadcast:$.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}async function c12(A,Q,w){let B=A.getEntityTypes();for(let f of B){let Y=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let X of Y)await Q.add(X.entityType,X.id)}let $=0;for(let f of B){let Y=await Q.list(f);$+=Y.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}L0();var hzw=["draft","queued","published","failed"];async function l12(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>Tzw(A),digestProvider:gzw}})}var Czw=Z.object({summary:Z.object({draft:Z.number(),queued:Z.number(),published:Z.number(),failed:Z.number()}),generating:Z.array(Z.unknown())});function gzw(A){let{summary:Q,generating:w}=Czw.parse(A),B=Q.queued+w.length,$=B===0?"idle":`${Q.queued} queued \xB7 ${w.length} generating`,f=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`,Y=Q.draft+Q.failed;return{digest:[{label:"Pipeline",value:$,...B>0?{tone:"warn"}:{}},{label:"Awaiting review",value:f,...Y>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Y}}var yzw=Z.object({sourceEntityType:Z.string(),sourceEntityId:Z.string(),attachmentType:Z.string().optional()});async function Ezw(A){let Q=await A.jobs.getActiveJobs(),w=[];for(let B of Q){if(B.source!=="content-pipeline")continue;if(B.status!=="pending"&&B.status!=="processing")continue;let $;try{$=JSON.parse(B.data)}catch{continue}let f=yzw.safeParse($);if(!f.success)continue;w.push({id:B.id,label:f.data.attachmentType??B.type,target:`${f.data.sourceEntityType}/${f.data.sourceEntityId}`,status:B.status})}return w}async function Tzw(A){let Q=A.entityService.getEntityTypes(),w=[],B={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let f=await A.entityService.listEntities({entityType:$});for(let Y of f){let X=Szw(Y.metadata.status);if(!X)continue;B[X]++,w.push({id:Y.id,title:mzw(Y.id,Y.metadata.title),type:$,status:X})}}return{summary:B,items:w,generating:await Ezw(A)}}function Szw(A){return hzw.find((Q)=>Q===A)}function mzw(A,Q){return typeof Q==="string"?Q:A}var p12={name:"@brains/content-pipeline",version:"0.2.0-alpha.163",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},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 Fa0 extends Aw{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",p12,A,k12)}async onRegister(A){this.pluginContext=A,this.queueManager=$3.createFresh(),this.providerRegistry=f3.createFresh(),this.retryTracker=Y3.createFresh(),this.publishAssetRegistry=X3.createFresh(),this.publishAssetPreflight=new NX0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new yy({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=u12({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),S12(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await c12(A.entityService,this.queueManager,this.logger),await l12(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[PX0(this.pluginContext,this.id,this.queueManager),jX0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),MX0(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}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),$3.resetInstance(),f3.resetInstance(),Y3.resetInstance(),X3.resetInstance()}}function ka0(A={}){return new Fa0(A)}wA();L0();var i12=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),La0=Z.object({cloudflare:i12.optional()});wA();L0();var czw=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function lzw(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 d12(A,Q,w){let B=[];if(!w)return B;return B.push(x6(A,"query",`Query website analytics from Cloudflare.
|
|
7973
|
+
${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:B,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=O3w.parse(Q),B=[],$=Kf.from(async(W)=>{let K={progress:W.progress};if(W.message!==void 0)K.message=W.message;B.push(K)});if(!$)throw Error("Failed to create progress reporter");let Y=await new bj(A.logger,A).process(w,`eval-${Date.now()}`,$),X=!1,H;if(Y.success&&Y.entityId){let W=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});X=!!W,H=W?.content.slice(0,300)}return{...Y,entityExists:X,entityPreview:H,progressSteps:B}})}wA();class Co{sendMessage;logger;entityService;providers;permissions;resolveAttachment;constructor(A){this.sendMessage=A.sendMessage,this.logger=A.logger,this.entityService=A.entityService,this.providers=A.providers,this.permissions=A.permissions,this.resolveAttachment=A.resolveAttachment}async handle(A){let{entityType:Q,entityId:w}=A;if(Q!=="social-post")return;this.permissions.assertEntityActionAllowed(Q,"publish",A.authContext??{userPermissionLevel:"anchor"}),this.logger.debug("Handling publish:execute",{entityId:w});try{let B=await this.entityService.getEntity({entityType:"social-post",id:w});if(!B){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let $=B;if($.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let f=$.metadata.platform,Y=this.providers.get(f);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${f}`);return}let X=r2($.content,vU),H;if(X.metadata.coverImageId)H=await this.fetchImageData(X.metadata.coverImageId);let W=X.metadata.documents??[],K=await this.fetchDocumentData(W);try{if(W.length>0&&K.length===0)throw Error(`Refusing to publish: ${W.length} document(s) referenced but none could be fetched`);let U=W.length===0?await this.resolveSourceAttachment(X.metadata):[],G=K.length>0?K:U,q=G.length?await Y.publish(X.content,$.metadata,H,G):await Y.publish(X.content,$.metadata,H),b=new Date().toISOString(),J=q.id||void 0,V={...X.metadata,status:"published",publishedAt:b,...J&&{platformPostId:J}},k=r7.createPostContent(V,X.content);await this.entityService.updateEntity({entity:{...$,content:k,metadata:{...$.metadata,status:"published",publishedAt:b,platformPostId:J}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:f,platformPostId:J})}catch(U){let G=U instanceof Error?U.message:String(U),q={...X.metadata,status:"failed"},b=r7.createPostContent(q,X.content);await this.entityService.updateEntity({entity:{...$,content:b,metadata:{...$.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:f,error:G})}}catch(B){let $=SA(B);this.logger.error("Unexpected error in publish handler",{entityId:w,error:$}),await this.reportFailure(Q,w,$)}}async reportSuccess(A,Q,w){await this.sendMessage({type:"publish:report:success",payload:{entityType:A,entityId:Q,result:{id:w}}})}async reportFailure(A,Q,w){await this.sendMessage({type:"publish:report:failure",payload:{entityType:A,entityId:Q,error:w}})}async resolveSourceAttachment(A){if(!this.resolveAttachment||!A.sourceEntityType||!A.sourceEntityId)return[];let Q=await this.resolveAttachment({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:"carousel"});return Q?[Q]:[]}async fetchDocumentData(A){if(!A?.length)return[];let Q=[];for(let w of A){let B=await this.fetchSingleDocumentData(w.id);if(B)Q.push(B)}return Q}async fetchSingleDocumentData(A){try{let Q=await this.entityService.getEntity({entityType:"document",id:A});if(!Q){this.logger.warn("Document not found",{documentId:A});return}let w=Q.content.match(/^data:application\/pdf;base64,(.+)$/);if(!w?.[1]){this.logger.warn("Invalid document data URL format",{documentId:A});return}let B=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:B}}catch(Q){this.logger.warn("Failed to fetch document",{documentId:A,error:Q});return}}async fetchImageData(A){try{let Q=await this.entityService.getEntity({entityType:"image",id:A});if(!Q){this.logger.warn("Cover image not found",{imageId:A});return}let B=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!B?.[1]||!B[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let $=B[1],f=B[2];return{data:Buffer.from(f,"base64"),mimeType:$}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function U12(A,Q,w){if(Q.size===0){w.debug("No providers configured, skipping publish-pipeline registration");return}A.messaging.subscribe("system:plugins:ready",async()=>{let B=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:B,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function G12(A,Q,w){let B=new Co({sendMessage:A.messaging.send,logger:w.child("PublishExecuteHandler"),entityService:A.entityService,providers:Q,permissions:A.permissions,resolveAttachment:A.attachments.resolve});A.messaging.subscribe("publish:execute",async($)=>{return await B.handle($.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function D12(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:B,entityId:$,entity:f}=w.payload;if(B!=="post")return{success:!0};if(f.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:$}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${$}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:B,sourceEntityId:$,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${$}`),{success:!0}}catch(X){let H=SA(X);return Q.error(`Failed to trigger auto-generate for ${$}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function z12(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:B,sourceEntityId:$,platform:f}=w.payload;try{let Y=await A.jobs.enqueue({type:`${r7.entityType}:generation`,data:{sourceEntityType:B,sourceEntityId:$,platform:f,addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info(`Social post generation job enqueued for ${B}/${$}`,{jobId:Y}),{success:!0,jobId:Y}}catch(Y){let X=SA(Y);return Q.error(`Failed to enqueue social post generation for ${$}:`,{error:X}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function q12(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:B}=w.payload;if(B!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let $=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if($.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let f=null;for(let X of $)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:X.id}},limit:1}})).length===0){f=X;break}if(!f)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${r7.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:f.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:f.id}),{success:!0}}catch($){let f=SA($);return Q.error("Failed to handle generate:execute:",{error:f}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:f}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function b12({entity:A,config:Q}){let w=EF.parse(A),B=r7.parsePostFrontmatter(w),$=r7.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:B.title,platform:B.platform,body:$,format:"text/markdown",status:B.status,...B.publishedAt&&{publishedAt:B.publishedAt},...B.platformPostId&&{platformPostId:B.platformPostId},...B.sourceEntityType&&{sourceLocalEntityType:B.sourceEntityType},...B.sourceEntityId&&{sourceLocalEntityId:B.sourceEntityId},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"social-post",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function Aa0(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:_6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:b12}}var V12={name:"@brains/social-media",version:"0.2.0-alpha.164",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 Qa0 extends sQ{entityType=r7.entityType;schema=EF;adapter=r7;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",V12,A,rs0)}createGenerationHandler(A){return new bj(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return W12()}getDataSources(){return[new VX0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),U12(A,this.providers,this.logger),G12(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)D12(A,this.logger),z12(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");q12(A,this.logger),K12(A),this.unregisterAtprotoProjection=B8.getInstance().register(Aa0()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=es0(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function go(A={}){return new Qa0(A)}L0();var R3w=Z.enum(["draft","queued","published","failed"]),J12=Z.object({status:R3w.default("draft"),queueOrder:Z.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:Z.string().datetime().optional()});class wa0{name="internal";async publish(A,Q){return{id:"internal"}}}var yo={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},AY={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"},TF={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"},I12={REGISTER:"publish-assets:register"};L0();var h3w=Z.enum(["provider"]),F12=Z.object({executionMode:h3w.optional(),publishResultIdField:Z.string().min(1).optional(),publishTimestampField:Z.string().min(1).optional(),enabled:Z.boolean().optional()}).strict();var C3w=Z.object({skipIfDraftExists:Z.boolean().optional(),minSourceEntities:Z.number().optional(),maxUnpublishedDrafts:Z.number().optional(),sourceEntityType:Z.string().optional()}),k12=Z.object({entitySchedules:Z.record(Z.string(),Z.string()).optional(),generationSchedules:Z.record(Z.string(),Z.string()).optional(),generationConditions:Z.record(Z.string(),C3w).optional()});class $3{static instance=null;queues=new Map;static getInstance(){return $3.instance??=new $3,$3.instance}static resetInstance(){$3.instance=null}static createFresh(){return new $3}constructor(){}async add(A,Q,w=yo){let B=this.getOrCreateQueue(A),$=B.find((X)=>X.entityId===Q);if($)return{position:$.position};let f=B.length+1,Y={entityId:Q,entityType:A,position:f,queuedAt:new Date().toISOString(),authContext:{...w}};return B.push(Y),{position:f}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let B=w.findIndex(($)=>$.entityId===Q);if(B===-1)return;w.splice(B,1),this.recalculatePositions(w)}async reorder(A,Q,w){let B=this.queues.get(A);if(!B)return;let $=B.findIndex((X)=>X.entityId===Q);if($===-1)return;let[f]=B.splice($,1);if(!f)return;let Y=Math.max(0,Math.min(w-1,B.length));B.splice(Y,0,f),this.recalculatePositions(B)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let w=Q[0];if(!w)continue;if(!A||w.queuedAt<A.queuedAt)A=w}return A}async popNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;let w=Q.shift()??null;if(w)this.recalculatePositions(Q);return w}getRegisteredTypes(){return Array.from(this.queues.keys())}async getQueuedEntityTypes(){let A=[];for(let[Q,w]of this.queues.entries())if(w.length>0)A.push(Q);return A}getOrCreateQueue(A){let Q=this.queues.get(A);if(!Q)Q=[],this.queues.set(A,Q);return Q}recalculatePositions(A){A.forEach((Q,w)=>{Q.position=w+1})}}class f3{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new wa0;static getInstance(){return f3.instance??=new f3,f3.instance}static resetInstance(){f3.instance=null}static createFresh(){return new f3}constructor(){}register(A,Q,w){let B=this.providers.get(A);if(B&&B.name!=="internal"&&Q.name==="internal")return;if(this.providers.set(A,Q),this.executionModes.set(A,w?.executionMode??"provider"),w?.publishResultIdField)this.publishResultIdFields.set(A,w.publishResultIdField);else this.publishResultIdFields.delete(A);if(w?.publishTimestampField)this.publishTimestampFields.set(A,w.publishTimestampField);else this.publishTimestampFields.delete(A)}get(A){return this.providers.get(A)??this.defaultProvider}getExecutionMode(A){return this.executionModes.get(A)??"provider"}getPublishResultIdField(A){return this.publishResultIdFields.get(A)}getPublishTimestampField(A){return this.publishTimestampFields.get(A)}has(A){return this.providers.has(A)}unregister(A){this.providers.delete(A),this.executionModes.delete(A),this.publishResultIdFields.delete(A),this.publishTimestampFields.delete(A)}getRegisteredTypes(){return Array.from(this.providers.keys())}}async function L12(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await g3w(A,Q)}async function g3w(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let B={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:AY.FAILED,payload:B,sender:"publish-service",broadcast:!0});Q.onFailed?.(B);return}Ba0(A.entityType,A.entityId,w.result,Q)}catch(w){let B=SA(w);Q.retryTracker.recordFailure(A.entityId,B);let $=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:B,retryCount:$?.retryCount??1,willRetry:!1})}}function Ba0(A,Q,w,B){if(B.retryTracker.clearRetries(Q),B.messageBus)B.messageBus.send({type:AY.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});B.onPublish?.({entityType:A,entityId:Q,result:w})}function _12(A,Q,w,B){B.retryTracker.recordFailure(Q,w);let $=B.retryTracker.getRetryInfo(Q),f={entityType:A,entityId:Q,error:w,retryCount:$?.retryCount??1,willRetry:!1};if(B.messageBus)B.messageBus.send({type:AY.FAILED,payload:f,sender:"publish-service",broadcast:!0});B.onFailed?.(f)}async function N12(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let $=await Q.onCheckGenerationConditions(A,w);if(!$.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:TF.SKIPPED,payload:{entityType:A,reason:$.reason??"Conditions not met"},sender:"content-pipeline"});return}}let B={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:TF.EXECUTE,payload:B,sender:"content-pipeline"});Q.onGenerate?.(B)}function P12(A,Q,w){if(w)w.send({type:TF.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function j12(A,Q,w){if(w)w.send({type:TF.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var y3w=1000;class $a0{deps;publishJobs=new Map;immediateIntervalJob=null;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.entitySchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.processEntityType(A));this.publishJobs.set(A,w)}this.immediateIntervalJob=this.deps.config.backend.scheduleInterval(y3w,()=>this.processUnscheduledTypes())}stop(){if(E3w(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await L12(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function E3w(A){for(let Q of A.values())Q.stop();A.clear()}class fa0{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){T3w(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await N12(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function T3w(A){for(let Q of A.values())Q.stop();A.clear()}class RU{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return RU.instance??=new RU(A),RU.instance}static resetInstance(){if(RU.instance)RU.instance.stop();RU.instance=null}static createFresh(A){return new RU(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new $a0({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new fa0({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){Ba0(A,Q,w,this.publishDeps)}failPublish(A,Q,w){_12(A,Q,w,this.publishDeps)}completeGeneration(A,Q){P12(A,Q,this.config.messageBus)}failGeneration(A,Q){j12(A,Q,this.config.messageBus)}get entitySchedules(){return this.config.entitySchedules}get generationSchedules(){return this.config.generationSchedules}get publishDeps(){return{retryTracker:this.config.retryTracker,messageBus:this.config.messageBus,publishExecutor:this.config.publishExecutor,onPublish:this.config.onPublish,onFailed:this.config.onFailed}}get generationDeps(){return{logger:this.config.logger,messageBus:this.config.messageBus,generationConditions:this.config.generationConditions,onCheckGenerationConditions:this.config.onCheckGenerationConditions,onGenerate:this.config.onGenerate}}validateCronExpressions(){for(let[A,Q]of Object.entries(this.entitySchedules))this.validateCronExpression(A,Q,"publish");for(let[A,Q]of Object.entries(this.generationSchedules))this.validateCronExpression(A,Q,"generation")}validateCronExpression(A,Q,w){try{this.config.backend.validateCron(Q)}catch(B){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${SA(B)}`,{cause:B})}}}class Y3{static instance=null;retries=new Map;static getInstance(){return Y3.instance??=new Y3,Y3.instance}static resetInstance(){Y3.instance=null}static createFresh(){return new Y3}constructor(){}recordFailure(A,Q){let B=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:B,lastError:Q})}clearRetries(A){this.retries.delete(A)}getRetryInfo(A){let Q=this.retries.get(A);if(!Q)return null;return{entityId:Q.entityId,retryCount:Q.retryCount,lastError:Q.lastError}}}function Eo(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function Ya0(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function S3w(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let B=A.substring(9);return B.includes("Z")||B.includes("+")||B.includes("-")?Za0(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):Za0(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function M12(A,Q,w){return v12(S3w(A,Q),w)}function v12(A,Q){let w=new Date(Eo(A)),B=To(w,A.tz),$=Eo(A),f=Eo(B),Y=$-f,X=new Date(w.getTime()+Y),H=To(X,A.tz);if(Ya0(H,A)){let U=new Date(X.getTime()-3600000),G=To(U,A.tz);return Ya0(G,A)?U:X}let W=new Date(X.getTime()+Eo(A)-Eo(H)),K=To(W,A.tz);if(Ya0(K,A))return W;if(Q)throw Error("Invalid date passed to fromTZ()");return X.getTime()>W.getTime()?X:W}function To(A,Q){let w,B;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),B=w.formatToParts(A)}catch(f){let Y=f instanceof Error?f.message:String(f);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let $={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let f of B)(f.type==="year"||f.type==="month"||f.type==="day"||f.type==="hour"||f.type==="minute"||f.type==="second")&&($[f.type]=parseInt(f.value,10));if(isNaN($.year)||isNaN($.month)||isNaN($.day)||isNaN($.hour)||isNaN($.minute)||isNaN($.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify($)}`);return $.hour===24&&($.hour=0),{y:$.year,m:$.month,d:$.day,h:$.hour,i:$.minute,s:$.second,tz:Q}}function Za0(A,Q,w,B,$,f,Y){return{y:A,m:Q,d:w,h:B,i:$,s:f,tz:Y}}var R12=[1,2,4,8,16],x12=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let B;switch(this.mode){case"5-part":B=5;break;case"6-part":B=6;break;case"7-part":B=7;break;case"5-or-6-parts":B=[5,6];break;case"6-or-7-parts":B=[6,7];break;default:B=0}if(!(Array.isArray(B)?B.includes(Q):Q===B)){let $=Array.isArray(B)?B.join(" or "):B.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${$} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,B){let $=this[A],f=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!f&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return $.fill(B);let X=Q.split(",");if(X.length>1)for(let H=0;H<X.length;H++)this.partToArray(A,X[H],w,B);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,B):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,B):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,B):Q!==""&&this.handleNumber(Q,A,w,B)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,B){let $=this.extractNth(A,Q),f=A.toUpperCase().includes("W");if(Q!=="day"&&f)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");f&&(Q="nearestWeekdays");let Y=parseInt($[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,$[1]||B)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,B,$){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+$+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[B].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[B].length+")")}}handleRangeWithStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let $=this.extractNth(A,Q),f=$[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(f===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,X,H]=f,W=parseInt(Y,10)+w,K=parseInt(X,10)+w,U=parseInt(H,10);this.validateNotNaN(W,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(W,K,U,Q,A);for(let G=W;G<=K;G+=U)this.setPart(Q,G,$[1]||B)}extractNth(A,Q){let w=A,B;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");B=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");B="L",w=w.slice(0,-1)}return[w,B]}handleRange(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let $=this.extractNth(A,Q),f=$[0].split("-");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(f[0],10)+w,X=parseInt(f[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(X,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,X,void 0,Q,A);for(let H=Y;H<=X;H++)this.setPart(Q,H,$[1]||B)}handleStepping(A,Q,w,B){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let $=this.extractNth(A,Q),f=$[0].split("/");if(f.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)f[0]===""&&(f[0]="*");else{if(f[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(f[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;f[0]!=="*"&&(Y=parseInt(f[0],10)+w);let X=parseInt(f[1],10);this.validateNotNaN(X,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,X,Q,A);for(let H=Y;H<this[Q].length;H+=X)this.setPart(Q,H,$[1]||B)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|R12[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},Xa0=[31,28,31,30,31,30,31,31,30,31,30,31],z$=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],o7=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?Xa0[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let B=this.getLastDayOfMonth(Q,w),$=new Date(Date.UTC(Q,w,B)).getUTCDay();return $===0?B-2:$===6?B-1:B}getNearestWeekday(Q,w,B){let $=this.getLastDayOfMonth(Q,w);if(B>$)return-1;let f=new Date(Date.UTC(Q,w,B)).getUTCDay();return f===0?B===$?B-2:B+1:f===6?B===1?B+2:B-1:B}isNthWeekdayOfMonth(Q,w,B,$){let f=new Date(Date.UTC(Q,w,B)).getUTCDay(),Y=0;for(let X=1;X<=B;X++)new Date(Date.UTC(Q,w,X)).getUTCDay()===f&&Y++;if($&63&&R12[Y-1]&$)return!0;if($&32){let X=this.getLastDayOfMonth(Q,w);for(let H=B+1;H<=X;H++)if(new Date(Date.UTC(Q,w,H)).getUTCDay()===f)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=To(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let B=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${B}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>Xa0[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=M12(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(M12(Q,this.tz))}findNext(Q,w,B,$){return this._findMatch(Q,w,B,$,1)}_findMatch(Q,w,B,$,f){let Y=this[w],X;B.lastDayOfMonth&&(X=this.getLastDayOfMonth(this.year,this.month));let H=!B.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,W=this[w]+$,K=f===1?(U)=>U<B[w].length:(U)=>U>=0;for(let U=W;K(U);U+=f){let G=B[w][U];if(w==="day"&&!G){for(let q=0;q<B.nearestWeekdays.length;q++)if(B.nearestWeekdays[q]){let b=this.getNearestWeekday(this.year,this.month,q-$);if(b===-1)continue;if(b===U-$){G=1;break}}}if(w==="day"&&B.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-$===q&&(G=1)}if(w==="day"&&B.lastDayOfMonth&&U-$==X&&(G=1),w==="day"&&!B.starDOW){let q=B.dayOfWeek[(H+(U-$-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-$,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);B.useAndLogic?G=G&&q:!Q.domAndDow&&!B.starDOM?G=G||q:G=G&&q}if(G)return this[w]=U-$,Y!==this[w]?2:1}return 3}recurse(Q,w,B){if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let f=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){f=Y;break}if(f===-1)return null;this.year=f,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let $=this.findNext(w,z$[B][0],Q,z$[B][2]);if($>1){let f=B+1;for(;f<z$.length;)this[z$[f][0]]=-z$[f][2],f++;if($===3){if(this[z$[B][1]]++,this[z$[B][0]]=-z$[B][2],this.apply(),B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,B-1)}return B+=1,B>=z$.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,B)}increment(Q,w,B){return this.second+=w.interval!==void 0&&w.interval>1&&B?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,B,$=0){if($>1e4)return null;if(B===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let X=this.year-1;X>=0;X--)if(Q.year[X]===1){Y=X;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let f=this.findPrevious(w,z$[B][0],Q,z$[B][2]);if(f>1){let Y=B+1;for(;Y<z$.length;){let X=z$[Y][0],H=z$[Y][2],W=this.getMaxPatternValue(X,Q,H);this[X]=W,Y++}if(f===3){if(this[z$[B][1]]--,B===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if(B===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let G=U!==1?Xa0[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>G&&(this.day=G)}this.apply();let X=z$[B][0],H=z$[B][2],W=this.getMaxPatternValue(X,Q,H);if(X==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[X]=Math.min(W,K)}else this[X]=W;if(this.apply(),B===0){let K=z$[1][2],U=this.getMaxPatternValue("day",Q,K),G=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,G);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,z$[2][2]),this.minute=this.getMaxPatternValue("minute",Q,z$[3][2]),this.second=this.getMaxPatternValue("second",Q,z$[4][2]))}if(B===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,$+1)}else if(this.apply())return this.recurseBackward(Q,w,B-1,$+1)}return B+=1,B>=z$.length?this:this.year<0?null:this.recurseBackward(Q,w,B,$+1)}getMaxPatternValue(Q,w,B){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let $=w[Q].length-1;$>=0;$--)if(w[Q][$])return $-B;return w[Q].length-1-B}findPrevious(Q,w,B,$){return this._findMatch(Q,w,B,$,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):v12(Za0(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let B=0;B<z$.length;B++){let $=z$[B][0],f=z$[B][2],Y=this[$];if(Y+f<0||Y+f>=Q[$].length)return!1;let X=Q[$][Y+f];if($==="day"){if(!X){for(let H=0;H<Q.nearestWeekdays.length;H++)if(Q.nearestWeekdays[H]){let W=this.getNearestWeekday(this.year,this.month,H-f);if(W!==-1&&W===Y){X=1;break}}}if(Q.lastWeekday){let H=this.getLastWeekday(this.year,this.month);Y===H&&(X=1)}if(Q.lastDayOfMonth){let H=this.getLastDayOfMonth(this.year,this.month);Y===H&&(X=1)}if(!Q.starDOW){let H=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),W=Q.dayOfWeek[(H+(Y-1))%7];W&&W&63&&(W=this.isNthWeekdayOfMonth(this.year,this.month,Y,W)?1:0),Q.useAndLogic?X=X&&W:!w.domAndDow&&!Q.starDOM?X=X||W:X=X&&W}}if(!X)return!1}return!0}};function m3w(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new o7(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new o7(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function So(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function u3w(A){return So(A)}function c3w(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var O12=30000,kX0=[],Ha0=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let B,$;if(So(Q))$=Q;else if(typeof Q=="object")B=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(So(w))$=w;else if(typeof w=="object")B=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=B?.name,this.options=m3w(B),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:B?B.maxRuns:void 0,paused:B?B.paused:!1,pattern:new x12("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new o7(A,this.getTz()):this._states.pattern=new x12(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(kX0.find((f)=>f.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");kX0.push(this)}return $!==void 0&&u3w($)&&(this.fn=$,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let B=[],$=Q?new o7(Q,this.getTz()):null,f=w==="next"?this._next:this._previous;for(;A--;){let Y=f.call(this,$);if(!Y)break;let X=Y.getDate(!1);B.push(this.applyDayOffset(X)),$=Y}return B}match(A){if(this._states.once){let w=new o7(A,this.getTz());w.ms=0;let B=new o7(this._states.once,this.getTz());return B.ms=0,w.getTime()===B.getTime()}let Q=new o7(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,B=!this._states.kill;return Q&&w&&B&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof o7||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new o7(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=kX0.indexOf(this);A>=0&&kX0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>O12&&(Q=O12),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&c3w(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new o7(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(So(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new o7(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),B=this._states.blocking&&this.options.protect;w&&!B?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&B&&So(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new o7(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let B=this._states.once||new o7(A,this.getTz());return!w&&B!==this._states.once&&(B=B.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||B===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&B.getTime()>=this.options.stopAt.getTime()?null:B}_previous(A){let Q=new o7(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new o7(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new o7(void 0,this.getTz()),B=A;if(this.options.startAt.getTime()<=w.getTime()){B=this.options.startAt;let $=B.getTime()+this.options.interval*1000;for(;$<=w.getTime();)B=new o7(B,this.getTz()).increment(this._states.pattern,this.options,!0),$=B.getTime()+this.options.interval*1000;Q=!0}return B===null&&(B=void 0),[B,Q]}};class LX0{scheduleCron(A,Q){let w=new Ha0(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new Ha0(A).stop()}}L0();var h12=Z.union([Z.string().min(1),Z.object({location:Z.enum(["metadata","frontmatter"]),field:Z.string().min(1)})]),_X0=Z.object({entityType:Z.string().min(1),attachmentType:Z.string().min(1),mediaEntityType:Z.enum(["image","document"]),targetEntityField:h12.optional(),requiredWhen:Z.object({status:Z.string().min(1).optional(),visibility:Z.string().min(1).optional()}).optional(),autoGenerate:Z.boolean().optional(),requiredForPublish:Z.boolean().optional(),jobType:Z.string().min(1).optional()});function Wa0(A){return`${A.entityType}:${A.attachmentType}`}class X3{static instance=null;definitions=new Map;static getInstance(){return X3.instance??=new X3,X3.instance}static resetInstance(){X3.instance=null}static createFresh(){return new X3}constructor(){}register(A){let Q=_X0.parse(A),w=Wa0(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(Wa0({entityType:A,attachmentType:Q}))}list(A){let Q=Array.from(this.definitions.values());return A?Q.filter((w)=>w.entityType===A):Q}has(A,Q){return this.get(A,Q)!==void 0}unregister(A,Q){this.definitions.delete(Wa0({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}l9();D2();class NX0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter(($)=>$.autoGenerate===!0).filter(($)=>!Q.attachmentType||$.attachmentType===Q.attachmentType),B={checked:w.length,enqueued:0,skipped:0};for(let $ of w)if(await this.ensureDefinition(A,$))B.enqueued+=1;else B.skipped+=1;return B}async ensureDefinition(A,Q){if(!this.matchesPolicy(A,Q))return!1;if(this.hasTargetField(A,Q.targetEntityField))return!1;if(!this.deps.context.attachments.hasProvider(A.entityType,Q.attachmentType))return!1;let w=this.resolveJobType(Q);if(!w)return!1;let B=this.getPredictedMediaId(A,Q),$=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:B,dedupKey:$,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:$}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType:w}),!0}matchesPolicy(A,Q){let{requiredWhen:w}=Q;if(!w)return!0;if(w.status&&A.metadata.status!==w.status)return!1;if(w.visibility&&A.visibility!==w.visibility)return!1;return!0}hasTargetField(A,Q){if(!Q)return!1;if(typeof Q==="string")return Ka0(A.metadata[Q]);if(Q.location==="metadata")return Ka0(A.metadata[Q.field]);let{frontmatter:w}=M6(A.content);return Ka0(w[Q.field])}resolveJobType(A){if(A.jobType)return A.jobType;if(A.mediaEntityType==="image")return"image:image-render-source";return}getPredictedMediaId(A,Q){let w=Q.attachmentType==="og-image"?"og":Q.attachmentType;return H1(`${w}-${A.entityType}-${A.id}`)}getDeduplicationKey(A,Q){return`publish-asset:${Q.attachmentType}:${A.entityType}:${A.id}`}getTargetImageFieldData(A){let Q=typeof A==="string"?A:A?.field;if(Q==="coverImageId"||Q==="ogImageId")return{targetImageField:Q};return{}}}function Ka0(A){return typeof A==="string"?A.length>0:A!==void 0}wA();L0();var l3w=Z.object({id:Z.string().min(1)});async function g12(A,Q){let{bodyContent:w,coverImageId:B,documents:$,sourceEntityType:f,sourceEntityId:Y}=p3w(Q.content),X=B?await n3w(A,B):void 0,H;if($&&$.length>0){let K=await r3w(A,$);if(K.length>0)H=K}H??=await d3w(A,f,Y);let W={bodyContent:w};if(X)W.imageData=X;if(H&&H.length>0)W.documentData=H;return W}function p3w(A){try{let Q=r2(A,Z.record(Z.string(),Z.unknown())),w=Q.metadata.coverImageId,B=typeof w==="string"?w:void 0,$=i3w(Q.metadata.documents),f=C12(Q.metadata.sourceEntityType),Y=C12(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...B&&{coverImageId:B},...$.length>0&&{documents:$},...f&&{sourceEntityType:f},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function i3w(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=l3w.safeParse(Q);return w.success?[w.data]:[]})}function C12(A){return typeof A==="string"&&A.length>0?A:void 0}async function d3w(A,Q,w){if(!Q||!w)return;let B=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return B?[B]:void 0}async function n3w(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let B=y12(w.content);if(!B?.mimeType.startsWith("image/"))return;return{data:B.data,mimeType:B.mimeType}}async function r3w(A,Q){return(await Promise.all(Q.map((B)=>o3w(A,B)))).filter((B)=>B!==void 0)}async function o3w(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let B=y12(w.content);if(B?.mimeType!=="application/pdf")return;return{type:"document",data:B.data,mimeType:"application/pdf",filename:s3w(w,Q.id)}}function y12(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function s3w(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}l9();var a3w=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function Ua0(A,Q,w,B={}){let $=B.publishTimestampField??"publishedAt",f=Q.metadata[$],Y=B.publishedAt??(typeof f==="string"?f:void 0)??new Date().toISOString(),X={...Q.metadata,status:"published",[$]:Y,platformId:w.id,...t3w(w.id,B.publishResultIdField)},H={...Q,content:E12(Q.content,Y,w.id,B.publishResultIdField,$),metadata:X};return await A.entityService.updateEntity({entity:H}),H}function E12(A,Q,w,B,$="publishedAt"){if(!a3w.test(A))return A;let f=b4(b4(A,"status","published"),$,Q);if(!w||!B)return f;return b4(f,B,w)}function t3w(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class yy{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:B}=A;if(!w&&!B)return{error:"Either 'id' or 'slug' must be provided"};let $=await this.findPublishableEntity(Q,w,B);if(!$)return{error:`Entity not found: ${Q}:${w??B}`};if($.visibility!=="public")return{error:`Cannot publish ${Q}:${$.id} to a public provider because visibility is ${$.visibility}`};if($.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:$}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:B}=A,$=this.deps.providerRegistry.get(B),{bodyContent:f,imageData:Y,documentData:X}=await g12(this.deps.context,w),H=await $.publish(f,w.metadata,Y,X),W=this.deps.providerRegistry.getPublishResultIdField(B),K=this.deps.providerRegistry.getPublishTimestampField(B),U=await Ua0(this.deps.context,w,H,{...W?{publishResultIdField:W}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,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,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}wA();L0();var Ga0=Z.object({action:Z.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:Z.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:Z.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:Z.number().optional().describe("New position for reorder action (1-based)")}),Da0=Z.object({position:Z.number(),entityType:Z.string(),entityId:Z.string(),queuedAt:Z.string()}),e3w=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({queue:Z.array(Da0).optional(),entityType:Z.string().optional(),entityId:Z.string().optional(),position:Z.number().optional()}).optional()}),Azw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),za0=Z.union([e3w,Azw]);function PX0(A,Q,w){return{...x6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",Ga0,async($,f)=>{let{action:Y,entityType:X,entityId:H,position:W}=$;switch(Y){case"list":return Qzw(w,X);case"add":return wzw(A,w,X,H,f);case"remove":return Bzw(A,w,X,H,f);case"reorder":return $zw(A,w,X,H,W,f);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:za0}}async function Qzw(A,Q){let w=[];if(Q)w=await A.list(Q);else{let $=A.getRegisteredTypes();for(let f of $){let Y=await A.list(f);w.push(...Y)}w.sort((f,Y)=>new Date(f.queuedAt).getTime()-new Date(Y.queuedAt).getTime())}if(w.length===0)return{success:!0,data:{queue:[]},message:"No items in queue"};return{success:!0,data:{queue:w.map(($,f)=>({position:f+1,entityType:$.entityType,entityId:$.entityId,queuedAt:$.queuedAt}))},message:`${w.length} items in queue`}}async function wzw(A,Q,w,B,$){let f=qa0("add",w,B);if(!f.success)return f.error;A.permissions.assertEntityActionAllowed(f.entityType,"publish",$??{});let Y=await Q.add(f.entityType,f.entityId,{...$,authorization:"user"});return{success:!0,data:{entityType:f.entityType,entityId:f.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function Bzw(A,Q,w,B,$){let f=qa0("remove",w,B);if(!f.success)return f.error;return A.permissions.assertEntityActionAllowed(f.entityType,"update",$??{}),await Q.remove(f.entityType,f.entityId),{success:!0,data:{entityType:f.entityType,entityId:f.entityId},message:"Removed from queue"}}async function $zw(A,Q,w,B,$,f){let Y=qa0("reorder",w,B);if(!Y.success)return Y.error;let X=fzw($);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",f??{}),await Q.reorder(Y.entityType,Y.entityId,X.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:X.position},message:`Moved to position ${X.position}`}}function qa0(A,Q,w){if(!Q)return{success:!1,error:{success:!1,error:`entityType is required for ${A} action`}};if(!w)return{success:!1,error:{success:!1,error:`entityId is required for ${A} action`}};return{success:!0,entityType:Q,entityId:w}}function fzw(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}}L0();import{createHash as Yzw}from"crypto";var ba0=Z.object({entityType:Z.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:Z.string().optional().describe("Entity ID to publish"),slug:Z.string().optional().describe("Entity slug to publish"),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),Xzw=Z.object({entityType:Z.string(),id:Z.string().optional(),slug:Z.string().optional(),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),contentHash:Z.string().optional(),expiresAt:Z.string().datetime().optional()}),Zzw=Z.object({success:Z.literal(!0),message:Z.string().optional(),data:Z.object({entityType:Z.string().optional(),entityId:Z.string().optional(),platformId:Z.string().optional(),url:Z.string().optional()}).optional()}),Hzw=Z.object({success:Z.literal(!1),error:Z.string(),code:Z.string().optional()}),Wzw=Z.object({success:Z.literal(!1).optional(),error:Z.string().optional(),needsConfirmation:Z.literal(!0),toolName:Z.string(),summary:Z.string(),preview:Z.string().optional(),args:Z.unknown()}),Va0=Z.union([Zzw,Hzw,Wzw]),Kzw=900000;function jX0(A,Q,w,B){let $=B??new yy({context:A,providerRegistry:w}),f=`${Q}_publish`;return{name:f,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). 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:ba0.shape,outputSchema:Va0,visibility:"anchor",sideEffects:"external",handler:async(Y,X)=>{let H=Xzw.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join(", ")}`};let W=H.data,{entityType:K,id:U,slug:G}=W;try{A.permissions.assertEntityActionAllowed(K,"publish",X)}catch(J){return{success:!1,error:J instanceof Error?J.message:String(J)}}let q=await $.resolveCandidate({entityType:K,id:U,slug:G});if("error"in q)return{success:!1,error:q.error};let{entity:b}=q;if(W.confirmed){let J=Gzw(f,W,b);if(J!==null)return J;let V;try{V=await $.publish({entityType:K,id:b.id})}catch(L){return{success:!1,error:L instanceof Error?L.message:String(L)}}if("error"in V)return{success:!1,error:V.error};let{entity:k,result:N}=V;return{success:!0,data:{entityType:K,entityId:k.id,platformId:N.id,url:N.url},message:`Published ${K}:${k.id}`}}return Uzw(f,W,b)}}}function Uzw(A,Q,w){let B=new Date(Date.now()+Kzw).toISOString(),$=T12(A,w,B),f=Dzw(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${f}"?`,preview:`This will publish ${w.entityType}:${w.id} to its registered public publish provider.`,args:{...Q,id:w.id,slug:void 0,confirmed:!0,confirmationToken:$,contentHash:w.contentHash,expiresAt:B}}}function Gzw(A,Q,w){let{confirmationToken:B,contentHash:$,expiresAt:f}=Q;if(!B||!f)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(f);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($&&$!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if(B!==T12(A,w,f))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function T12(A,Q,w){return Yzw("sha256").update(A).update("\x00").update(Q.entityType).update("\x00").update(Q.id).update("\x00").update(Q.contentHash).update("\x00").update(w).digest("hex")}function Dzw(A){let Q=A.metadata.title;if(typeof Q==="string"&&Q.length>0)return Q;let w=A.metadata.subject;if(typeof w==="string"&&w.length>0)return w;let B=A.metadata.slug;if(typeof B==="string"&&B.length>0)return B;return A.id}wA();L0();var Ja0=Z.object({entityType:Z.string().min(1).describe("Entity type to reconcile"),status:Z.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:Z.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),Ia0=Z.object({success:Z.literal(!0),data:Z.object({entityType:Z.string(),assetType:Z.string().optional(),checkedEntities:Z.number(),checkedAssets:Z.number(),enqueued:Z.number(),skipped:Z.number()}),message:Z.string().optional()});function MX0(A,Q,w,B){return{...x6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",Ja0,async(f,Y)=>{if(A.permissions.assertEntityActionAllowed(f.entityType,"publish",Y),w.list(f.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!f.assetType||G.attachmentType===f.assetType).length===0)return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${f.entityType}`};let H=await A.entityService.listEntities({entityType:f.entityType,options:{...f.status&&{filter:{metadata:{status:f.status}}}}}),W=0,K=0,U=0;for(let G of H){let q=await B.ensureForEntity(G,{...f.assetType&&{attachmentType:f.assetType}});W+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:f.entityType,...f.assetType&&{assetType:f.assetType},checkedEntities:H.length,checkedAssets:W,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:Ia0}}wA();function S12(A,Q){zzw(A,Q),qzw(A,Q),bzw(A,Q),Vzw(A,Q)}function zzw(A,Q){A.messaging.subscribe(AY.REGISTER,async(w)=>Jzw(Q,w.payload)),A.messaging.subscribe(AY.QUEUE,async(w)=>Lzw(A,Q,w.payload)),A.messaging.subscribe(AY.DIRECT,async(w)=>_zw(A,Q,w.payload)),A.messaging.subscribe(AY.REMOVE,async(w)=>Nzw(Q,w.payload)),A.messaging.subscribe(AY.REORDER,async(w)=>Pzw(Q,w.payload)),A.messaging.subscribe(AY.LIST,async(w)=>jzw(A,Q,w.payload)),A.messaging.subscribe(AY.REPORT_SUCCESS,async(w)=>Mzw(Q,w.payload)),A.messaging.subscribe(AY.REPORT_FAILURE,async(w)=>xzw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function qzw(A,Q){A.messaging.subscribe(TF.REPORT_SUCCESS,async(w)=>Ozw(Q,w.payload)),A.messaging.subscribe(TF.REPORT_FAILURE,async(w)=>vzw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function bzw(A,Q){A.messaging.subscribe(I12.REGISTER,async(w)=>Izw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function Vzw(A,Q){let w=async(B)=>Fzw(A,Q,B.payload);A.messaging.subscribe("entity:created",w),A.messaging.subscribe("entity:updated",w),Q.logger.debug("Subscribed to entity change messages for publish assets")}async function Jzw(A,Q){let{entityType:w,provider:B,config:$}=Q;try{let f=$?F12.safeParse($):void 0;if(f&&!f.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:f.error.message}),{success:!1};if(B)A.providerRegistry.register(w,B,f?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:B.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(f){let Y=SA(f);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function Izw(A,Q){let w=_X0.safeParse(Q);if(!w.success)return A.logger.warn("Invalid publish asset registration",{error:w.error.message}),{success:!1};return A.publishAssetRegistry.register(w.data),A.logger.info("Registered publish asset",{entityType:w.data.entityType,attachmentType:w.data.attachmentType,mediaEntityType:w.data.mediaEntityType}),{success:!0}}async function Fzw(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let B=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!kzw(B))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity(B),{success:!0}}catch(B){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:SA(B)}),{success:!1}}}function kzw(A){if(!A)return!1;let Q=J12.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Lzw(A,Q,w){let{entityType:B,entityId:$}=w;try{let f=w.authContext??yo;A.permissions.assertEntityActionAllowed(B,"publish",f);let Y=await Q.queueManager.add(B,$,f);return await A.messaging.send({type:AY.QUEUED,payload:{entityType:B,entityId:$,position:Y.position}}),Q.logger.debug(`Entity queued: ${$}`,{entityType:B,position:Y.position}),{success:!0}}catch(f){let Y=SA(f);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function _zw(A,Q,w){let{entityType:B,entityId:$}=w,f=w.authContext??yo;try{if(A.permissions.assertEntityActionAllowed(B,"publish",f),!Q.providerRegistry.has(B))return Q.scheduler.failPublish(B,$,`No publish provider registered for ${B}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:B,id:$});if("error"in Y)return Q.scheduler.failPublish(B,$,Y.error),{success:!1};return Q.scheduler.completePublish(B,$,Y.result),Q.logger.debug(`Direct publish completed: ${$}`,{entityType:B}),{success:!0}}catch(Y){let X=SA(Y);return Q.logger.error(`Failed direct publish request: ${X}`),{success:!1}}}async function Nzw(A,Q){let{entityType:w,entityId:B}=Q;try{return await A.queueManager.remove(w,B),A.logger.debug(`Entity removed from queue: ${B}`,{entityType:w}),{success:!0}}catch($){let f=SA($);return A.logger.error(`Failed to remove entity: ${f}`),{success:!1}}}async function Pzw(A,Q){let{entityType:w,entityId:B,position:$}=Q;try{return await A.queueManager.reorder(w,B,$),A.logger.debug(`Entity reordered: ${B}`,{entityType:w,newPosition:$}),{success:!0}}catch(f){let Y=SA(f);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function jzw(A,Q,w){let{entityType:B}=w;try{let $=await Q.queueManager.list(B);return await A.messaging.send({type:AY.LIST_RESPONSE,payload:{entityType:B,queue:$.map((f)=>({entityId:f.entityId,position:f.position,queuedAt:f.queuedAt}))}}),{success:!0}}catch($){let f=SA($);return Q.logger.error(`Failed to list queue: ${f}`),{success:!1}}}async function Mzw(A,Q){let{entityType:w,entityId:B,result:$}=Q;return A.scheduler.completePublish(w,B,$),A.logger.info(`Publish reported success: ${B}`,{entityType:w}),{success:!0}}async function xzw(A,Q){let{entityType:w,entityId:B,error:$}=Q;A.scheduler.failPublish(w,B,$);let f=A.retryTracker.getRetryInfo(B);return A.logger.info(`Publish reported failure: ${B}`,{entityType:w,error:$,retryCount:f?.retryCount}),{success:!0}}async function Ozw(A,Q){let{entityType:w,entityId:B}=Q;return A.scheduler.completeGeneration(w,B),A.logger.info("Generation completed",{entityType:w,entityId:B}),{success:!0}}async function vzw(A,Q){let{entityType:w,error:B}=Q;return A.scheduler.failGeneration(w,B),A.logger.warn("Generation failed",{entityType:w,error:B}),{success:!0}}async function m12(A,Q,w,B){try{if(B.skipIfDraftExists!==!1){if((await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:1}})).length>0)return{shouldGenerate:!1,reason:"Draft already exists"}}if(B.maxUnpublishedDrafts!==void 0){let $=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:B.maxUnpublishedDrafts+1}});if($.length>=B.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${$.length}/${B.maxUnpublishedDrafts})`}}if(B.minSourceEntities!==void 0&&B.sourceEntityType){let $=await A.listEntities({entityType:B.sourceEntityType,options:{publishedOnly:!0,limit:B.minSourceEntities}});if($.length<B.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${$.length}/${B.minSourceEntities} ${B.sourceEntityType})`}}return{shouldGenerate:!0}}catch($){return Q.error("Failed to check generation conditions",{entityType:w,error:SA($)}),{shouldGenerate:!1,reason:`Condition check failed: ${SA($)}`}}}function u12(A){let{context:Q,config:w,queueManager:B,providerRegistry:$,retryTracker:f,publishExecutor:Y,logger:X}=A,H=Rzw(Q);return RU.createFresh({queueManager:B,providerRegistry:$,retryTracker:f,logger:X,backend:new LX0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(W,K)=>m12(Q.entityService,X,W,K)})}function Rzw(A){return{send:async($)=>{return A.messaging.send({type:$.type,payload:$.payload,...$.target!==void 0?{target:$.target}:{},...$.metadata!==void 0?{metadata:$.metadata}:{},...$.broadcast!==void 0?{broadcast:$.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}async function c12(A,Q,w){let B=A.getEntityTypes();for(let f of B){let Y=await A.listEntities({entityType:f,options:{filter:{metadata:{status:"queued"}}}});for(let X of Y)await Q.add(X.entityType,X.id)}let $=0;for(let f of B){let Y=await Q.list(f);$+=Y.length}if($>0)w.info(`Rebuilt queue with ${$} queued entities`)}L0();var hzw=["draft","queued","published","failed"];async function l12(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>Tzw(A),digestProvider:gzw}})}var Czw=Z.object({summary:Z.object({draft:Z.number(),queued:Z.number(),published:Z.number(),failed:Z.number()}),generating:Z.array(Z.unknown())});function gzw(A){let{summary:Q,generating:w}=Czw.parse(A),B=Q.queued+w.length,$=B===0?"idle":`${Q.queued} queued \xB7 ${w.length} generating`,f=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`,Y=Q.draft+Q.failed;return{digest:[{label:"Pipeline",value:$,...B>0?{tone:"warn"}:{}},{label:"Awaiting review",value:f,...Y>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Y}}var yzw=Z.object({sourceEntityType:Z.string(),sourceEntityId:Z.string(),attachmentType:Z.string().optional()});async function Ezw(A){let Q=await A.jobs.getActiveJobs(),w=[];for(let B of Q){if(B.source!=="content-pipeline")continue;if(B.status!=="pending"&&B.status!=="processing")continue;let $;try{$=JSON.parse(B.data)}catch{continue}let f=yzw.safeParse($);if(!f.success)continue;w.push({id:B.id,label:f.data.attachmentType??B.type,target:`${f.data.sourceEntityType}/${f.data.sourceEntityId}`,status:B.status})}return w}async function Tzw(A){let Q=A.entityService.getEntityTypes(),w=[],B={draft:0,queued:0,published:0,failed:0};for(let $ of Q){let f=await A.entityService.listEntities({entityType:$});for(let Y of f){let X=Szw(Y.metadata.status);if(!X)continue;B[X]++,w.push({id:Y.id,title:mzw(Y.id,Y.metadata.title),type:$,status:X})}}return{summary:B,items:w,generating:await Ezw(A)}}function Szw(A){return hzw.find((Q)=>Q===A)}function mzw(A,Q){return typeof Q==="string"?Q:A}var p12={name:"@brains/content-pipeline",version:"0.2.0-alpha.164",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},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 Fa0 extends Aw{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",p12,A,k12)}async onRegister(A){this.pluginContext=A,this.queueManager=$3.createFresh(),this.providerRegistry=f3.createFresh(),this.retryTracker=Y3.createFresh(),this.publishAssetRegistry=X3.createFresh(),this.publishAssetPreflight=new NX0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new yy({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=u12({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),S12(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await c12(A.entityService,this.queueManager,this.logger),await l12(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[PX0(this.pluginContext,this.id,this.queueManager),jX0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),MX0(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}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),$3.resetInstance(),f3.resetInstance(),Y3.resetInstance(),X3.resetInstance()}}function ka0(A={}){return new Fa0(A)}wA();L0();var i12=Z.object({accountId:Z.string().describe("Cloudflare account ID"),apiToken:Z.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:Z.string().describe("Cloudflare Web Analytics site tag")}),La0=Z.object({cloudflare:i12.optional()});wA();L0();var czw=Z.object({date:Z.string().describe("Single date in YYYY-MM-DD format").optional(),days:Z.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:Z.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:Z.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:Z.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function lzw(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 d12(A,Q,w){let B=[];if(!w)return B;return B.push(x6(A,"query",`Query website analytics from Cloudflare.
|
|
7974
7974
|
|
|
7975
7975
|
Date range options (use only one):
|
|
7976
7976
|
- No params: yesterday only
|
|
@@ -8108,7 +8108,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,czw,
|
|
|
8108
8108
|
}
|
|
8109
8109
|
}
|
|
8110
8110
|
}
|
|
8111
|
-
`,{...this.baseVariables(A),limit:A.limit??20})).map((B)=>({country:B.dimensions.countryName,visits:B.sum.visits}))}}var Na0=7,pzw=10;function r12(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=Ww0(),w=qOA(Na0),B=av(w),$=av(Q);try{let[f,Y]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:pzw})]);return{days:Na0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:Y}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:Na0}}}}var o12={name:"@brains/analytics",version:"0.2.0-alpha.
|
|
8111
|
+
`,{...this.baseVariables(A),limit:A.limit??20})).map((B)=>({country:B.dimensions.countryName,visits:B.sum.visits}))}}var Na0=7,pzw=10;function r12(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=Ww0(),w=qOA(Na0),B=av(w),$=av(Q);try{let[f,Y]=await Promise.all([A.getWebsiteStats({startDate:B,endDate:$}),A.getTopPages({startDate:B,endDate:$,limit:pzw})]);return{days:Na0,startDate:B,endDate:$,pageviews:f.pageviews,visitors:f.visitors,topPages:Y}}catch(f){return{error:f instanceof Error?f.message:"Failed to fetch analytics",days:Na0}}}}var o12={name:"@brains/analytics",version:"0.2.0-alpha.164",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 s12 extends Aw{cloudflareClient;constructor(A={}){super("analytics",o12,A,La0)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new _a0(this.config.cloudflare):void 0,A.insights.register("traffic-overview",r12(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:n12(Q)}})}async getTools(){return d12(this.id,this.getContext(),this.cloudflareClient)}}function dzw(A={}){return new s12(A)}var xX0=dzw;wA();L0();wA();L0();import{join as Qqw}from"path";D2();var a12="note",nzw=new Set(["description","excerpt","summary","tagline","story"]);function rzw(A){if(A.endsWith("s"))return A;return wK(A)}function co(A){return A===a12}function t12(A,Q){let w=A===a12?"Note":FV(A),B=Q?.label??w;return{label:B,pluralLabel:Q?.pluralName??rzw(B)}}function mo(A){return typeof A==="object"&&A!==null}function Vj(A){if(!mo(A))return;let Q=A.def;return mo(Q)?Q:void 0}function e12(A){let Q=Vj(A)?.type;return typeof Q==="string"?Q:void 0}function ozw(A){return typeof A==="function"?A():A}function Pa0(A,Q=!1,w){let B=e12(A),$=Vj(A);if(B==="optional"||B==="nullable")return Pa0($?.innerType,!0,w);if(B==="default")return Pa0($?.innerType,!0,ozw($?.defaultValue));let f={inner:A,isOptional:Q};if(w!==void 0)f.defaultValue=w;return f}function szw(A){let Q=Vj(A)?.entries;if(!mo(Q))return;let w=Object.values(Q);return w.every((B)=>typeof B==="string")?w:void 0}function azw(A){let Q=Vj(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function tzw(A){let Q=Vj(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some((w)=>{return Vj(w)?.format==="datetime"})}function ezw(A){return A==="imageId"||A.endsWith("ImageId")}function Aqw(A){if(!mo(A))return;let Q=A.shape;return mo(Q)?Q:void 0}function uo(A,Q){let{inner:w,isOptional:B,defaultValue:$}=Pa0(Q),f=e12(w),Y=$??azw(w),X={name:A,label:FV(A),widget:"string",...B&&{required:!1},...Y!==void 0&&{default:Y}};switch(f){case"string":{if(ezw(A))return{...X,widget:"image"};if(tzw(w))return{...X,widget:"datetime"};if(nzw.has(A))return{...X,widget:"text"};return{...X,widget:"string"}}case"number":return{...X,widget:"number"};case"boolean":return{...X,widget:"boolean"};case"enum":{let H=szw(w);return{...X,widget:"select",...H?{options:H}:{}}}case"array":{let H=Vj(w)?.element,W=uo("item",H);if(W.widget==="object"&&W.fields)return{...X,widget:"list",fields:W.fields};return{...X,widget:"list",field:{name:A,label:FV(A),widget:W.widget}}}case"object":{let H=Object.entries(Aqw(w)??{}).map(([W,K])=>uo(W,K));return{...X,widget:"object",fields:H}}case"literal":return{...X,widget:"string"};default:return{...X,widget:"string"}}}function A22(A){return`<!doctype html>
|
|
8112
8112
|
<html lang="en" data-climate="paper">
|
|
8113
8113
|
<head>
|
|
8114
8114
|
<meta charset="utf-8" />
|
|
@@ -8166,7 +8166,7 @@ ${SC}
|
|
|
8166
8166
|
</html>`}var wqw=Qqw(import.meta.dir,"..","dist","ui","cms-app.js"),Bqw=Z.object({entityType:Z.string(),id:Z.string(),frontmatter:Z.record(Z.string(),Z.unknown()),body:Z.string().optional(),baseContentHash:Z.string().optional()}),$qw=Z.object({entityType:Z.string(),frontmatter:Z.record(Z.string(),Z.unknown()),body:Z.string().optional()}),ja0={entityType:Z.string(),body:Z.string(),frontmatter:Z.record(Z.string(),Z.unknown())},fqw=Z.union([Z.object({...ja0,variant:Z.literal("rewrite").optional(),instruction:Z.string().trim().min(1),selection:Z.string().min(1).max(8000)}),Z.object({...ja0,variant:Z.literal("summarise"),targetField:Z.string().trim().min(1),body:Z.string().min(1)}),Z.object({...ja0,variant:Z.literal("tag-suggest"),targetField:Z.string().trim().min(1),body:Z.string().min(1)})]),Q22=Z.object({suggestion:Z.string()}),Yqw=Z.object({suggestions:Z.array(Z.string().trim().min(1)).max(12)}),Xqw=Z.object({selection:Z.string().min(1).max(8000),instruction:Z.string().trim().min(1).max(2000),agent:Z.string().trim().min(1).max(253)}),Zqw=Z.looseObject({response:Z.string()}),Hqw=Z.object({agents:Z.array(Z.object({id:Z.string(),label:Z.string()}))}),Wqw="file",w22=10485760,Kqw=Z.object({watchEnabled:Z.boolean(),lastSync:Z.string().nullable(),git:Z.object({branch:Z.string(),hasChanges:Z.boolean(),ahead:Z.number(),behind:Z.number(),lastCommit:Z.string().nullable(),remote:Z.string().nullable()}).nullable()});function B22(A){let{routePath:Q,getContext:w,resolveOperatorSession:B,getEntityDisplay:$}=A,f=`${Q}/assets/app.js`,Y=(H)=>`${Q}/api/${H}`,X=async(H)=>await B(H)?null:kQ({error:"Operator session required"},401);return[{path:Q,method:"GET",public:!0,handler:async(H)=>{if(!await B(H))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(Q)}`,"Cache-Control":"no-store"}});return new Response(A22({assetPath:f,surfaces:dI(w().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:f,method:"GET",public:!0,handler:async()=>{let H=Bun.file(wqw);if(!await H.exists())return new Response("CMS editor UI asset not built",{status:404});return new Response(H,{headers:{"Content-Type":"text/javascript; charset=utf-8","Cache-Control":"no-cache"}})}},{path:Y("types"),method:"GET",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Gqw(w(),$())}},{path:Y("schema"),method:"GET",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Dqw(w(),H)}},{path:Y("entities"),method:"GET",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return zqw(w(),H)}},{path:Y("entities"),method:"PUT",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return qqw(w(),H)}},{path:Y("entities"),method:"POST",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return bqw(w(),H)}},{path:Y("entities"),method:"DELETE",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Vqw(w(),H)}},{path:Y("upload"),method:"POST",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return kqw(w(),H,Y("upload"))}},{path:Y("assist"),method:"POST",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Jqw(w(),H)}},{path:Y("agents"),method:"GET",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Iqw(w())}},{path:Y("ask-agent"),method:"POST",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Fqw(w(),H)}},{path:Y("sync-status"),method:"GET",public:!0,handler:async(H)=>{let W=await X(H);if(W)return W;return Uqw(w())}}]}async function Uqw(A){let Q={directorySync:null,git:null},w=await A.messaging.send({type:"sync:status:request",payload:{}});if(!("success"in w)||!w.success)return kQ(Q);let B=Kqw.safeParse(w.data);if(!B.success)return kQ(Q);return kQ({directorySync:{lastSync:B.data.lastSync,watching:B.data.watchEnabled},git:B.data.git})}async function Gqw(A,Q){let w=new Map((await A.entityService.getEntityCounts()).map(($)=>[$.entityType,$.count])),B=A.entityService.getEntityTypes().flatMap(($)=>{if(!A.entities.getEffectiveFrontmatterSchema($))return[];let Y=A.entities.getAdapter($);return[{entityType:$,label:t12($,Q?.[$]).pluralLabel,isSingleton:Y?.isSingleton===!0,hasBody:Y?.hasBody!==!1,count:w.get($)??0}]});return kQ({types:B})}function Dqw(A,Q){let w=new URL(Q.url).searchParams.get("type");if(!w)return kQ({error:"type query parameter is required"},400);let B=A.entities.getEffectiveFrontmatterSchema(w);if(!B)return kQ({error:`Unknown entity type: ${w}`},404);let $=A.entities.getAdapter(w),f=co(w),Y=f?[]:Object.entries(B.shape).map(([X,H])=>uo(X,H));return kQ({entityType:w,format:f?"raw":"frontmatter",isSingleton:$?.isSingleton===!0,hasBody:f||$?.hasBody!==!1,fields:Y})}async function zqw(A,Q){let w=new URL(Q.url).searchParams,B=w.get("type");if(!B)return kQ({error:"type query parameter is required"},400);if(!A.entities.getEffectiveFrontmatterSchema(B))return kQ({error:`Unknown entity type: ${B}`},404);let $=w.get("id");if($){let Y=await A.entityService.getEntity({entityType:B,id:$});if(!Y)return kQ({error:`Entity not found: ${$}`},404);let{frontmatter:X,body:H}=Ma0(B,Y.content);return kQ({entity:{id:Y.id,entityType:Y.entityType,frontmatter:X,body:H,contentHash:Y.contentHash,created:Y.created,updated:Y.updated}})}let f=await A.entityService.listEntities({entityType:B});return kQ({entities:f.map((Y)=>({id:Y.id,entityType:Y.entityType,frontmatter:Ma0(B,Y.content).frontmatter,updated:Y.updated}))})}async function qqw(A,Q){let w;try{w=Bqw.parse(await Q.json())}catch{return kQ({error:"Invalid update payload"},400)}let{entityType:B,id:$}=w,f=A.entities.getEffectiveFrontmatterSchema(B);if(!f)return kQ({error:`Unknown entity type: ${B}`},404);let Y=$22(A,B,w.body);if(Y)return Y;let X=co(B);if(X&&Object.keys(w.frontmatter).length>0)return kQ({error:`Entity type ${B} is raw markdown without frontmatter`},400);let H=X?{success:!0,data:{}}:f.safeParse(w.frontmatter);if(!H.success)return kQ({error:"Invalid frontmatter",issues:H.error.issues},400);let W=await A.entityService.getEntity({entityType:B,id:$});if(!W)return kQ({error:`Entity not found: ${$}`},404);if(w.baseContentHash!==void 0&&w.baseContentHash!==W.contentHash)return kQ({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:W.contentHash},409);let K=w.body??Ma0(B,W.content).body,U=X?K:F5(K,H.data),G=A.entities.getAdapter(B)?.fromMarkdown(U),q={...W,...G,id:W.id,entityType:W.entityType,content:U},b=await A.entityService.updateEntity({entity:q});return kQ({entityId:b.entityId,jobId:b.jobId,skipped:b.skipped})}async function bqw(A,Q){let w;try{w=$qw.parse(await Q.json())}catch{return kQ({error:"Invalid create payload"},400)}let{entityType:B}=w,$=A.entities.getEffectiveFrontmatterSchema(B);if(!$)return kQ({error:`Unknown entity type: ${B}`},404);let f=$22(A,B,w.body);if(f)return f;let Y=co(B);if(Y&&Object.keys(w.frontmatter).length>0)return kQ({error:`Entity type ${B} is raw markdown without frontmatter`},400);let X=Y?{success:!0,data:{}}:$.safeParse(w.frontmatter);if(!X.success)return kQ({error:"Invalid frontmatter",issues:X.error.issues},400);let H=Y?w.body??"":F5(w.body??"",X.data),W=A.entities.getAdapter(B)?.fromMarkdown(H),K=await A.entityService.createEntity({entity:{...W,entityType:B,content:H,metadata:W?.metadata??{}}});return kQ({entityId:K.entityId,jobId:K.jobId},201)}async function Vqw(A,Q){let w=new URL(Q.url).searchParams,B=w.get("type"),$=w.get("id");if(!B||!$)return kQ({error:"type and id query parameters are required"},400);if(!await A.entityService.getEntity({entityType:B,id:$}))return kQ({error:`Entity not found: ${$}`},404);let Y=await A.entityService.deleteEntity({entityType:B,id:$});return kQ({deleted:Y})}async function Jqw(A,Q){let w;try{w=fqw.parse(await Q.json())}catch{return kQ({error:"Invalid assist payload or selection length"},400)}let B=A.entities.getEffectiveFrontmatterSchema(w.entityType);if(!B)return kQ({error:`Unknown entity type: ${w.entityType}`},404);if(w.variant==="summarise"||w.variant==="tag-suggest"){let Y=B.shape[w.targetField];if(!Y)return kQ({error:`Unknown frontmatter field: ${w.targetField}`},400);let X=uo(w.targetField,Y);if(!(w.variant==="summarise"?X.widget==="string"||X.widget==="text":X.widget==="list"&&X.field?.widget==="string"))return kQ({error:`Field ${w.targetField} is incompatible with ${w.variant}`},400);let W=["You are editing CMS frontmatter from an existing markdown body.",`Entity type: ${w.entityType}`,`Target field: ${w.targetField}`,`Existing frontmatter JSON: ${JSON.stringify(w.frontmatter)}`,"","Full markdown body:",w.body];if(w.variant==="summarise"){let{object:U}=await A.ai.generateObject(["Summarise the body for the target frontmatter field.","Return only the field value in the suggestion field.",...W].join(`
|
|
8167
8167
|
`),Q22);return kQ({variant:w.variant,targetField:w.targetField,suggestion:U.suggestion})}let{object:K}=await A.ai.generateObject(["Suggest tags for the target frontmatter field.","Return concise tag strings in the suggestions field without duplicates.",...W].join(`
|
|
8168
8168
|
`),Yqw);return kQ({variant:w.variant,targetField:w.targetField,suggestions:[...new Set(K.suggestions)]})}let $=["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: ${w.entityType}`,`Frontmatter JSON: ${JSON.stringify(w.frontmatter)}`,`Instruction: ${w.instruction}`,"","Selected markdown:",w.selection,"","Full body for context:",w.body].join(`
|
|
8169
|
-
`),{object:f}=await A.ai.generateObject($,Q22);return kQ({suggestion:f.suggestion})}async function Iqw(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return kQ({agents:[]});let w=Hqw.safeParse(Q.data);return kQ(w.success?w.data:{agents:[]})}async function Fqw(A,Q){let w;try{w=Xqw.parse(await Q.json())}catch{return kQ({error:"Invalid agent ask payload or selection length"},400)}let B=await A.messaging.send({type:"a2a:call:request",payload:w});if(!("success"in B)||!B.success){let f="error"in B&&typeof B.error==="string"?B.error:"Agent call failed",Y=f.startsWith("No handler found");return kQ({error:Y?"Agent asking is unavailable":f},Y?503:400)}if(B.data===void 0)return kQ({error:"Agent asking is unavailable"},503);let $=Zqw.safeParse(B.data);if(!$.success)return kQ({error:"Invalid response from agent"},502);return kQ({agentId:w.agent,response:$.data.response})}async function kqw(A,Q,w){let B=Number(Q.headers.get("content-length"));if(Number.isFinite(B)&&B>w22)return kQ({error:"Upload too large"},400);let $;try{$=await Q.formData()}catch{return kQ({error:"Invalid multipart upload"},400)}let f=$.get(Wqw);if(!(f instanceof File))return kQ({error:"Missing upload file"},400);if(f.size>w22)return kQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(f.type);if(!Y)return kQ({error:`No handler accepts uploads of type ${f.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:f.name,mediaType:f.type,content:Buffer.from(await f.arrayBuffer())}),W=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!W.success)return kQ({error:W.error},502);return kQ({entityId:W.data.entityId,jobId:W.data.jobId},201)}function $22(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return kQ({error:`Entity type ${Q} does not have a body`},400);return null}function Ma0(A,Q){if(co(A))return{frontmatter:{},body:Q};try{let w=r2(Q,Z.record(Z.string(),Z.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function kQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}var f22={name:"@brains/cms",version:"0.2.0-alpha.
|
|
8169
|
+
`),{object:f}=await A.ai.generateObject($,Q22);return kQ({suggestion:f.suggestion})}async function Iqw(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return kQ({agents:[]});let w=Hqw.safeParse(Q.data);return kQ(w.success?w.data:{agents:[]})}async function Fqw(A,Q){let w;try{w=Xqw.parse(await Q.json())}catch{return kQ({error:"Invalid agent ask payload or selection length"},400)}let B=await A.messaging.send({type:"a2a:call:request",payload:w});if(!("success"in B)||!B.success){let f="error"in B&&typeof B.error==="string"?B.error:"Agent call failed",Y=f.startsWith("No handler found");return kQ({error:Y?"Agent asking is unavailable":f},Y?503:400)}if(B.data===void 0)return kQ({error:"Agent asking is unavailable"},503);let $=Zqw.safeParse(B.data);if(!$.success)return kQ({error:"Invalid response from agent"},502);return kQ({agentId:w.agent,response:$.data.response})}async function kqw(A,Q,w){let B=Number(Q.headers.get("content-length"));if(Number.isFinite(B)&&B>w22)return kQ({error:"Upload too large"},400);let $;try{$=await Q.formData()}catch{return kQ({error:"Invalid multipart upload"},400)}let f=$.get(Wqw);if(!(f instanceof File))return kQ({error:"Missing upload file"},400);if(f.size>w22)return kQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(f.type);if(!Y)return kQ({error:`No handler accepts uploads of type ${f.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:f.name,mediaType:f.type,content:Buffer.from(await f.arrayBuffer())}),W=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!W.success)return kQ({error:W.error},502);return kQ({entityId:W.data.entityId,jobId:W.data.jobId},201)}function $22(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return kQ({error:`Entity type ${Q} does not have a body`},400);return null}function Ma0(A,Q){if(co(A))return{frontmatter:{},body:Q};try{let w=r2(Q,Z.record(Z.string(),Z.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function kQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}var f22={name:"@brains/cms",version:"0.2.0-alpha.164",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",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 _qw=Z.looseObject({label:Z.string().optional(),pluralName:Z.string().optional()}),Nqw=Z.object({entityDisplay:Z.record(Z.string(),_qw).optional(),routePath:Z.string().default("/cms")});class xa0 extends Aw{constructor(A={}){super("cms",f22,A,Nqw)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"})}getWebRoutes(){return B22({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:Pqw,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay})}}function Jj(A={}){return new xa0(A)}async function Pqw(A){return Boolean(await v7()?.getOperatorSession(A))}wA();L0();wA();L0();var OX0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],jqw=new Set(OX0),Mqw=Z.enum(["public","trusted","anchor"]);function Oa0(A){return jqw.has(A)}var Y22=Z.object({label:Z.string(),value:Z.string(),tone:Z.enum(["plain","good","warn"]).optional()}),X22=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),group:Z.string().min(1),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),visibility:Mqw.default("public"),needsOperator:Z.number().int().nonnegative().optional(),digest:Z.array(Y22).max(4).optional()});class vX0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let w={...X22.parse(A),dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{},...A.component?{component:A.component}:{},...A.clientScript?{clientScript:A.clientScript}:{}},B=`${w.pluginId}:${w.id}`;this.widgets.set(B,w),this.logger.debug("Dashboard widget registered",{key:B,title:w.title,rendererName:w.rendererName,group:w.group})}unregister(A,Q){if(Q){this.widgets.delete(`${A}:${Q}`);return}for(let w of this.widgets.keys())if(w.startsWith(`${A}:`))this.widgets.delete(w)}get(A,Q){return this.widgets.get(`${A}:${Q}`)}list(A={}){let Q=typeof A==="string"?{section:A}:A,w=Q.permissionLevel??"public";return Array.from(this.widgets.values()).filter((B)=>!Q.section||B.section===Q.section).filter((B)=>Y9.hasPermission(w,B.visibility)).sort((B,$)=>B.priority-$.priority)}get size(){return this.widgets.size}}class RX0{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={},w=A.widgets??this.registry.list({...A.permissionLevel!==void 0&&{permissionLevel:A.permissionLevel}}),B=await Promise.allSettled(w.map(async($)=>{let f=await $.dataProvider(),{dataProvider:Y,digestProvider:X,component:H,clientScript:W,visibility:K="public",...U}=$;return{key:`${$.pluginId}:${$.id}`,widget:{...U,visibility:K,...this.deriveLiveDigest($,f)},data:f}}));for(let $=0;$<B.length;$++){let f=B[$],Y=w[$];if(!f||!Y)continue;if(f.status==="fulfilled")Q[f.value.key]={widget:f.value.widget,data:f.value.data};else this.logger.error("Widget data provider failed",{widgetId:Y.id,pluginId:Y.pluginId,error:SA(f.reason)})}return{widgets:Q}}deriveLiveDigest(A,Q){if(!A.digestProvider)return{};try{let w=A.digestProvider(Q);return{...w.digest!==void 0&&{digest:w.digest},...w.needsOperator!==void 0&&{needsOperator:w.needsOperator}}}catch(w){return this.logger.error("Widget digest provider failed",{widgetId:A.id,pluginId:A.pluginId,error:SA(w)}),{}}}async fetch(A,Q,w){return await this.getDashboardData()}}import{render as Zbw}from"preact-render-to-string";var Z22=`* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8170
8170
|
html, body { min-height: 100%; max-width: 100%; }
|
|
8171
8171
|
body {
|
|
8172
8172
|
font-family: var(--console-ui);
|
|
@@ -10051,7 +10051,7 @@ ${H22}`;import{jsxDEV as Ij,Fragment as K22}from"preact/jsx-dev-runtime";functio
|
|
|
10051
10051
|
activate(resolveId(window.location.hash), false);
|
|
10052
10052
|
});
|
|
10053
10053
|
})();`;function zbw({hiddenWidgetCount:A,loginUrl:Q}){return bA("section",{class:"card operator-gate",children:[bA("div",{children:[bA("div",{class:"card-title",children:"Operator access"},void 0,!1,void 0,this),bA("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),bA("a",{class:"operator-gate-link",href:Q,children:"Sign in"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function qbw({dashboardPath:A,surfaces:Q,operatorAccess:w}){let B=w?.isOperator?w.logoutUrl:w?.loginUrl??"/login",$=w?.isOperator?"Operator":"Visitor",f=w?.isOperator?"Sign out":"Sign in";return bA("header",{class:"console-strip","aria-label":"Operator surfaces",children:[bA("a",{class:"console-mark",href:A,"aria-label":"Dashboard home",children:[bA("span",{class:"pulse"},void 0,!1,void 0,this),bA("span",{children:["Brain"," ",bA("span",{class:"console-mark-long",children:["\xB7 ",bA("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),bA("nav",{class:"surface-nav","aria-label":"Console surfaces",children:Q.map((Y)=>bA("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),bA("button",{class:"command-chip",type:"button","aria-label":"Search or jump",children:[bA("span",{class:"command-chip-hint",children:"Search or jump\u2026"},void 0,!1,void 0,this),bA("kbd",{children:"\u2318K"},void 0,!1,void 0,this),bA("span",{class:"command-chip-icon","aria-hidden":"true",children:"\u2315"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("button",{id:"climateToggle",class:"climate-chip",type:"button","aria-label":"Toggle climate",children:"\u25D0"},void 0,!1,void 0,this),bA("a",{class:w?.isOperator?"session-chip":"session-chip is-visitor",href:B,"aria-label":`${$} \xB7 ${f}`,children:[bA("span",{children:$},void 0,!1,void 0,this),bA("strong",{children:f},void 0,!1,void 0,this),bA("span",{class:"session-chip-avatar","aria-hidden":"true",children:w?.isOperator?"OP":"VI"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function bbw({tabs:A}){return bA("nav",{class:"dashboard-tabs","aria-label":"Dashboard sections",role:"tablist",children:[bA("a",{class:"dashboard-tab is-active",href:"#overview",role:"tab","aria-selected":"true","data-dashboard-tab-link":"overview",children:"Overview"},void 0,!1,void 0,this),A.map((Q)=>bA("a",{class:"dashboard-tab",href:`#${Q.id}`,role:"tab","aria-selected":"false","data-dashboard-tab-link":Q.id,children:[bA("span",{children:Q.label},void 0,!1,void 0,this),Q.needsOperator>0?bA("span",{class:"tab-badge tab-badge--needs",children:Q.needsOperator},void 0,!1,void 0,this):Q.widgetCount>0?bA("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)}function ga0(A){return A.indexStatus?.ready??A.indexReady??A.appInfo.embeddings>0}function Vbw({input:A}){let Q=ga0(A),w=A.activityLog?.[0],B=A.appInfo.entityCounts.length,$=A.appInfo.interactions.map((U)=>U.id).slice(0,3).join(" / "),f=A.indexStatus?.embeddedEntities??A.appInfo.embeddings,Y=A.indexStatus?.embeddableEntities,X=A.indexStatus?(A.indexStatus.activeEmbeddingJobs??0)+(A.indexStatus.missingEmbeddings??0)+(A.indexStatus.staleEmbeddings??0):0,H=Y===void 0?`${f}`:`${f}/${Y}`,W=X>0?`${H} embedded \xB7 ${X} queued`:`${H} embedded`,K=(A.jobProgress??[]).some((U)=>U.status==="processing"||U.status==="pending");return bA("section",{class:"overview-vitals","aria-label":"Runtime vitals",children:[bA("article",{class:"vital-card",children:[bA("span",{class:"vital-label",children:"Entities"},void 0,!1,void 0,this),bA("strong",{class:"vital-num",children:A.appInfo.entities},void 0,!1,void 0,this),bA("span",{class:"vital-sub",children:B===1?"1 type":`${B} types`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("article",{class:"vital-card",children:[bA("span",{class:"vital-label",children:"Interactions"},void 0,!1,void 0,this),bA("strong",{class:"vital-num",children:A.appInfo.interactions.length},void 0,!1,void 0,this),bA("span",{class:"vital-sub",children:$||"no channels"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("article",{class:`vital-card ${Q?"vital-card--ok":"vital-card--warm"}`,children:[bA("span",{class:"vital-label",children:"Semantic index"},void 0,!1,void 0,this),bA("strong",{class:"vital-num vital-num--text",children:Q?"Ready":"Pending"},void 0,!1,void 0,this),bA("span",{class:"vital-sub",children:W},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("article",{class:`vital-card${K?" vital-card--warm":""}`,children:[bA("span",{class:"vital-label",children:"Last write"},void 0,!1,void 0,this),bA("strong",{class:"vital-num vital-num--text",children:w?ya0(w.timestamp):"\u2014"},void 0,!1,void 0,this),bA("span",{class:"vital-sub",children:w?`${w.entityType}/${w.entityId}`:"no writes observed"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Jbw({input:A}){let{role:Q,purpose:w,values:B}=A.character;if(!Q&&!w&&B.length===0)return null;return bA("aside",{class:"card identity-capsule",children:[bA("div",{class:"card-head",children:[bA("span",{class:"card-title",children:"Identity"},void 0,!1,void 0,this),bA("span",{class:"card-from",children:"identity"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("div",{class:"identity-capsule-body",children:[Q&&bA("span",{class:"identity-role",children:["\u201C",Q,"\u201D"]},void 0,!0,void 0,this),B.length>0&&bA("span",{class:"values",children:B.map(($)=>bA("span",{class:"value",children:$},$,!1,void 0,this))},void 0,!1,void 0,this),w&&bA("span",{class:"identity-purpose",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Ibw({cards:A}){if(A.length===0)return bA("section",{class:"card overview-empty-digest",children:[bA("div",{class:"card-head",children:bA("span",{class:"card-title",children:"Group digests"},void 0,!1,void 0,this)},void 0,!1,void 0,this),bA("p",{class:"muted",children:"No plugin groups are visible yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return bA("section",{class:"digests","aria-label":"Group digests",children:A.map((Q)=>bA("a",{class:"card digest-card",href:Q.href,children:[bA("div",{class:"digest-head",children:[bA("h4",{children:Q.label},void 0,!1,void 0,this),bA("span",{class:"digest-go",children:"open \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("dl",{class:"digest-lines",children:Q.lines.map((w)=>bA("div",{class:`digest-line digest-line--${w.tone??"plain"}`,children:[bA("dt",{children:w.label},void 0,!1,void 0,this),bA("dd",{children:w.value},void 0,!1,void 0,this)]},`${w.label}:${w.value}`,!0,void 0,this))},void 0,!1,void 0,this)]},Q.id,!0,void 0,this))},void 0,!1,void 0,this)}function Fbw(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 ya0(A){let Q=new Date(A);if(Number.isNaN(Q.getTime()))return"\u2014";return Q.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"})}var I22={created:{glyph:"\uFF0B",tone:""},updated:{glyph:"\u2713",tone:" ledger-glyph--ok"},deleted:{glyph:"\u2212",tone:" ledger-glyph--warn"}};function kbw({events:A}){return bA("section",{class:"card activity-ledger",children:[bA("div",{class:"card-head",children:[bA("span",{class:"card-title",children:"Activity"},void 0,!1,void 0,this),bA("span",{class:"card-from",children:"entity events"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0?bA("p",{class:"muted",children:"No entity activity has been observed this session."},void 0,!1,void 0,this):bA("ol",{class:"ledger",children:A.map((Q)=>bA("li",{class:"ledger-entry",children:[bA("time",{class:"ledger-time",dateTime:Q.timestamp,children:ya0(Q.timestamp)},void 0,!1,void 0,this),bA("span",{class:`ledger-glyph${I22[Q.action].tone}`,"aria-hidden":"true",children:I22[Q.action].glyph},void 0,!1,void 0,this),bA("span",{class:"ledger-what",children:[bA("b",{children:Q.entityType},void 0,!1,void 0,this)," ",Q.action," \u2014"," ",bA("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 Lbw(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 _bw(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 Nbw({status:A}){let Q=Lbw(A),w=A.ready?A.degraded?"Degraded":"Ready":"Indexing";return bA("div",{class:"index-gauge",style:`--index-percent: ${Q}%`,children:[bA("div",{class:"index-gauge-ring","aria-hidden":"true",children:bA("span",{children:[Q,"%"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),bA("div",{class:"index-gauge-copy",children:[bA("strong",{children:w},void 0,!1,void 0,this),bA("span",{children:_bw(A)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Pbw({input:A}){let Q=ga0(A);return bA("section",{class:"card semantic-index-card",children:[bA("div",{class:"card-head",children:[bA("span",{class:"card-title",children:"Semantic index"},void 0,!1,void 0,this),bA("span",{class:"card-from",children:"entity-service"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.indexStatus?bA(Nbw,{status:A.indexStatus},void 0,!1,void 0,this):bA("dl",{class:"kv",children:bA("div",{class:"kv-row",children:[bA("dt",{children:"Semantic index"},void 0,!1,void 0,this),bA("dd",{children:Q?"Ready":"Pending"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function jbw({status:A}){let Q=A.totalFiles===void 0?"\u2014":A.totalFiles===1?"1 file":`${A.totalFiles} files`,w=A.byEntityType?Object.entries(A.byEntityType).sort(([,B],[,$])=>$-B).slice(0,2).map(([B,$])=>`${B} ${$}`).join(", "):void 0;return bA("section",{class:"card content-sync-card",children:[bA("div",{class:"card-head",children:[bA("span",{class:"card-title",children:"Content sync"},void 0,!1,void 0,this),bA("span",{class:"card-from",children:"directory-sync"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("dl",{class:"kv",children:[bA("div",{class:"kv-row",children:[bA("dt",{children:"Path"},void 0,!1,void 0,this),bA("dd",{children:A.syncPath},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("div",{class:"kv-row",children:[bA("dt",{children:"Files"},void 0,!1,void 0,this),bA("dd",{children:w?`${Q} \xB7 ${w}`:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("div",{class:"kv-row",children:[bA("dt",{children:"Watch"},void 0,!1,void 0,this),bA("dd",{children:A.watchEnabled?"Watching":A.isInitialized?"Manual":"Not initialized"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("div",{class:"kv-row",children:[bA("dt",{children:"Last sync"},void 0,!1,void 0,this),bA("dd",{children:A.lastSync?`last sync ${Fbw(A.lastSync)}`:"\u2014"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),bA("div",{class:"pipeline-mini","aria-label":"Write pipeline",children:[bA("span",{class:`pipeline-step${A.isInitialized?" is-done":""}`,children:"entity db"},void 0,!1,void 0,this),bA("span",{class:"pipeline-track"},void 0,!1,void 0,this),bA("span",{class:`pipeline-step${(A.totalFiles??0)>0?" is-done":""}`,children:"exported"},void 0,!1,void 0,this),bA("span",{class:"pipeline-track"},void 0,!1,void 0,this),bA("span",{class:`pipeline-step${A.lastSync?" is-done":""}`,children:"committed"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Mbw={pending:"run",processing:"run",completed:"done",failed:"fail"},xbw={pending:"pending",processing:"running",completed:"done",failed:"failed"};function Obw({jobs:A}){return bA("section",{class:"card widget-card--wide job-queue-card",children:[bA("div",{class:"card-head",children:[bA("span",{class:"card-title",children:"Job queue"},void 0,!1,void 0,this),bA("span",{class:"card-from",children:"job-queue"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0?bA("p",{class:"muted",children:"No recent job progress observed."},void 0,!1,void 0,this):bA("table",{class:"jobs",children:[bA("thead",{children:bA("tr",{children:[bA("th",{children:"Job"},void 0,!1,void 0,this),bA("th",{children:"Type"},void 0,!1,void 0,this),bA("th",{children:"Updated"},void 0,!1,void 0,this),bA("th",{children:"Status"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),bA("tbody",{children:A.map((Q)=>bA("tr",{children:[bA("td",{class:"mono",children:Q.id.slice(0,8)},void 0,!1,void 0,this),bA("td",{children:Q.jobType??Q.kind},void 0,!1,void 0,this),bA("td",{class:"mono",children:ya0(Q.updatedAt)},void 0,!1,void 0,this),bA("td",{children:bA("span",{class:`status-pill status-pill--${Mbw[Q.status]}`,children:[xbw[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)}function vbw({input:A,tabs:Q,showOperatorGate:w}){let B=Kbw(Q,A),$=A.activityLog??[];return bA("section",{id:"overview",class:"dashboard-tab-panel is-active","data-dashboard-tab-panel":!0,"aria-labelledby":"dashboard-tab-overview",children:[bA(Vbw,{input:A},void 0,!1,void 0,this),bA(Jbw,{input:A},void 0,!1,void 0,this),w&&A.operatorAccess&&bA(zbw,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),bA("div",{class:"overview-grid",children:[bA(Ibw,{cards:B},void 0,!1,void 0,this),bA(kbw,{events:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Rbw({tab:A,input:Q,now:w}){let B=[...A.widgets.primary,...A.widgets.secondary],$=A.group==="system",f=A.group==="knowledge",Y=A.widgets.sidebar.length>0||$;return bA("section",{id:A.id,class:"dashboard-tab-panel","data-dashboard-tab-panel":!0,"data-dashboard-group":A.group,children:[bA("header",{class:"tab-section-head",children:bA("h2",{children:A.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),bA("div",{class:`layout tab-layout${Y?"":" tab-layout--main-only"}`,children:[bA("div",{class:"main-column",children:[f&&bA(G22,{total:Q.appInfo.entities,entityCounts:Q.appInfo.entityCounts},void 0,!1,void 0,this),$&&bA(F22,{children:[bA(Pbw,{input:Q},void 0,!1,void 0,this),Q.directorySyncStatus&&bA(jbw,{status:Q.directorySyncStatus},void 0,!1,void 0,this),bA(Obw,{jobs:Q.jobProgress??[]},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B.map((X)=>bA(Ra0,{widget:X},`${X.widget.pluginId}:${X.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),Y&&bA("div",{class:"sidebar-column",children:[$&&bA(F22,{children:[bA(D22,{endpoints:Q.appInfo.endpoints,baseUrl:Q.baseUrl},void 0,!1,void 0,this),bA(V22,{appInfo:Q.appInfo,now:w},void 0,!1,void 0,this),bA(z22,{interactions:Q.appInfo.interactions,baseUrl:Q.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.widgets.sidebar.map((X)=>bA(Ra0,{widget:X},`${X.widget.pluginId}:${X.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function hbw({input:A}){let Q=Gbw(A.widgets),w=A.operatorAccess&&!A.operatorAccess.isOperator&&A.operatorAccess.hiddenWidgetCount>0,B=A.dashboardPath??"/dashboard",$=new Date;return bA("html",{lang:"en","data-climate":"instrument",children:[bA("head",{children:[bA("meta",{charSet:"utf-8"},void 0,!1,void 0,this),bA("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0, viewport-fit=cover"},void 0,!1,void 0,this),bA("title",{children:A.title},void 0,!1,void 0,this),bA("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),bA("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),bA("link",{href:Sd,rel:"stylesheet"},void 0,!1,void 0,this),A.themeCSS!==void 0&&bA("style",{"data-dashboard-theme":!0,dangerouslySetInnerHTML:{__html:A.themeCSS}},void 0,!1,void 0,this),bA("style",{"data-dashboard-styles":!0,dangerouslySetInnerHTML:{__html:W22}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("body",{children:[bA(qbw,{dashboardPath:B,surfaces:A.surfaces??[{id:"dashboard",label:"Dashboard",href:B,isActive:!0}],operatorAccess:A.operatorAccess},void 0,!1,void 0,this),bA("main",{class:"console","data-component":"dashboard:dashboard",children:[bA("div",{class:"frame",children:[bA(U22,{title:A.title,tagline:A.profile.description},void 0,!1,void 0,this),bA(bbw,{tabs:Q},void 0,!1,void 0,this),bA("div",{class:"canvas",children:bA("div",{class:"dashboard-tab-panels",children:[bA(vbw,{input:A,tabs:Q,showOperatorGate:Boolean(w)},void 0,!1,void 0,this),Q.map((f)=>bA(Rbw,{tab:f,input:A,now:$},f.id,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA(J22,{title:A.title,appInfo:A.appInfo,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),bA("script",{dangerouslySetInnerHTML:{__html:$P}},void 0,!1,void 0,this),bA("script",{dangerouslySetInnerHTML:{__html:fP}},void 0,!1,void 0,this),bA("script",{dangerouslySetInnerHTML:{__html:Dbw}},void 0,!1,void 0,this),A.widgetScripts.map((f,Y)=>bA("script",{dangerouslySetInnerHTML:{__html:f}},`widget-script:${Y}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function L22(A){return`<!doctype html>
|
|
10054
|
-
${Zbw(bA(hbw,{input:A},void 0,!1,void 0,this))}`}function Cbw(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function _22(A){let Q=A.query.trim().toLowerCase(),w=[];if(A.cmsPath!==void 0&&A.entities.length>0){let $=A.cmsPath;w.push({id:"entities",label:"Entities",items:A.entities.map((f)=>({id:`${f.entityType}/${f.id}`,title:f.title,sub:f.entityType,href:`${$}#/${encodeURIComponent(f.entityType)}/${encodeURIComponent(f.id)}`,tag:"edit in cms"}))})}let B=CX0([...new Set(A.groups)]).map(($)=>({group:$,label:Ey($)})).filter(({group:$,label:f})=>Q===""||f.toLowerCase().includes(Q)||$.toLowerCase().includes(Q)).map(({group:$,label:f})=>({id:`tab/${$}`,title:f,sub:"tab",href:`${A.dashboardPath}#${Cbw($)}`,tag:"dashboard"}));if(B.length>0)w.push({id:"tabs",label:"Dashboard",items:B});return w}function N22(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let Y=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...Y?.component?{component:Y.component}:{}},Y?.clientScript)B.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var P22={name:"@brains/dashboard",version:"0.2.0-alpha.163",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",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 ybw=Z.object({version:Z.string().default("1.0.0"),routePath:Z.string().default("/dashboard"),themeCSS:Z.string().optional()}),Ebw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),group:Z.string().min(1),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),visibility:Z.enum(["public","trusted","anchor"]).default("public"),needsOperator:Z.number().int().nonnegative().optional(),digest:Z.array(Z.object({label:Z.string(),value:Z.string(),tone:Z.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:Z.custom().optional(),clientScript:Z.string().optional(),dataProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!Oa0(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Tbw=Z.object({pluginId:Z.string(),widgetId:Z.string().optional()}),Sbw=Z.object({entityType:Z.string(),entityId:Z.string(),conversationId:Z.string().optional()}),mbw=Z.object({id:Z.string(),type:Z.enum(["job","batch"]),status:Z.enum(["pending","processing","completed","failed"]),message:Z.string().optional(),progress:Z.object({current:Z.number(),total:Z.number(),percentage:Z.number()}).optional(),jobDetails:Z.object({jobType:Z.string(),priority:Z.number(),retryCount:Z.number()}).optional()}),ubw=Z.object({success:Z.literal(!0),data:Z.object({syncPath:Z.string(),isInitialized:Z.boolean(),watchEnabled:Z.boolean(),lastSync:Z.string().datetime().optional(),totalFiles:Z.number().int().nonnegative().optional(),byEntityType:Z.record(Z.string(),Z.number().int().nonnegative()).optional()})});function cbw(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.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{}}}class Ea0 extends Aw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",P22,A,ybw)}recordActivity(A,Q){let w=Sbw.safeParse(Q);if(!w.success)return;this.activityLog=[{action:A,entityType:w.data.entityType,entityId:w.data.entityId,timestamp:new Date().toISOString(),...w.data.conversationId?{conversationId:w.data.conversationId}:{}},...this.activityLog].slice(0,12)}recordJobProgress(A){let Q=mbw.safeParse(A);if(!Q.success)return;let w=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,B={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}:{},...w?{progressLabel:w}:{}};this.jobProgress=[B,...this.jobProgress.filter(($)=>$.id!==B.id||$.kind!==B.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=ubw.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 vX0(this.logger),this.datasource=new RX0(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 w=Ebw.parse(Q.payload),B=cbw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:OX0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:SA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Tbw.parse(Q.payload);return this.widgetRegistry?.unregister(w.pluginId,w.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:w.pluginId,widgetId:w.widgetId}),{success:!0}}catch(w){return this.logger.error("Failed to unregister widget",{error:SA(w),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,w=await v7()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=f.filter((h)=>Y9.hasPermission($,h.visibility)),X=f.length-Y.length,[H,W,K,U]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),G=Q.identity.get(),q=Q.identity.getProfile(),b=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),J={...W,endpoints:W.endpoints.filter((h)=>Y9.hasPermission($,h.visibility)),interactions:W.interactions.filter((h)=>Y9.hasPermission($,h.visibility))},V=q.name||W.model||"Brain Dashboard",k=new URL(A.url),N=`${k.pathname}${k.search}`,L=encodeURIComponent(N),O=N22(H.widgets,this.widgetRegistry),v={title:V,baseUrl:b,widgets:O.widgets,widgetScripts:O.widgetScripts,dashboardPath:this.config.routePath,surfaces:dI(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:G,profile:q,appInfo:J,activityLog:this.activityLog,jobProgress:this.jobProgress,...U!==void 0&&{indexStatus:U},...K!==void 0&&{directorySyncStatus:K},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:X,loginUrl:`/login?return_to=${L}`,logoutUrl:`/logout?return_to=${L}`}};return new Response(L22(v),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await v7()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let w=this.ctx;if(!w)return Response.json({groups:[]});let B=new URL(A.url).searchParams.get("q")?.trim()??"",$=[];if(B.length>=2)try{$=(await w.entityService.search({query:B,options:{limit:6}})).map((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let f=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((X)=>X.group),Y=dI(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((X)=>X.id==="cms")?.href;return Response.json({groups:_22({query:B,groups:[...f,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:$})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function mF(A={}){return new Ea0(A)}L0();var lbw=Z.enum(["public","trusted","anchor"]),pbw=Z.object({label:Z.string(),value:Z.string(),tone:Z.enum(["plain","good","warn"]).optional()}),ibw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),group:Z.string().min(1),priority:Z.number(),section:Z.enum(["primary","secondary","sidebar"]),rendererName:Z.string(),visibility:lbw,needsOperator:Z.number().int().nonnegative().optional(),digest:Z.array(pbw).max(4).optional(),component:Z.custom().optional()}),dbw=Z.object({widget:ibw,data:Z.unknown()}),nbw=Z.object({widgets:Z.record(Z.string(),dbw)});wA();L0();wA();L0();import{h as KVw}from"preact";wA();yX();D2();L0();var gX0=Z.enum(["generating","draft","queued","published","failed"]),rbw=Z.enum(["generating","draft","queued","published","failed"]),yX0=Z.object({subject:Z.string(),status:gX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional()}),j22=Z.object({subject:Z.string(),status:gX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),obw=Z.object({subject:Z.string(),status:rbw,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Ty=PQ.extend({entityType:Z.literal("newsletter"),metadata:obw});wA();class M22 extends E2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Ty,frontmatterSchema:yX0})}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 x22=new M22;wA();wA();D2();L0();var sbw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional()}),abw=Z.looseObject({entityType:Z.string().optional(),query:sbw.optional()});function O22(A){try{let{content:Q}=r2(A.content,yX0);return Q}catch{return A.content}}class Ta0 extends L5{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=abw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=O22(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:Vf(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)w.sentAt=A.metadata.sentAt;return w}buildListResult(A,Q,w){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.id)return this.fetchSingleNewsletter(B.id,Q,$);let f=B.status,Y=f?{filter:{metadata:{status:f}}}:void 0,{items:X,pagination:H}=await this.fetchList(B,$,Y);return Q.parse(this.buildListResult(X,H,B))}async fetchSingleNewsletter(A,Q,w){let B=await w.getEntity({entityType:this.config.entityType,id:A});if(!B)throw Error(`Newsletter not found: ${A}`);let $=await this.resolveNavigation(B,w),f=[];if(B.metadata.entityIds?.length){let H=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:H,id:K});if(U){let G=U.metadata;return{id:K,title:G.title??K,url:`/${H}s/${G.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=O22(B),X={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:Y,created:B.created,updated:B.updated,sentAt:B.metadata.sentAt,scheduledFor:B.metadata.scheduledFor,newsletter:B,prevNewsletter:$.prev?{id:$.prev.id,subject:$.prev.subject,url:$.prev.url}:null,nextNewsletter:$.next?{id:$.next.id,subject:$.next.subject,url:$.next.url}:null,sourceEntities:f.length>0?f:void 0};return Q.parse(X)}}wA();D2();L0();var tbw=Z.object({prompt:Z.string().optional().describe("AI generation prompt"),sourceEntityIds:Z.array(Z.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:Z.enum(["post"]).optional().describe("Type of source entities"),content:Z.string().optional().describe("Direct content (skip AI)"),subject:Z.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:Z.boolean().optional().describe("Create as queued (true) or draft (false)")});class Sa0 extends J4{constructor(A,Q){super(A,Q,{schema:tbw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let G=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let b=(await Promise.all($.map((L)=>this.context.entityService.getEntity({entityType:G,id:L})))).filter((L)=>L!=null);if(b.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${b.length} posts`});let V=`Create an engaging newsletter that highlights these blog posts:
|
|
10054
|
+
${Zbw(bA(hbw,{input:A},void 0,!1,void 0,this))}`}function Cbw(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function _22(A){let Q=A.query.trim().toLowerCase(),w=[];if(A.cmsPath!==void 0&&A.entities.length>0){let $=A.cmsPath;w.push({id:"entities",label:"Entities",items:A.entities.map((f)=>({id:`${f.entityType}/${f.id}`,title:f.title,sub:f.entityType,href:`${$}#/${encodeURIComponent(f.entityType)}/${encodeURIComponent(f.id)}`,tag:"edit in cms"}))})}let B=CX0([...new Set(A.groups)]).map(($)=>({group:$,label:Ey($)})).filter(({group:$,label:f})=>Q===""||f.toLowerCase().includes(Q)||$.toLowerCase().includes(Q)).map(({group:$,label:f})=>({id:`tab/${$}`,title:f,sub:"tab",href:`${A.dashboardPath}#${Cbw($)}`,tag:"dashboard"}));if(B.length>0)w.push({id:"tabs",label:"Dashboard",items:B});return w}function N22(A,Q){let w={},B=new Set;for(let[$,f]of Object.entries(A)){let Y=Q?.get(f.widget.pluginId,f.widget.id);if(w[$]={...f,...Y?.component?{component:Y.component}:{}},Y?.clientScript)B.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from(B)}}var P22={name:"@brains/dashboard",version:"0.2.0-alpha.164",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",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 ybw=Z.object({version:Z.string().default("1.0.0"),routePath:Z.string().default("/dashboard"),themeCSS:Z.string().optional()}),Ebw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),group:Z.string().min(1),priority:Z.number().default(50),section:Z.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:Z.string(),visibility:Z.enum(["public","trusted","anchor"]).default("public"),needsOperator:Z.number().int().nonnegative().optional(),digest:Z.array(Z.object({label:Z.string(),value:Z.string(),tone:Z.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:Z.custom().optional(),clientScript:Z.string().optional(),dataProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:Z.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!Oa0(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Tbw=Z.object({pluginId:Z.string(),widgetId:Z.string().optional()}),Sbw=Z.object({entityType:Z.string(),entityId:Z.string(),conversationId:Z.string().optional()}),mbw=Z.object({id:Z.string(),type:Z.enum(["job","batch"]),status:Z.enum(["pending","processing","completed","failed"]),message:Z.string().optional(),progress:Z.object({current:Z.number(),total:Z.number(),percentage:Z.number()}).optional(),jobDetails:Z.object({jobType:Z.string(),priority:Z.number(),retryCount:Z.number()}).optional()}),ubw=Z.object({success:Z.literal(!0),data:Z.object({syncPath:Z.string(),isInitialized:Z.boolean(),watchEnabled:Z.boolean(),lastSync:Z.string().datetime().optional(),totalFiles:Z.number().int().nonnegative().optional(),byEntityType:Z.record(Z.string(),Z.number().int().nonnegative()).optional()})});function cbw(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.clientScript?{clientScript:A.clientScript}:{},dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{}}}class Ea0 extends Aw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",P22,A,ybw)}recordActivity(A,Q){let w=Sbw.safeParse(Q);if(!w.success)return;this.activityLog=[{action:A,entityType:w.data.entityType,entityId:w.data.entityId,timestamp:new Date().toISOString(),...w.data.conversationId?{conversationId:w.data.conversationId}:{}},...this.activityLog].slice(0,12)}recordJobProgress(A){let Q=mbw.safeParse(A);if(!Q.success)return;let w=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,B={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}:{},...w?{progressLabel:w}:{}};this.jobProgress=[B,...this.jobProgress.filter(($)=>$.id!==B.id||$.kind!==B.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=ubw.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 vX0(this.logger),this.datasource=new RX0(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 w=Ebw.parse(Q.payload),B=cbw(w);return this.widgetRegistry?.register(B),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:OX0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:SA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Tbw.parse(Q.payload);return this.widgetRegistry?.unregister(w.pluginId,w.widgetId),this.logger.debug("Widget unregistered via messaging",{pluginId:w.pluginId,widgetId:w.widgetId}),{success:!0}}catch(w){return this.logger.error("Failed to unregister widget",{error:SA(w),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,w=await v7()?.getOperatorSession(A),B=Boolean(w),$=B?"anchor":"public",f=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=f.filter((h)=>Y9.hasPermission($,h.visibility)),X=f.length-Y.length,[H,W,K,U]=await Promise.all([this.datasource.getDashboardData({permissionLevel:$,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),G=Q.identity.get(),q=Q.identity.getProfile(),b=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),J={...W,endpoints:W.endpoints.filter((h)=>Y9.hasPermission($,h.visibility)),interactions:W.interactions.filter((h)=>Y9.hasPermission($,h.visibility))},V=q.name||W.model||"Brain Dashboard",k=new URL(A.url),N=`${k.pathname}${k.search}`,L=encodeURIComponent(N),O=N22(H.widgets,this.widgetRegistry),v={title:V,baseUrl:b,widgets:O.widgets,widgetScripts:O.widgetScripts,dashboardPath:this.config.routePath,surfaces:dI(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:G,profile:q,appInfo:J,activityLog:this.activityLog,jobProgress:this.jobProgress,...U!==void 0&&{indexStatus:U},...K!==void 0&&{directorySyncStatus:K},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:B,hiddenWidgetCount:X,loginUrl:`/login?return_to=${L}`,logoutUrl:`/logout?return_to=${L}`}};return new Response(L22(v),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await v7()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let w=this.ctx;if(!w)return Response.json({groups:[]});let B=new URL(A.url).searchParams.get("q")?.trim()??"",$=[];if(B.length>=2)try{$=(await w.entityService.search({query:B,options:{limit:6}})).map((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let f=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((X)=>X.group),Y=dI(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((X)=>X.id==="cms")?.href;return Response.json({groups:_22({query:B,groups:[...f,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:$})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function mF(A={}){return new Ea0(A)}L0();var lbw=Z.enum(["public","trusted","anchor"]),pbw=Z.object({label:Z.string(),value:Z.string(),tone:Z.enum(["plain","good","warn"]).optional()}),ibw=Z.object({id:Z.string(),pluginId:Z.string(),title:Z.string(),description:Z.string().optional(),group:Z.string().min(1),priority:Z.number(),section:Z.enum(["primary","secondary","sidebar"]),rendererName:Z.string(),visibility:lbw,needsOperator:Z.number().int().nonnegative().optional(),digest:Z.array(pbw).max(4).optional(),component:Z.custom().optional()}),dbw=Z.object({widget:ibw,data:Z.unknown()}),nbw=Z.object({widgets:Z.record(Z.string(),dbw)});wA();L0();wA();L0();import{h as KVw}from"preact";wA();yX();D2();L0();var gX0=Z.enum(["generating","draft","queued","published","failed"]),rbw=Z.enum(["generating","draft","queued","published","failed"]),yX0=Z.object({subject:Z.string(),status:gX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional()}),j22=Z.object({subject:Z.string(),status:gX0,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),obw=Z.object({subject:Z.string(),status:rbw,entityIds:Z.array(Z.string()).optional(),scheduledFor:Z.string().datetime().optional(),sentAt:Z.string().datetime().optional(),buttondownId:Z.string().optional(),sourceEntityType:Z.string().optional(),error:Z.string().optional()}),Ty=PQ.extend({entityType:Z.literal("newsletter"),metadata:obw});wA();class M22 extends E2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Ty,frontmatterSchema:yX0})}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 x22=new M22;wA();wA();D2();L0();var sbw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:Z.enum(["generating","draft","queued","published","failed"]).optional()}),abw=Z.looseObject({entityType:Z.string().optional(),query:sbw.optional()});function O22(A){try{let{content:Q}=r2(A.content,yX0);return Q}catch{return A.content}}class Ta0 extends L5{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=abw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=O22(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:Vf(Q,150),created:A.created,url:`/newsletters/${A.id}`};if(A.metadata.sentAt)w.sentAt=A.metadata.sentAt;return w}buildListResult(A,Q,w){return{newsletters:A,totalCount:Q?.totalItems??A.length,pagination:Q}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A),$=w.entityService;if(B.id)return this.fetchSingleNewsletter(B.id,Q,$);let f=B.status,Y=f?{filter:{metadata:{status:f}}}:void 0,{items:X,pagination:H}=await this.fetchList(B,$,Y);return Q.parse(this.buildListResult(X,H,B))}async fetchSingleNewsletter(A,Q,w){let B=await w.getEntity({entityType:this.config.entityType,id:A});if(!B)throw Error(`Newsletter not found: ${A}`);let $=await this.resolveNavigation(B,w),f=[];if(B.metadata.entityIds?.length){let H=B.metadata.sourceEntityType??"post";f=(await Promise.all(B.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:H,id:K});if(U){let G=U.metadata;return{id:K,title:G.title??K,url:`/${H}s/${G.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=O22(B),X={id:B.id,subject:B.metadata.subject,status:B.metadata.status,content:Y,created:B.created,updated:B.updated,sentAt:B.metadata.sentAt,scheduledFor:B.metadata.scheduledFor,newsletter:B,prevNewsletter:$.prev?{id:$.prev.id,subject:$.prev.subject,url:$.prev.url}:null,nextNewsletter:$.next?{id:$.next.id,subject:$.next.subject,url:$.next.url}:null,sourceEntities:f.length>0?f:void 0};return Q.parse(X)}}wA();D2();L0();var tbw=Z.object({prompt:Z.string().optional().describe("AI generation prompt"),sourceEntityIds:Z.array(Z.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:Z.enum(["post"]).optional().describe("Type of source entities"),content:Z.string().optional().describe("Direct content (skip AI)"),subject:Z.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:Z.boolean().optional().describe("Create as queued (true) or draft (false)")});class Sa0 extends J4{constructor(A,Q){super(A,Q,{schema:tbw,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:B,sourceEntityIds:$,sourceEntityType:f}=A,{content:Y,subject:X}=A;if(Y){if(!X)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if($&&$.length>0){let G=f??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${$.length} source entities`});let b=(await Promise.all($.map((L)=>this.context.entityService.getEntity({entityType:G,id:L})))).filter((L)=>L!=null);if(b.length===0)this.failEarly(`No source entities found for IDs: ${$.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${b.length} posts`});let V=`Create an engaging newsletter that highlights these blog posts:
|
|
10055
10055
|
|
|
10056
10056
|
${b.map((L)=>`## ${L.metadata.title}
|
|
10057
10057
|
|
|
@@ -10120,17 +10120,17 @@ Newsletter-specific guidelines:
|
|
|
10120
10120
|
- "Reply and let me know..."
|
|
10121
10121
|
- "Until next time..."
|
|
10122
10122
|
|
|
10123
|
-
The goal is to build a relationship with readers through valuable, authentic content.`});L0();wA();import{jsxDEV as QY,Fragment as $Vw}from"preact/jsx-dev-runtime";var AVw=Z.enum(["generating","draft","queued","published","failed"]),QVw=Z.object({id:Z.string(),subject:Z.string(),status:AVw,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),wVw=Z.object({newsletters:Z.array(QVw),totalCount:Z.number(),pagination:PA0.nullable()}),BVw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return QY($Vw,{children:[QY(dQ,{title:f,description:Y},void 0,!1,void 0,this),QY("div",{className:"newsletter-list bg-theme",children:QY("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[QY("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?QY("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):QY("div",{className:"space-y-4",children:A.map((X)=>QY(z6,{href:X.url,children:[QY(Z7,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),QY(T7,{children:QY("div",{className:"flex items-center gap-3",children:[QY(oY,{status:X.status},void 0,!1,void 0,this),QY("span",{className:"text-sm text-theme-muted",children:P8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&QY("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&QY(oq,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},R22=l1({name:"newsletter-list",description:"Newsletter list page template",schema:wVw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:BVw}});L0();wA();import{jsxDEV as eB,Fragment as HVw}from"preact/jsx-dev-runtime";var fVw=Z.enum(["generating","draft","queued","published","failed"]),YVw=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),h22=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),XVw=Z.object({id:Z.string(),subject:Z.string(),status:fVw,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(YVw).optional(),prevNewsletter:h22.nullable().optional(),nextNewsletter:h22.nullable().optional()}),ZVw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:Y,prevNewsletter:X,nextNewsletter:H})=>{let W=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=$??B,U=$?"Sent":"Created";return eB(HVw,{children:[eB(dQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),eB("section",{className:"newsletter-detail-section",children:eB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:eB("div",{className:"max-w-3xl mx-auto",children:[eB(gD,{items:W},void 0,!1,void 0,this),eB("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),eB("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[eB(oY,{status:Q},void 0,!1,void 0,this),eB("span",{children:[U,": ",P8(K,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&eB("span",{children:["Scheduled for: ",P8(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&eB(z6,{variant:"compact",className:"mb-8",children:[eB("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),eB("ul",{className:"space-y-1",children:Y.map((G)=>eB("li",{children:eB("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),eB(_9,{markdown:w},void 0,!1,void 0,this),(X??H)&&eB("nav",{className:"mt-12 pt-8 border-t border-theme",children:eB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?eB(z6,{href:X.url,variant:"compact",children:[eB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),eB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:X.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):eB("div",{},void 0,!1,void 0,this),H&&eB(z6,{href:H.url,variant:"compact",className:"md:text-right",children:[eB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),eB("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)},C22=l1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:XVw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:ZVw}});var EX0={name:"@brains/newsletter",version:"0.2.0-alpha.
|
|
10123
|
+
The goal is to build a relationship with readers through valuable, authentic content.`});L0();wA();import{jsxDEV as QY,Fragment as $Vw}from"preact/jsx-dev-runtime";var AVw=Z.enum(["generating","draft","queued","published","failed"]),QVw=Z.object({id:Z.string(),subject:Z.string(),status:AVw,excerpt:Z.string(),created:Z.string(),sentAt:Z.string().optional(),url:Z.string()}),wVw=Z.object({newsletters:Z.array(QVw),totalCount:Z.number(),pagination:PA0.nullable()}),BVw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:B,baseUrl:$="/newsletters"})=>{let f=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return QY($Vw,{children:[QY(dQ,{title:f,description:Y},void 0,!1,void 0,this),QY("div",{className:"newsletter-list bg-theme",children:QY("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[QY("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:f},void 0,!1,void 0,this),A.length===0?QY("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):QY("div",{className:"space-y-4",children:A.map((X)=>QY(z6,{href:X.url,children:[QY(Z7,{className:"text-lg",children:X.subject},void 0,!1,void 0,this),QY(T7,{children:QY("div",{className:"flex items-center gap-3",children:[QY(oY,{status:X.status},void 0,!1,void 0,this),QY("span",{className:"text-sm text-theme-muted",children:P8(X.sentAt??X.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X.excerpt&&QY("p",{className:"text-theme-muted line-clamp-2",children:X.excerpt},void 0,!1,void 0,this)]},X.id,!0,void 0,this))},void 0,!1,void 0,this),B&&B.totalPages>1&&QY(oq,{currentPage:B.currentPage,totalPages:B.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},R22=l1({name:"newsletter-list",description:"Newsletter list page template",schema:wVw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:BVw}});L0();wA();import{jsxDEV as eB,Fragment as HVw}from"preact/jsx-dev-runtime";var fVw=Z.enum(["generating","draft","queued","published","failed"]),YVw=Z.object({id:Z.string(),title:Z.string(),url:Z.string()}),h22=Z.object({id:Z.string(),subject:Z.string(),url:Z.string()}),XVw=Z.object({id:Z.string(),subject:Z.string(),status:fVw,content:Z.string(),created:Z.string(),updated:Z.string(),sentAt:Z.string().optional(),scheduledFor:Z.string().optional(),sourceEntities:Z.array(YVw).optional(),prevNewsletter:h22.nullable().optional(),nextNewsletter:h22.nullable().optional()}),ZVw=({subject:A,status:Q,content:w,created:B,sentAt:$,scheduledFor:f,sourceEntities:Y,prevNewsletter:X,nextNewsletter:H})=>{let W=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=$??B,U=$?"Sent":"Created";return eB(HVw,{children:[eB(dQ,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),eB("section",{className:"newsletter-detail-section",children:eB("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:eB("div",{className:"max-w-3xl mx-auto",children:[eB(gD,{items:W},void 0,!1,void 0,this),eB("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),eB("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[eB(oY,{status:Q},void 0,!1,void 0,this),eB("span",{children:[U,": ",P8(K,{style:"long"})]},void 0,!0,void 0,this),f&&Q==="queued"&&eB("span",{children:["Scheduled for: ",P8(f,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&eB(z6,{variant:"compact",className:"mb-8",children:[eB("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),eB("ul",{className:"space-y-1",children:Y.map((G)=>eB("li",{children:eB("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),eB(_9,{markdown:w},void 0,!1,void 0,this),(X??H)&&eB("nav",{className:"mt-12 pt-8 border-t border-theme",children:eB("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[X?eB(z6,{href:X.url,variant:"compact",children:[eB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),eB("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:X.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):eB("div",{},void 0,!1,void 0,this),H&&eB(z6,{href:H.url,variant:"compact",className:"md:text-right",children:[eB("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),eB("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)},C22=l1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:XVw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:ZVw}});var EX0={name:"@brains/newsletter",version:"0.2.0-alpha.164",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 UVw=Z.looseObject({}),GVw=Z.object({prompt:Z.string().optional(),content:Z.string().optional()});class TX0 extends sQ{entityType="newsletter";schema=Ty;adapter=x22;constructor(A={}){super("newsletter",EX0,A,UVw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new Sa0(this.logger,A)}getTemplates(){return{generation:v22,"newsletter-list":R22,"newsletter-detail":C22}}getDataSources(){return[new Ta0(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:()=>KVw(ji0,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async(w,B)=>{let $=typeof B.subject==="string"?B.subject:"",f=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:$,content:w}});return{id:!("noop"in f)&&f.data?.emailId?f.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let w=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:10}});if(w.length===0)return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:"No published posts available for newsletter"}}),{success:!0};return await A.jobs.enqueue({type:"newsletter:generation",data:{sourceEntityIds:w.map((B)=>B.id),sourceEntityType:"post",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}}),{success:!0}}catch(w){return await A.messaging.send({type:"generate:report:failure",payload:{entityType:"newsletter",error:SA(w)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let w=GVw.parse(Q),B=w.content?`Create an engaging newsletter based on this content:
|
|
10124
10124
|
|
|
10125
10125
|
${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:B,templateName:"newsletter:generation"})})}}function SX0(A={}){return new TX0(A)}wA();L0();L0();var zVw="https://api.buttondown.email/v1",qVw=Z.enum(["unactivated","regular","unsubscribed","already_subscribed"]),bVw=Z.enum(["draft","about_to_send","scheduled","sent"]),ma0=Z.looseObject({id:Z.string(),email:Z.string(),subscriber_type:qVw,metadata:Z.record(Z.string(),Z.string()).optional()}),g22=Z.looseObject({id:Z.string(),subject:Z.string(),body:Z.string().optional(),status:bVw,publish_date:Z.string().optional()}),VVw=Z.looseObject({results:Z.array(ma0),count:Z.number()}),JVw=Z.looseObject({detail:Z.string().optional(),message:Z.string().optional(),code:Z.string().optional()});class ua0 extends Error{status;code;constructor(A,Q,w){super(A);this.name="ButtondownApiError",this.status=Q,this.code=w}}class Fj{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let w=`${zVw}${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let B=await fetch(w,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!B.ok){let $=await B.json().catch(()=>({})),f=JVw.safeParse($),Y=f.success?f.data.detail??f.data.message??`HTTP ${B.status}`:`HTTP ${B.status}`,X=f.success?f.data.code:void 0;throw this.logger.error("Buttondown API error",{endpoint:A,status:B.status,code:X,error:Y}),new ua0(`Buttondown API error: ${Y}`,B.status,X)}return B.json()}async createSubscriber(A){let Q={email_address:A.email,type:this.config.doubleOptIn?"unactivated":"regular"};if(A.name)Q.metadata={name:A.name};if(A.tags&&A.tags.length>0)Q.tags=A.tags;this.logger.info("Creating subscriber",{email:A.email});try{return ma0.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch(w){if(w instanceof ua0&&w.code==="email_already_exists")return this.logger.info("Subscriber already exists",{email:A.email}),{...await this.getSubscriberByEmail(A.email),subscriber_type:"already_subscribed"};throw w}}async getSubscriberByEmail(A){return ma0.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 w=Q.toString(),B=w?`/subscribers?${w}`:"/subscribers";return VVw.parse(await this.request(B))}async createEmail(A){let Q={subject:A.subject,body:A.body,status:A.status??"draft"};if(A.publish_date)Q.publish_date=A.publish_date;return this.logger.info("Creating email",{subject:A.subject,status:A.status??"draft"}),g22.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return g22.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}wA();L0();var y22=Z.string().email({pattern:Z.regexes.html5Email}),IVw=Z.object({email:y22.describe("Email address to subscribe"),name:Z.string().optional().describe("Subscriber name (optional)"),tags:Z.array(Z.string()).optional().describe("Tags to apply to subscriber (optional)")}),FVw=Z.object({email:y22.describe("Email address to unsubscribe")}),kVw=Z.object({type:Z.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:Z.number().optional().describe("Maximum number of results")});function E22(A,Q,w){let B=new Fj(Q,w);return[x6(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",IVw,async($)=>{try{let f=await B.createSubscriber({email:$.email,...$.name&&{name:$.name},...$.tags&&{tags:$.tags}}),Y=f.subscriber_type==="already_subscribed";return k5({subscriberId:f.id,email:f.email,status:f.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${$.email} is already subscribed`:`Subscribed ${$.email} successfully`)}catch(f){return j7(SA(f))}}),x6(A,"unsubscribe","Unsubscribe an email address from the newsletter.",FVw,async($)=>{try{return await B.unsubscribe($.email),k5({email:$.email},`Unsubscribed ${$.email} successfully`)}catch(f){return j7(SA(f))}}),x6(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",kVw,async($)=>{try{let f=await B.listSubscribers({...$.type&&{type:$.type},...$.limit&&{limit:$.limit}});return k5({subscribers:f.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:f.count},`Found ${f.count} subscribers`)}catch(f){return j7(SA(f))}})]}async function T22(A,Q,w,B){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let $=await w.getEntity({entityType:"post",id:A.entityId});if(!$)return{success:!1,error:`Post ${A.entityId} not found`};B.info("Auto-sending newsletter for published post",{postId:$.id,title:$.metadata.title});try{let f=await Q.createEmail({subject:$.metadata.title,body:$.content,status:"about_to_send"});return B.info("Newsletter sent for post",{postId:$.id,emailId:f.id}),{success:!0,emailId:f.id}}catch(f){let Y=SA(f);return B.error("Failed to send newsletter for post",{postId:$.id,error:Y}),{success:!1,error:Y}}}var LVw=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class mX0 extends Aw{constructor(A={}){super("buttondown",EX0,A,LVw)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new Fj({apiKey:this.config.apiKey,doubleOptIn:this.config.doubleOptIn},this.logger);if(A.messaging.subscribe("buttondown:send",async(w)=>{try{return{success:!0,data:{emailId:(await Q.createEmail({subject:w.payload.subject,body:w.payload.content,status:"about_to_send"})).id}}}catch(B){return this.logger.error("Buttondown send failed",{error:SA(B)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{let B=await T22(w.payload,Q,A.entityService,this.logger);if(!B.success)return this.logger.error("Buttondown auto-send failed",{entityId:w.payload.entityId,error:B.error}),{success:!1,error:B.error};return{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return E22(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 uX0(A={}){return new mX0(A)}var _Vw=Z.object({apiKey:Z.string().optional().describe("Buttondown API key"),doubleOptIn:Z.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:Z.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function S22(A={}){let Q=_Vw.safeParse(A);if(!Q.success)throw new Az("newsletter",Q.error.issues.map((B)=>({path:B.path.map(String).join("."),code:B.code,message:B.message})));let w=Q.data;return[SX0({}),uX0({...w.apiKey!==void 0&&{apiKey:w.apiKey},...w.doubleOptIn!==void 0&&{doubleOptIn:w.doubleOptIn},...w.autoSendOnPublish!==void 0&&{autoSendOnPublish:w.autoSendOnPublish}})]}wA();L0();import{existsSync as TVw,mkdirSync as SVw,writeFileSync as mVw}from"fs";import{join as zb}from"path";L0();var ca0=Z.object({baseFolder:Z.string().default("_obsidian")});function la0(A){return typeof A==="object"&&A!==null}function lo(A){if(!la0(A))return;let Q=A.def;return la0(Q)?Q:void 0}function m22(A){let Q=lo(A)?.type;return typeof Q==="string"?Q:void 0}function NVw(A){return typeof A==="function"?A():A}function PVw(A){let Q=A,w=!0,B=void 0,$=!1,f=!0;while(f){f=!1;let X=lo(Q),H=m22(Q);if(H==="optional"||H==="nullable"){w=!1,Q=X?.innerType,f=!0;continue}if(H==="default")w=!1,$=!0,B=NVw(X?.defaultValue),Q=X?.innerType,f=!0}let Y={inner:Q,required:w};if($)Y.defaultValue=B;return Y}function jVw(A){let w=lo(A)?.entries;if(!la0(w))return;let B=Object.values(w);if(!B.every(($)=>typeof $==="string"))return;return B}function MVw(A){let Q=lo(A),w=Q?.values;if(Array.isArray(w))return w[0];return Q?.value}function u22(A){let Q=m22(A);if(Q==="enum"){let w=jVw(A);return w?{type:"enum",enumValues:w}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:MVw(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 w=lo(A);return u22(w?.out)}return{type:"unknown"}}function c22(A){let Q=[];for(let[w,B]of Object.entries(A.shape)){let{inner:$,required:f,defaultValue:Y}=PVw(B),X=u22($),H={name:w,type:X.type,required:f},W=Y!==void 0?Y:X.defaultValue;if(W!==void 0)H.defaultValue=W;if(X.enumValues)H.enumValues=X.enumValues;Q.push(H)}return Q}function xVw(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 l22(A,Q,w=""){let B=["---"];for(let $ of Q){let f=xVw($,A);if(f==="")B.push(`${$.name}:`);else B.push(`${$.name}: ${f}`)}if(B.push("---"),B.push(""),w)B.push(w);else B.push("<!-- Write your content here -->"),B.push("");return B.join(`
|
|
10126
10126
|
`)}Dv();var OVw={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function vVw(A){let Q={name:A.name,id:A.name,type:OVw[A.type]};if(A.type==="enum"&&A.enumValues){let w={};A.enumValues.forEach((B,$)=>{w[String($)]=B}),Q.options=w}return Q}function p22(A,Q){let w={filesPaths:A,fields:Q.map(vVw)};return`---
|
|
10127
10127
|
${Gv(w)}---
|
|
10128
|
-
`}D2();Dv();var RVw=new Set(["entityType"]),hVw={base:"Notes"},CVw=new Set(["note"]);function gVw(A){let Q=["file.name"];for(let w of A)if(!RVw.has(w.name))Q.push(w.name);return Q}function yVw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function i22(A,Q){let w=hVw[A]??x9A(A),B=yVw(Q),$=gVw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let X={filters:{and:[CVw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:Gv(X),hasStatus:B}}function d22(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return Gv(w)}function n22(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B.entityType}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q},'status != "published"']},views:[{type:"table",name:"Pipeline",groupBy:{property:"status",direction:"ASC"},order:["file.name","file.folder","status"]}]};return Gv(w)}var r22={name:"@brains/obsidian-vault",version:"0.2.0-alpha.
|
|
10128
|
+
`}D2();Dv();var RVw=new Set(["entityType"]),hVw={base:"Notes"},CVw=new Set(["note"]);function gVw(A){let Q=["file.name"];for(let w of A)if(!RVw.has(w.name))Q.push(w.name);return Q}function yVw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function i22(A,Q){let w=hVw[A]??x9A(A),B=yVw(Q),$=gVw(Q),f=[{type:"table",name:`All ${w}`,order:$}];if(B)f.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:$});let X={filters:{and:[CVw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:f};return{filename:`${w}.base`,content:Gv(X),hasStatus:B}}function d22(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return Gv(w)}function n22(A){if(A.length===0)return null;let Q=A.map((B)=>`file.inFolder("${B.entityType}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q},'status != "published"']},views:[{type:"table",name:"Pipeline",groupBy:{property:"status",direction:"ASC"},order:["file.name","file.folder","status"]}]};return Gv(w)}var r22={name:"@brains/obsidian-vault",version:"0.2.0-alpha.164",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 uVw={mkdir:SVw,writeFile:mVw,existsFile:TVw},cVw=Z.object({entityTypes:Z.array(Z.string()).optional().describe("Entity types to generate templates for (default: all)")});class pa0 extends Aw{deps;constructor(A={},Q={}){super("obsidian-vault",r22,A,ca0);this.deps={...uVw,...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[x6(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",cVw,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),B=Q?w.filter((V)=>Q.includes(V)):w,$=zb(A.dataDir,this.config.baseFolder),f=zb($,"templates"),Y=zb($,"fileClasses"),X=zb($,"bases");this.deps.mkdir(f,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(X,{recursive:!0});let H=[],W=[],K=[],U=[],G=[],q=[];for(let V of B){let k=A.entities.getEffectiveFrontmatterSchema(V);if(!k){this.logger.debug(`Skipping ${V}: no frontmatter schema`),W.push(V);continue}let N=c22(k),L=A.entities.getAdapter(V),O=L?.isSingleton===!0,v=p22(V,N);if(this.deps.writeFile(zb(Y,`${V}.md`),v),K.push(V),O){G.push(V),this.logger.debug(`Generated fileClass (singleton): ${V}`);continue}let h=L?.getBodyTemplate()??"",j=l22(V,N,h);this.deps.writeFile(zb(f,`${V}.md`),j),H.push(V);let E=i22(V,N),S=zb(X,E.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,E.content),U.push(V),this.logger.debug(`Generated base: ${E.filename}`);if(E.hasStatus)q.push({entityType:V,fields:N});this.logger.debug(`Generated template + fileClass: ${V}`)}let b=d22(G);if(b){let V=zb(X,"Settings.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,b),U.push("Settings"),this.logger.debug("Generated Settings.base")}let J=n22(q);if(J){let V=zb(X,"Pipeline.base");if(!this.deps.existsFile(V))this.deps.writeFile(V,J),U.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${H.length} templates, ${K.length} fileClasses, ${U.length} bases (${W.length} skipped)`),k5({generated:H,skipped:W,fileClasses:K,bases:U})}catch(w){return this.logger.error("Failed to sync",{error:w}),j7(w instanceof Error?w.message:"Unknown error")}}}function ia0(A={},Q){return new pa0(A,Q)}T6();wA();wA();D2();q5();wA();L0();var cX0=Z.enum(["draft","active","archived"]),lX0=Z.enum(["anchor","trusted","public"]),pX0=Z.enum(["agent-confirmed","manual"]),lVw=Z.enum(["draft","active","archived"]),pVw=Z.enum(["anchor","trusted","public"]),iVw=Z.enum(["agent-confirmed","manual"]),Z3=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),qb=Z.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,Z.string().min(1).optional()),da0=Z.object({event:Z.string().min(1),target:Z.string().min(1),operatorAction:Z.boolean().optional(),label:qb,description:qb,operatorDescription:qb}),na0=Z.object({id:Z.string().min(1),title:Z.string().min(1),prompt:qb,requiredDetails:Z.array(Z.string().min(1)).default([]),instructions:Z.array(Z.string().min(1)).default([]),doneWhen:Z.array(Z.string().min(1)).default([]),transitions:Z.array(da0).default([])}),iX0=Z.object({purpose:Z.string().min(1),operatingRules:Z.array(Z.string().min(1)).default([]),initialState:Z.string().min(1),states:Z.array(na0).min(1),finalStates:Z.array(Z.string().min(1)).min(1),nextPrompts:Z.array(Z.string().min(1)).default([])}),Sy=Z.object({title:Z.string(),status:cX0.default("active"),audience:lX0.default("anchor"),trigger:Z3.optional(),lifecycle:Z3.optional(),once:Z.boolean().optional(),starterText:Z3.optional(),description:Z3.optional(),starterPrompt:Z3.optional(),completionMode:pX0.default("agent-confirmed")}),o22=Z.object({title:Z.string(),status:cX0,audience:lX0,trigger:Z3.optional(),lifecycle:Z3.optional(),once:Z.boolean().optional(),starterText:Z3.optional(),description:Z3.optional(),starterPrompt:Z3.optional(),completionMode:pX0}),dVw=Z.object({title:Z.string(),status:lVw,audience:pVw,trigger:qb.optional(),lifecycle:qb.optional(),once:Z.boolean().optional(),starterText:qb.optional(),description:qb.optional(),starterPrompt:qb.optional(),completionMode:iVw}),my=PQ.extend({entityType:Z.literal("playbook"),metadata:dVw});class dX0 extends $6{constructor(){super(iX0,{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:ra0,parser:oa0},{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:nVw,parser:rVw},{key:"label",label:"Label",type:"custom",formatter:ra0,parser:oa0},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:ra0,parser:oa0}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var po=new dX0;function ra0(A){return typeof A==="string"?A:""}function oa0(A){let Q=A.trim();return Q.length>0?Q:void 0}function nVw(A){return typeof A==="boolean"?String(A):""}function rVw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function sa0(A){let Q=[],w=new Set,B=new Set;for(let $ of A.states){if(w.has($.id))B.add($.id);w.add($.id)}if(!w.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let $ of B)Q.push(`Duplicate playbook state id '${$}'.`);for(let $ of A.finalStates)if(!w.has($))Q.push(`Playbook final state '${$}' is not defined.`);for(let $ of A.states)for(let f of $.transitions)if(!w.has(f.target))Q.push(`Playbook transition '${$.id}' -> '${f.target}' targets an undefined state.`);for(let $ of oVw(A,w))Q.push(`Playbook state '${$}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function uy(A){let Q=sa0(A);if(!Q.valid)throw Error(Q.errors.join(`
|
|
10129
10129
|
`))}function oVw(A,Q){if(!Q.has(A.initialState))return[];let w=new Set,B=[A.initialState];while(B.length>0){let $=B.shift();if(!$||w.has($))continue;w.add($);let f=A.states.find((Y)=>Y.id===$);if(!f)continue;for(let Y of f.transitions)if(Q.has(Y.target)&&!w.has(Y.target))B.push(Y.target)}return A.states.map(($)=>$.id).filter(($)=>!w.has($))}class rX0 extends E2{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:my,frontmatterSchema:Sy})}createPlaybookContent(A,Q){return this.buildMarkdown(po.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,Sy),w=this.extractBody(A).trim(),B=sVw(w)?aVw(w):po.parse(w);return uy(B),{frontmatter:Sy.parse(Q),body:B,bodyMarkdown:w}}fromMarkdown(A){let{frontmatter:Q}=this.parsePlaybookContent(A);return{content:A,entityType:"playbook",metadata:{title:Q.title,status:Q.status,audience:Q.audience,...Q.trigger?{trigger:Q.trigger}:{},...Q.lifecycle?{lifecycle:Q.lifecycle}:{},...Q.once!==void 0?{once:Q.once}:{},...Q.starterText?{starterText:Q.starterText}:{},...Q.description?{description:Q.description}:{},...Q.starterPrompt?{starterPrompt:Q.starterPrompt}:{},completionMode:Q.completionMode}}}}var kj=new rX0;function sVw(A){return/^##\s+Steps\s*$/im.test(A)}function aVw(A){let Q=tVw(aa0(A,"Steps"));if(Q.length===0)throw Error("Playbook must declare at least one step.");let w=Q.map((B,$)=>{let f=$===Q.length-1;if(!f&&B.doneWhen.length===0&&B.choices.length===0&&!B.skip)throw Error(`Playbook step '${B.title}' must declare Done when, Choices, or Skip.`);return{id:B.id,title:B.title,...B.prompt?{prompt:B.prompt}:{},requiredDetails:B.requiredDetails,instructions:B.instructions,doneWhen:B.doneWhen,transitions:[...B.doneWhen.length>0&&!f?[{event:"NEXT",target:Q[$+1]?.id??B.id}]:[],...B.choices.map((Y,X)=>({event:`CHOICE_${X+1}`,target:H1(Y.target),operatorAction:!0,label:Y.label})),...B.skip?[{event:"SKIP",target:H1(B.skip.target),operatorAction:!0,label:B.skip.label}]:[]]}});return{purpose:eVw(A,"Purpose"),operatingRules:s22(A,"Operating Rules"),initialState:Q[0]?.id??"",states:w,finalStates:[Q.at(-1)?.id??""],nextPrompts:s22(A,"Next Prompts")}}function tVw(A){let Q=[],w;for(let B of A.split(/\r?\n/)){let $=/^###\s+(.+?)\s*$/.exec(B);if($){w={title:$[1]??"",content:[]},Q.push(w);continue}w?.content.push(B)}return Q.map((B)=>{let $=B.content.join(`
|
|
10130
10130
|
`);return{title:B.title,id:H1(B.title),...a22($,"Say")?{prompt:a22($,"Say")}:{},requiredDetails:nX0($,"Required details"),instructions:nX0($,"To do"),doneWhen:nX0($,"Done when"),choices:AJw($,"Choices"),...t22($)?{skip:t22($)}:{}}})}function aa0(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((f)=>f.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if(B===-1)return"";let $=[];for(let f of w.slice(B+1)){if(/^##\s+/.test(f))break;$.push(f)}return $.join(`
|
|
10131
10131
|
`).trim()}function eVw(A,Q){return aa0(A,Q).split(/\r?\n/).map((w)=>w.trim()).filter((w)=>w.length>0&&!w.startsWith("#")).join(`
|
|
10132
10132
|
`).trim()}function s22(A,Q){return e22(aa0(A,Q))}function a22(A,Q){return new RegExp(`^${wJw(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function nX0(A,Q){let w=A.split(/\r?\n/),B=w.findIndex((f)=>f.trim().toLowerCase()===`${Q.toLowerCase()}:`);if(B===-1)return[];let $=[];for(let f of w.slice(B+1)){let Y=f.trim();if(Y.length===0)continue;if(/^[A-Za-z][A-Za-z ]+:/.test(Y)||/^#{1,6}\s+/.test(Y))break;$.push(f)}return e22($.join(`
|
|
10133
|
-
`))}function AJw(A,Q){return nX0(A,Q).map(QJw)}function QJw(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 t22(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 e22(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function wJw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}L0();var oX0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));var sX0={name:"@brains/playbooks",version:"0.2.0-alpha.
|
|
10133
|
+
`))}function AJw(A,Q){return nX0(A,Q).map(QJw)}function QJw(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 t22(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 e22(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function wJw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}L0();var oX0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));var sX0={name:"@brains/playbooks",version:"0.2.0-alpha.164",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 $Jw="playbook";class ta0 extends sQ{entityType=$Jw;schema=my;adapter=kj;constructor(A={}){super("playbook",sX0,A,oX0)}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 ea0(A={}){return new ta0(A)}T6();wA();L0();yX();Ou();function aX0(A,Q){return A.length===Q.length&&A.every((w,B)=>w===Q[B])}function At0(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function tX0(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&aX0(w.goal,A.doneWhen)&&w.met)}function fJw(A,Q,w){return r1.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map((B)=>{let $=Q.finalStates.includes(B.id);return[B.id,{...$?{type:"final"}:{},...$?{}:{on:Object.fromEntries(B.transitions.map((f)=>[f.event,{target:f.target,...At0(B,f.event)?{guard:()=>tX0(B,w)}:{}}]))}}]}))})}function Qt0(A,Q){let w=fJw(Q.playbookId,A,Q);return r1.createActor(w,{snapshot:w.resolveState({value:Q.currentState})})}function YJw(A,Q,w){let B=Qt0(Q,A);B.start();let $=B.getSnapshot().can({type:w});return B.stop(),$}function cy(A,Q,w){return w.transitions.filter((B)=>YJw(A,Q,B.event))}function io(A,Q,w){let B=new Set(cy(A,Q,w).map(($)=>`${$.event}\x00${$.target}`));return w.transitions.filter(($)=>!B.has(`${$.event}\x00${$.target}`))}function AQ2(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}function Lj(A,Q){return A.states.find((w)=>w.id===Q)}function _j(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function QQ2(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find((B)=>B.stateId===Q.id&&aX0(B.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}function wQ2(A,Q,w){let B=cy(A,Q,w),$=B.filter((H)=>H.operatorAction!==!0),f=B.filter((H)=>H.operatorAction===!0),Y=io(A,Q,w),X=A.gateVerdicts.find((H)=>H.stateId===w.id&&aX0(H.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((H)=>`- ${H}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((H)=>`- ${H}`):["- none"],"Goal status:",X?`- ${X.met?"Met":"Not yet met"}: ${X.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...$.length>0?$.map((H)=>_j(H)):["- none"],"Available operator actions:",...f.length>0?f.map((H)=>_j(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>_j(H)):["- none"]].join(`
|
|
10134
10134
|
`)}function BQ2(A){let{run:Q,body:w,state:B,playbookTitle:$}=A,f=cy(Q,w,B),Y=f.filter((V)=>V.operatorAction!==!0),X=f.filter((V)=>V.operatorAction===!0),H=io(Q,w,B),W=Y.map((V)=>_j(V)).join(`
|
|
10135
10135
|
`),K=X.map((V)=>_j(V)).join(`
|
|
10136
10136
|
`),U=H.map((V)=>_j(V)).join(`
|
|
@@ -10204,9 +10204,9 @@ ${Object.entries(A).map(([w,B])=>`- ${w}: playbookId=${B.playbookId}, trigger=${
|
|
|
10204
10204
|
${A.guidance}`:$}}function zQ2(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:FJw(Q.data)}))}}function FJw(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function kJw(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 LJw(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function qQ2(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function bQ2(A,Q){let w=A.filter(Q),B=w.filter(($)=>$.status==="active"||$.status==="offered");return Xt0(B)??Xt0(w)}function Xt0(A){return[...A].sort((Q,w)=>(w.completedAt??w.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function _Jw(A){return{async evaluate(Q){let w=Q.goal.join(`
|
|
10205
10205
|
`),B=await A.entityService.search({query:w,options:{limit:8,excludeTypes:["playbook"],visibilityScope:Y$("anchor")}}),$=NJw(Q,B),{verdict:f}=await A.judge({instruction:"Decide whether the playbook goal is satisfied by the supplied current-run runtime evidence and KB excerpts. Current-run runtime evidence is authoritative for playbook completion; use KB excerpts as supporting context, not to override clear runtime evidence from this run. Return met=true only when the outcome clearly holds. If evidence is missing or ambiguous, return met=false with a short reason.",material:$,schema:qJw});return f}}}function NJw(A,Q){return["## Playbook run",`runId: ${A.run.id}`,`playbookId: ${A.run.playbookId}`,`currentState: ${A.state.id} (${A.state.title})`,"","## State instructions",...A.state.instructions.map((w)=>`- ${w}`),"","## Done When goal",...A.goal.map((w)=>`- ${w}`),"","## Runtime evidence",...A.evidence.length>0?A.evidence.map((w,B)=>PJw(B+1,w)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map((w,B)=>jJw(B+1,w)):["No relevant KB excerpts found."]].join(`
|
|
10206
10206
|
`)}function PJw(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${JQ2(Q.data)}`}function jJw(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${IQ2(Q.entity.content,1200)}`,`Metadata: ${JQ2(Q.entity.metadata)}`].join(`
|
|
10207
|
-
`)}function JQ2(A){try{return IQ2(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function IQ2(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var MJw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function Ht0(A={},Q={}){return new Zt0(A,Q)}T6();wA();L0();import{readFile as OJw}from"fs/promises";import{join as vJw}from"path";var FQ2={name:"@brains/rover-onboarding",version:"0.2.0-alpha.163",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 RJw=Z.object({enabled:Z.boolean().default(!1)}).strict(),kQ2=[{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 LQ2 extends Aw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",FQ2,A,RJw)}async onReady(A){if(!this.config.enabled)return;for(let Q of kQ2)await this.seedPlaybookIfMissing(A,Q);for(let Q of kQ2){if(!Q.starter)continue;await A.messaging.send({type:Kx,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let B=await OJw(vJw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:B}})}}function _Q2(A={}){return new LQ2(A)}wA();L0();L0();wA();var Wt0=Z.enum(["new","planned","in-progress","done","declined"]),Kt0=Z.enum(["low","medium","high","critical"]),hJw=Z.enum(["new","planned","in-progress","done","declined"]),CJw=Z.enum(["low","medium","high","critical"]),no=Z.object({title:Z.string(),status:Wt0,priority:Kt0.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),gJw=Z.object({title:Z.string(),status:Wt0,priority:Kt0,requested:Z.number().int(),slug:Z.string()}),yJw=Z.object({title:Z.string(),status:hJw,priority:CJw,requested:Z.number().int(),slug:Z.string()}),ro=PQ.extend({entityType:Z.literal("wish"),metadata:yJw});L0();var Ut0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));wA();D2();class oo extends E2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:ro,frontmatterSchema:no})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,no);return{frontmatter:no.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=H1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var NQ2=new oo;D2();D2();async function PQ2(A,Q){let w=`${Q.title}: ${Q.description}`,$=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let f=H1(Q.title);return A.getEntity({entityType:"wish",id:f})}class wZ0{logger;context;adapter=new oo;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let B=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",f=await PQ2({search:(W)=>this.context.entityService.search(W),getEntity:(W)=>this.context.entityService.getEntity(W),similarityThreshold:0.85},{title:B,description:$});if(f){let{frontmatter:W,description:K}=this.adapter.parseWishContent(f.content),U=W.requested+1,G=this.adapter.createWishContent({...W,requested:U},K);return await this.context.entityService.updateEntity({entity:{...f,content:G,metadata:{...f.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:U}),{success:!0,entityId:f.id,existed:!0,requested:U}}let Y=H1(B),X=A.options?.priority??"medium",H=this.adapter.createWishContent({title:B,status:"new",priority:X,requested:1},$);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,metadata:{title:B,status:"new",priority:X,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:B}),{success:!0,entityId:Y,existed:!1,requested:1}}}var jQ2={critical:0,high:1,medium:2,low:3};function MQ2(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return jQ2[Q.metadata.priority]-jQ2[w.metadata.priority]})}var xQ2={name:"@brains/wishlist",version:"0.2.0-alpha.163",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 TJw=Z.object({items:Z.array(Z.object({name:Z.string(),count:Z.number()}))}),SJw="wish";class OQ2 extends sQ{entityType=SJw;schema=ro;adapter=NQ2;constructor(A={}){super("wishlist",xQ2,A,Ut0)}async interceptCreate(A,Q,w){let B=await new wZ0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!B.success)return{kind:"handled",result:{success:!1,error:B.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...B.entityId?{entityId:B.entityId}:{},status:B.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",group:"knowledge",section:"secondary",priority:30,rendererName:"ListWidget",digestProvider:(w)=>{let{items:B}=TJw.parse(w),$=B[0];return{digest:$?[{label:"Top wish",value:`${$.name} \xB7 \xD7${$.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return MQ2(w),{items:w.map((B)=>({id:B.id,name:B.metadata.title,count:B.metadata.requested,priority:B.metadata.priority,status:B.metadata.status}))}}}}),{success:!0}});let Q=new wZ0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(w)=>w})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function mJw(A={}){return new OQ2(A)}var BZ0=mJw;wA();wA();L0();var so=Z.object({title:Z.string(),target:Z.string()}),vQ2=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),ao=PQ.extend({entityType:Z.literal("prompt"),metadata:vQ2});wA();D2();class Gt0 extends E2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:ao,frontmatterSchema:so})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,so);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,so),w=H1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var Dt0=new Gt0;var RQ2={name:"@brains/prompt",version:"0.2.0-alpha.163",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 cJw="prompt";class zt0 extends sQ{entityType=cJw;schema=ao;adapter=Dt0;constructor(){super("prompt",RQ2,{},P7)}getEntityTypeConfig(){return{embeddable:!1}}}function Pj(){return new zt0}wA();L0();L0();class $Z0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let w=new URL(`${this.baseUrl}/search/photos`);w.searchParams.set("query",A),w.searchParams.set("page",String(Q.page)),w.searchParams.set("per_page",String(Q.perPage));let B=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!B.ok)throw Error(`Unsplash API error: ${B.status} ${B.statusText}`);let $=pJw.parse(await B.json());return{photos:$.results.map(iJw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var lJw=Z.looseObject({id:Z.string(),description:Z.string().nullable(),alt_description:Z.string().nullable(),urls:Z.looseObject({raw:Z.url(),full:Z.url(),regular:Z.url(),small:Z.url(),thumb:Z.url()}),links:Z.looseObject({html:Z.url(),download_location:Z.url()}),user:Z.looseObject({name:Z.string(),links:Z.looseObject({html:Z.url()})}),width:Z.number().int().nonnegative(),height:Z.number().int().nonnegative()}),pJw=Z.looseObject({total:Z.number().int().nonnegative(),total_pages:Z.number().int().nonnegative(),results:Z.array(lJw)});function iJw(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}}L0();async function fZ0(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return!1;return await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}}),!0}var dJw={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},nJw={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.url().describe("Photographer profile URL for attribution"),sourceUrl:Z.url().describe("Photo page URL on provider"),imageUrl:Z.url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")},rJw=Z.object({query:Z.string(),perPage:Z.number().min(1).max(30).default(10),page:Z.number().min(1).default(1)}),oJw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});function hQ2(A,Q){return[sJw(A,Q),aJw(A,Q)]}function sJw(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:dJw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=rJw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(B.data.query,{page:B.data.page,perPage:B.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function aJw(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:nJw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=oJw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:H,imageUrl:W,title:K,alt:U,targetEntityType:G,targetEntityId:q}=B.data,b={photographerName:Y,photographerUrl:X,sourceUrl:H},J=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:W}}}});if(J[0]){let N={imageEntityId:J[0].id,alreadyExisted:!0,attribution:b};if(G&&q)N.coverSet=await fZ0(Q.entityService,G,q,J[0].id);return{success:!0,data:N}}let V=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:H,imageUrl:W,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...G!==void 0?{targetEntityType:G}:{},...q!==void 0?{targetEntityId:q}:{}}}),k={imageEntityId:$,alreadyExisted:!1,attribution:b,jobId:V,status:"generating"};if(G&&q)k.coverSet=!1;return{success:!0,data:k}}}}wA();L0();_4();var tJw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});class qt0 extends ew{deps;constructor(A,Q){super(A,{schema:tJw,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress(w,{progress:35,message:"Downloading stock photo"});let B=await this.deps.fetchImage(A.imageUrl),$=A.title??`Stock photo ${A.photoId}`,f=dX.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),X={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(X.coverSet=await fZ0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!X.coverSet)X.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),X}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}_4();var CQ2={name:"@brains/stock-photo",version:"0.2.0-alpha.163",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 AIw=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class bt0 extends Aw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",CQ2,A,AIw);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=hQ2(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??pH,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new qt0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??pH}))}createProvider(){return new $Z0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function Vt0(A={},Q={}){return new bt0(A,Q)}wA();L0();wA();wA();L0();var gQ2=Z.enum(["ai","foundation","work"]),yQ2=Z.object({suffix:gQ2,title:Z.string(),body:Z.string(),linkLabel:Z.string(),linkHref:Z.string()}),to=Z.object({eyebrow:Z.string(),headline:Z.string(),cards:Z.array(yQ2).min(1)}),Jt0=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),QIw=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),eo=PQ.extend({entityType:Z.literal("ecosystem-section"),metadata:QIw});class EQ2 extends E2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:eo,frontmatterSchema:Jt0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var It0=new EQ2;L0();function wIw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function Ft0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function As(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function YZ0(A){let Q=wIw(A),B=Ft0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return to.parse({eyebrow:Ft0(Q,"Eyebrow"),headline:Ft0(Q,"Headline"),cards:B.map(($)=>({suffix:As($,"Suffix"),title:As($,"Title"),body:As($,"Body"),linkLabel:As($,"Link Label"),linkHref:As($,"Link Href")}))})}function TQ2(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,w)=>[`### Card ${w+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
|
|
10207
|
+
`)}function JQ2(A){try{return IQ2(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function IQ2(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var MJw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function Ht0(A={},Q={}){return new Zt0(A,Q)}T6();wA();L0();import{readFile as OJw}from"fs/promises";import{join as vJw}from"path";var FQ2={name:"@brains/rover-onboarding",version:"0.2.0-alpha.164",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 RJw=Z.object({enabled:Z.boolean().default(!1)}).strict(),kQ2=[{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 LQ2 extends Aw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",FQ2,A,RJw)}async onReady(A){if(!this.config.enabled)return;for(let Q of kQ2)await this.seedPlaybookIfMissing(A,Q);for(let Q of kQ2){if(!Q.starter)continue;await A.messaging.send({type:Kx,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let B=await OJw(vJw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:B}})}}function _Q2(A={}){return new LQ2(A)}wA();L0();L0();wA();var Wt0=Z.enum(["new","planned","in-progress","done","declined"]),Kt0=Z.enum(["low","medium","high","critical"]),hJw=Z.enum(["new","planned","in-progress","done","declined"]),CJw=Z.enum(["low","medium","high","critical"]),no=Z.object({title:Z.string(),status:Wt0,priority:Kt0.default("medium"),requested:Z.number().int().default(1),declinedReason:Z.string().optional()}),gJw=Z.object({title:Z.string(),status:Wt0,priority:Kt0,requested:Z.number().int(),slug:Z.string()}),yJw=Z.object({title:Z.string(),status:hJw,priority:CJw,requested:Z.number().int(),slug:Z.string()}),ro=PQ.extend({entityType:Z.literal("wish"),metadata:yJw});L0();var Ut0=Z.object({}).catchall(Z.unknown()).transform(()=>({}));wA();D2();class oo extends E2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:ro,frontmatterSchema:no})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,no);return{frontmatter:no.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=H1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var NQ2=new oo;D2();D2();async function PQ2(A,Q){let w=`${Q.title}: ${Q.description}`,$=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if($&&$.score>=A.similarityThreshold)return $.entity;let f=H1(Q.title);return A.getEntity({entityType:"wish",id:f})}class wZ0{logger;context;adapter=new oo;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let B=A.title??A.prompt??"Untitled wish",$=A.content??A.prompt??"",f=await PQ2({search:(W)=>this.context.entityService.search(W),getEntity:(W)=>this.context.entityService.getEntity(W),similarityThreshold:0.85},{title:B,description:$});if(f){let{frontmatter:W,description:K}=this.adapter.parseWishContent(f.content),U=W.requested+1,G=this.adapter.createWishContent({...W,requested:U},K);return await this.context.entityService.updateEntity({entity:{...f,content:G,metadata:{...f.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:f.id,requested:U}),{success:!0,entityId:f.id,existed:!0,requested:U}}let Y=H1(B),X=A.options?.priority??"medium",H=this.adapter.createWishContent({title:B,status:"new",priority:X,requested:1},$);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,metadata:{title:B,status:"new",priority:X,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:B}),{success:!0,entityId:Y,existed:!1,requested:1}}}var jQ2={critical:0,high:1,medium:2,low:3};function MQ2(A){A.sort((Q,w)=>{let B=w.metadata.requested-Q.metadata.requested;if(B!==0)return B;return jQ2[Q.metadata.priority]-jQ2[w.metadata.priority]})}var xQ2={name:"@brains/wishlist",version:"0.2.0-alpha.164",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 TJw=Z.object({items:Z.array(Z.object({name:Z.string(),count:Z.number()}))}),SJw="wish";class OQ2 extends sQ{entityType=SJw;schema=ro;adapter=NQ2;constructor(A={}){super("wishlist",xQ2,A,Ut0)}async interceptCreate(A,Q,w){let B=await new wZ0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!B.success)return{kind:"handled",result:{success:!1,error:B.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...B.entityId?{entityId:B.entityId}:{},status:B.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"top-wishes",pluginId:this.id,title:"Top Wishes",group:"knowledge",section:"secondary",priority:30,rendererName:"ListWidget",digestProvider:(w)=>{let{items:B}=TJw.parse(w),$=B[0];return{digest:$?[{label:"Top wish",value:`${$.name} \xB7 \xD7${$.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return MQ2(w),{items:w.map((B)=>({id:B.id,name:B.metadata.title,count:B.metadata.requested,priority:B.metadata.priority,status:B.metadata.status}))}}}}),{success:!0}});let Q=new wZ0(this.logger,A);A.jobs.registerHandler("wish:create",{process:Q.process.bind(Q),validateAndParse:(w)=>w})}async getInstructions(){return"Wish entities record explicitly requested capabilities or desired end states whose literal completion is outside the available toolset. They may capture outcomes the assistant can advise about but cannot directly perform. They track demand, priority, and status for future capability planning; they are not a substitute for first-class entities that already support the requested action. To show the whole wishlist, call system_list once with entityType wish and omit status; only include status when the user asks for a specific wish status."}}function mJw(A={}){return new OQ2(A)}var BZ0=mJw;wA();wA();L0();var so=Z.object({title:Z.string(),target:Z.string()}),vQ2=Z.object({title:Z.string(),target:Z.string(),slug:Z.string().optional()}),ao=PQ.extend({entityType:Z.literal("prompt"),metadata:vQ2});wA();D2();class Gt0 extends E2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:ao,frontmatterSchema:so})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,so);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,so),w=H1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var Dt0=new Gt0;var RQ2={name:"@brains/prompt",version:"0.2.0-alpha.164",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 cJw="prompt";class zt0 extends sQ{entityType=cJw;schema=ao;adapter=Dt0;constructor(){super("prompt",RQ2,{},P7)}getEntityTypeConfig(){return{embeddable:!1}}}function Pj(){return new zt0}wA();L0();L0();class $Z0{apiKey;fetchFn;baseUrl="https://api.unsplash.com";constructor(A,Q){this.apiKey=A,this.fetchFn=Q}async searchPhotos(A,Q){let w=new URL(`${this.baseUrl}/search/photos`);w.searchParams.set("query",A),w.searchParams.set("page",String(Q.page)),w.searchParams.set("per_page",String(Q.perPage));let B=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!B.ok)throw Error(`Unsplash API error: ${B.status} ${B.statusText}`);let $=pJw.parse(await B.json());return{photos:$.results.map(iJw),total:$.total,totalPages:$.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var lJw=Z.looseObject({id:Z.string(),description:Z.string().nullable(),alt_description:Z.string().nullable(),urls:Z.looseObject({raw:Z.url(),full:Z.url(),regular:Z.url(),small:Z.url(),thumb:Z.url()}),links:Z.looseObject({html:Z.url(),download_location:Z.url()}),user:Z.looseObject({name:Z.string(),links:Z.looseObject({html:Z.url()})}),width:Z.number().int().nonnegative(),height:Z.number().int().nonnegative()}),pJw=Z.looseObject({total:Z.number().int().nonnegative(),total_pages:Z.number().int().nonnegative(),results:Z.array(lJw)});function iJw(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}}L0();async function fZ0(A,Q,w,B){let $=await A.getEntity({entityType:Q,id:w});if(!$)return!1;return await A.updateEntity({entity:{...$,metadata:{...$.metadata,coverImageId:B}}}),!0}var dJw={query:Z.string().describe("Search terms for stock photos"),perPage:Z.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:Z.number().min(1).default(1).describe("Page number")},nJw={photoId:Z.string().describe("Photo ID from search results"),downloadLocation:Z.url().describe("Download tracking URL (required by provider ToS)"),photographerName:Z.string().describe("Photographer name for attribution"),photographerUrl:Z.url().describe("Photographer profile URL for attribution"),sourceUrl:Z.url().describe("Photo page URL on provider"),imageUrl:Z.url().describe("Image URL to download"),title:Z.string().optional().describe("Image entity title"),alt:Z.string().optional().describe("Alt text for the image"),targetEntityType:Z.string().optional().describe("Entity type to set cover image on"),targetEntityId:Z.string().optional().describe("Entity ID to set cover image on")},rJw=Z.object({query:Z.string(),perPage:Z.number().min(1).max(30).default(10),page:Z.number().min(1).default(1)}),oJw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});function hQ2(A,Q){return[sJw(A,Q),aJw(A,Q)]}function sJw(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:dJw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let B=rJw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos(B.data.query,{page:B.data.page,perPage:B.data.perPage})}}catch($){return{success:!1,error:$ instanceof Error?$.message:"Search failed"}}}}}function aJw(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:nJw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let B=oJw.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};let{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:H,imageUrl:W,title:K,alt:U,targetEntityType:G,targetEntityId:q}=B.data,b={photographerName:Y,photographerUrl:X,sourceUrl:H},J=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:W}}}});if(J[0]){let N={imageEntityId:J[0].id,alreadyExisted:!0,attribution:b};if(G&&q)N.coverSet=await fZ0(Q.entityService,G,q,J[0].id);return{success:!0,data:N}}let V=await Q.jobs.enqueue({type:"select-photo",data:{photoId:$,downloadLocation:f,photographerName:Y,photographerUrl:X,sourceUrl:H,imageUrl:W,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...G!==void 0?{targetEntityType:G}:{},...q!==void 0?{targetEntityId:q}:{}}}),k={imageEntityId:$,alreadyExisted:!1,attribution:b,jobId:V,status:"generating"};if(G&&q)k.coverSet=!1;return{success:!0,data:k}}}}wA();L0();_4();var tJw=Z.object({photoId:Z.string(),downloadLocation:Z.url(),photographerName:Z.string(),photographerUrl:Z.url(),sourceUrl:Z.url(),imageUrl:Z.url(),title:Z.string().optional(),alt:Z.string().optional(),targetEntityType:Z.string().optional(),targetEntityId:Z.string().optional()});class qt0 extends ew{deps;constructor(A,Q){super(A,{schema:tJw,jobTypeName:"select-photo"});this.deps=Q}async process(A,Q,w){await this.reportProgress(w,{progress:10,message:"Tracking stock photo download"}),await this.deps.provider.triggerDownload(A.downloadLocation),await this.reportProgress(w,{progress:35,message:"Downloading stock photo"});let B=await this.deps.fetchImage(A.imageUrl),$=A.title??`Stock photo ${A.photoId}`,f=dX.createImageEntity({dataUrl:B,title:$,alt:A.alt??$});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...f,metadata:{...f.metadata,sourceUrl:A.imageUrl}}}),X={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(X.coverSet=await fZ0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!X.coverSet)X.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),X}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}_4();var CQ2={name:"@brains/stock-photo",version:"0.2.0-alpha.164",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 AIw=Z.object({provider:Z.enum(["unsplash"]).default("unsplash"),apiKey:Z.string().optional().describe("Stock photo provider API key")});class bt0 extends Aw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",CQ2,A,AIw);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=hQ2(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??pH,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new qt0(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??pH}))}createProvider(){return new $Z0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function Vt0(A={},Q={}){return new bt0(A,Q)}wA();L0();wA();wA();L0();var gQ2=Z.enum(["ai","foundation","work"]),yQ2=Z.object({suffix:gQ2,title:Z.string(),body:Z.string(),linkLabel:Z.string(),linkHref:Z.string()}),to=Z.object({eyebrow:Z.string(),headline:Z.string(),cards:Z.array(yQ2).min(1)}),Jt0=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),QIw=Z.object({title:Z.string(),slug:Z.string(),status:Z.enum(["draft","published"])}),eo=PQ.extend({entityType:Z.literal("ecosystem-section"),metadata:QIw});class EQ2 extends E2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:eo,frontmatterSchema:Jt0})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var It0=new EQ2;L0();function wIw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function Ft0(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function As(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function YZ0(A){let Q=wIw(A),B=Ft0(Q,"Cards").split(/^### Card \d+\s*$/m).map(($)=>$.trim()).filter(Boolean);return to.parse({eyebrow:Ft0(Q,"Eyebrow"),headline:Ft0(Q,"Headline"),cards:B.map(($)=>({suffix:As($,"Suffix"),title:As($,"Title"),body:As($,"Body"),linkLabel:As($,"Link Label"),linkHref:As($,"Link Href")}))})}function TQ2(A){return["# Ecosystem Section","","## Eyebrow",A.eyebrow,"","## Headline",A.headline,"","## Cards","",...A.cards.flatMap((Q,w)=>[`### Card ${w+1}`,"","#### Suffix",Q.suffix,"","#### Title",Q.title,"","#### Body",Q.body,"","#### Link Label",Q.linkLabel,"","#### Link Href",Q.linkHref,""])].join(`
|
|
10208
10208
|
`)}var BIw=Z.looseObject({query:Z.object({id:Z.string().optional()}).optional()});class XZ0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,w){let $=BIw.parse(A??{}).query?.id??"rizom-ecosystem",f=await w.entityService.getEntity({entityType:"ecosystem-section",id:$});if(!f)throw Error(`Ecosystem section not found: ${$}`);return Q.parse(YZ0(f.content))}}import{jsxDEV as YIw}from"preact/jsx-dev-runtime";var $Iw="px-6 md:px-10 xl:px-20",fIw=`${$Iw} relative z-[1]`,SQ2=({id:A,className:Q,children:w})=>YIw("section",{id:A,className:j2(fIw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as ZZ0}from"preact/jsx-dev-runtime";var XIw=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),mQ2=({name:A="rizom",brandSuffix:Q,className:w,dotClassName:B,suffixClassName:$})=>{let f=XIw.get(Q);return ZZ0("span",{className:j2("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",w),children:[ZZ0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),ZZ0("span",{className:j2(f??"text-accent",B),children:"."},void 0,!1,void 0,this),ZZ0("span",{className:j2("italic font-normal text-theme-muted",$),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Fragment as kt0}from"preact";import{jsxDEV as Qs}from"preact/jsx-dev-runtime";var ZIw=/(\*[^*]+\*)/;function uQ2(A,Q){let w=A.split(`
|
|
10209
|
-
`);return Qs(kt0,{children:w.map((B,$)=>Qs(kt0,{children:[$>0&&Qs("br",{},void 0,!1,void 0,this),B.split(ZIw).map((f,Y)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return Qs("span",{className:Q,children:f.slice(1,-1)},Y,!1,void 0,this);return Qs(kt0,{children:f},Y,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as QX,Fragment as JIw}from"preact/jsx-dev-runtime";var HIw="italic text-accent font-normal",WIw="You are here",KIw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},UIw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},GIw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},DIw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",zIw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",qIw="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",bIw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",VIw=({card:A})=>{let Q=A.linkLabel===WIw,w=A.linkHref.trim().length===0,B=QX(JIw,{children:[QX(mQ2,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),QX("span",{className:`${DIw} ${KIw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),QX("p",{className:zIw,children:A.body},void 0,!1,void 0,this),Q?QX("span",{className:bIw,children:A.linkLabel},void 0,!1,void 0,this):QX("span",{className:qIw,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$=`flex flex-col gap-[14px] border-t pt-7 ${Q?UIw[A.suffix]:"border-white/10"}`;return Q||w?QX("div",{className:$,children:B},void 0,!1,void 0,this):QX("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${GIw[A.suffix]}`,children:B},void 0,!1,void 0,this)},cQ2=({eyebrow:A,headline:Q,cards:w})=>QX(SQ2,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[QX("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[QX("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),QX("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:uQ2(Q,HIw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),QX("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:w.map((B)=>QX(VIw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);wA();var Lt0=l1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:to,formatter:{parse:YZ0,format:TQ2},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:cQ2}});var lQ2={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.
|
|
10209
|
+
`);return Qs(kt0,{children:w.map((B,$)=>Qs(kt0,{children:[$>0&&Qs("br",{},void 0,!1,void 0,this),B.split(ZIw).map((f,Y)=>{if(f.length>=3&&f.startsWith("*")&&f.endsWith("*"))return Qs("span",{className:Q,children:f.slice(1,-1)},Y,!1,void 0,this);return Qs(kt0,{children:f},Y,!1,void 0,this)})]},$,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as QX,Fragment as JIw}from"preact/jsx-dev-runtime";var HIw="italic text-accent font-normal",WIw="You are here",KIw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},UIw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},GIw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},DIw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",zIw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",qIw="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",bIw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",VIw=({card:A})=>{let Q=A.linkLabel===WIw,w=A.linkHref.trim().length===0,B=QX(JIw,{children:[QX(mQ2,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),QX("span",{className:`${DIw} ${KIw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),QX("p",{className:zIw,children:A.body},void 0,!1,void 0,this),Q?QX("span",{className:bIw,children:A.linkLabel},void 0,!1,void 0,this):QX("span",{className:qIw,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$=`flex flex-col gap-[14px] border-t pt-7 ${Q?UIw[A.suffix]:"border-white/10"}`;return Q||w?QX("div",{className:$,children:B},void 0,!1,void 0,this):QX("a",{href:A.linkHref,className:`${$} text-inherit no-underline transition-colors ${GIw[A.suffix]}`,children:B},void 0,!1,void 0,this)},cQ2=({eyebrow:A,headline:Q,cards:w})=>QX(SQ2,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[QX("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[QX("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),QX("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:uQ2(Q,HIw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),QX("div",{className:"mx-auto grid max-w-[1180px] grid-cols-3 gap-16 max-[768px]:grid-cols-1 max-[768px]:gap-7",children:w.map((B)=>QX(VIw,{card:B},B.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);wA();var Lt0=l1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:to,formatter:{parse:YZ0,format:TQ2},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:cQ2}});var lQ2={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.164",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 FIw=Z.object({}).catchall(Z.unknown()).transform(()=>({})),kIw="ecosystem-section";class _t0 extends sQ{entityType=kIw;schema=eo;adapter=It0;constructor(A={}){super("rizom-ecosystem",lQ2,A,FIw)}getTemplates(){return{ecosystem:Lt0}}getDataSources(){return[new XZ0]}}function jj(A={}){return new _t0(A)}L0();wA();wA();D2();L0();q5();L0();wA();var NB="agent",pQ2="agent-discovery";var iQ2="agent-network",dQ2="AgentNetworkWidget",nQ2="agent-proximity",rQ2="AgentProximityWidget",ws="agent-discovery:entities",HZ0="agent-discovery:proximity-map",Nt0="agent-proximity-map",Pt0="agent-list",jt0="agent-detail",M8="skill",oQ2="skill",WZ0="skill-derivation",sQ2="skill:project",aQ2="skill-derivation",tQ2="skill:skill-derivation",eQ2="skills";var KZ0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),uF=Z.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),Aw2=Z.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),LIw=Z.enum(["professional","team","collective"]),hU=Z.object({name:Z.string(),kind:LIw,organization:Z.string().optional(),brainName:Z.string().describe("Name of the brain instance"),url:Z.string().url().describe("Brain endpoint URL"),did:Z.string().optional().describe("Decentralized identifier (public)"),repoDid:Z.string().optional().describe("ATProto repo DID"),brainDid:Z.string().optional().describe("ATProto brain DID"),anchorDid:Z.string().optional().describe("ATProto anchor DID"),cardUri:Z.string().optional().describe("ATProto brain card URI"),cardCid:Z.string().optional().describe("ATProto brain card CID"),a2aEndpoint:Z.string().url().optional().describe("A2A endpoint URL"),status:uF,discoveredAt:Z.string().datetime().describe("When this agent was first discovered")}),Qw2=Z.object({name:Z.string(),url:Z.string().url(),status:uF,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),_Iw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional(),status:Aw2,discoveredAt:Z.string().datetime()}),NIw=Z.object({name:Z.string(),url:Z.string().url(),status:Aw2,discoveredAt:Z.string().datetime().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.string().url().optional()}),Bs=N$.extend({entityType:Z.literal(NB),metadata:Qw2}),PIw=PQ.extend({entityType:Z.literal(NB),metadata:NIw}),$s=PIw.extend({frontmatter:_Iw,about:Z.string(),skills:Z.array(KZ0),notes:Z.string()}),jIw=$s.extend({url:Z.string().optional(),typeLabel:Z.string().optional()}),MIw=$s.extend({url:Z.string(),typeLabel:Z.string()});L0();var xIw=Z.array(KZ0);function ww2(A){let Q=xIw.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
|
|
10210
10210
|
`)}function Bw2(A){if(!A.trim())return[];let Q=[];for(let w of A.split(`
|
|
10211
10211
|
`)){let B=w.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!B)continue;let $=B[1]??"",f=B[2]??"",Y=B[3],X=Y?Y.split(",").map((H)=>H.trim()).filter(Boolean):[];Q.push({name:$,description:f,tags:X})}return Q}var OIw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),vIw=Z.object({about:Z.string(),skills:Z.array(OIw),notes:Z.string()}),$w2=new $6(vIw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:ww2,parser:Bw2},{key:"notes",label:"Notes",type:"string"}]});class D7 extends E2{constructor(){super({entityType:NB,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:Bs,frontmatterSchema:hU})}fromMarkdown(A){let Q=this.parseFrontMatter(A,hU),w=Nx(Q.url);return{content:A,entityType:NB,metadata:{name:Q.name,url:Q.url,status:Q.status,discoveredAt:Q.discoveredAt,slug:w,...Q.repoDid&&{repoDid:Q.repoDid},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},...Q.cardUri&&{cardUri:Q.cardUri},...Q.cardCid&&{cardCid:Q.cardCid},...Q.a2aEndpoint&&{a2aEndpoint:Q.a2aEndpoint}}}}createAgentContent(A){let Q={name:A.name,kind:A.kind,...A.organization&&{organization:A.organization},brainName:A.brainName,url:A.url,...A.did&&{did:A.did},...A.repoDid&&{repoDid:A.repoDid},...A.brainDid&&{brainDid:A.brainDid},...A.anchorDid&&{anchorDid:A.anchorDid},...A.cardUri&&{cardUri:A.cardUri},...A.cardCid&&{cardCid:A.cardCid},...A.a2aEndpoint&&{a2aEndpoint:A.a2aEndpoint},status:uF.parse(A.status),discoveredAt:A.discoveredAt},w=$w2.format({about:A.about,skills:A.skills,notes:A.notes});return this.buildMarkdown(w,Q)}parseAgentContent(A){let Q=this.extractBody(A);if(!Q.trim())return{about:"",skills:[],notes:""};try{let w=$w2.parse(Q);return{about:w.about,skills:w.skills,notes:w.notes}}catch{return{about:"",skills:[],notes:""}}}parseEntity(A){return{frontmatter:this.parseFrontMatter(A.content,hU),body:this.parseAgentContent(A.content)}}}wA();L0();var RIw=new D7,fw2=Z.enum(["discovered","approved","archived"]),hIw=Z.looseObject({id:Z.string().optional(),limit:Z.number().optional(),page:Z.number().optional(),pageSize:Z.number().optional(),baseUrl:Z.string().optional(),status:fw2.optional()}),CIw=Z.looseObject({entityType:Z.string().optional(),query:hIw.optional()});function gIw(A){let Q=r2(A.content,hU),w=RIw.parseAgentContent(A.content);return $s.parse({...A,frontmatter:Q.metadata,about:w.about,skills:w.skills,notes:w.notes})}class UZ0 extends L5{id=ws;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:NB,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return gIw(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=CIw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,w){let B=fw2.safeParse(w.status);return{agents:A,pagination:Q,baseUrl:w.baseUrl,selectedStatus:B.success?B.data:"all"}}async fetch(A,Q,w){let{query:B}=this.parseQuery(A);if(B.id)return super.fetch(A,Q,w);let{items:$,pagination:f}=await this.fetchList(B,w.entityService,B.status?{filter:{metadata:{status:B.status}}}:void 0);return Q.parse(this.buildListResult($,f,B))}}var yIw=180*(3-Math.sqrt(5));function Yw2(A){return Math.max(0,Math.min(1,A))}function Xw2(A,Q){let[w,B]=A;if(Math.hypot(w,B)<=0.000000000001)return Q*yIw%360;return(Math.atan2(B,w)*180/Math.PI%360+360)%360}function Zw2(A,Q){let w=new Map(A.map((Y)=>[Y.id,Y])),B=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||!w.has(Y.source.entityId)||!w.has(Y.target.entityId))continue;B.get(Y.source.entityId)?.add(Y.target.entityId),B.get(Y.target.entityId)?.add(Y.source.entityId)}let $=new Set,f=[];for(let Y of Array.from(w.keys()).sort()){if($.has(Y))continue;let X=[],H=[Y];$.add(Y);while(H.length>0){let W=H.pop();if(!W)continue;X.push(W);for(let K of Array.from(B.get(W)??[]).sort()){if($.has(K))continue;$.add(K),H.push(K)}}if(X.length>=2)f.push(X.sort())}return f.map((Y)=>({label:EIw(Y,w),memberIds:Y,links:Y.flatMap((X)=>Array.from(B.get(X)??[]).filter((H)=>X.localeCompare(H)<0).sort().map((H)=>({sourceId:X,targetId:H})))})).sort((Y,X)=>{let H=Y.memberIds.some((U)=>(w.get(U)?.tags.length??0)>0),W=X.memberIds.some((U)=>(w.get(U)?.tags.length??0)>0);if(H!==W)return H?-1:1;let K=Y.label.localeCompare(X.label);return K!==0?K:(Y.memberIds[0]??"").localeCompare(X.memberIds[0]??"")})}function EIw(A,Q){let w=new Map;for(let $ of A){let f=Q.get($);for(let Y of new Set(f?.tags??[]))w.set(Y,(w.get(Y)??0)+1)}let B=Array.from(w.entries()).sort(($,f)=>{let Y=f[1]-$[1];return Y!==0?Y:$[0].localeCompare(f[0])})[0]?.[0];return B?`${B} \xB7 ${A.length}`:`unknown \xB7 ${A.length}`}L0();var TIw=hU.shape.kind,SIw=Z.object({kind:Z.enum(["identity","centroid"])}),mIw=Z.object({id:Z.string(),name:Z.string(),kind:TIw,status:uF,tags:Z.array(Z.string()),distance:Z.number().min(0).max(1),bearing:Z.number().min(0).lt(360)}),uIw=Z.object({sourceId:Z.string(),targetId:Z.string()}),cIw=Z.object({label:Z.string(),memberIds:Z.array(Z.string()).min(2),links:Z.array(uIw).min(1)}),lIw=Z.object({min:Z.number().min(0),max:Z.number().min(0)}),bb=Z.object({center:SIw,nodes:Z.array(mIw),clusters:Z.array(cIw),distanceRange:lIw,pendingCount:Z.number().int().min(0)});var pIw=new D7;function Hw2(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function H3(A){let Q=new Set,w=[];for(let B of A){let $=Hw2(B);if(!$||Q.has($))continue;Q.add($),w.push($)}return w}function iIw(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function Ww2(A,Q={}){let w=Q.minCount??1,B=Q.topN??12,$=Q.visibilityScope??"public",f=new Map,[Y,X]=await Promise.all([A.entityService.listEntities({entityType:M8,options:{filter:{visibilityScope:$}}}),A.entityService.listEntities({entityType:NB,options:{filter:{visibilityScope:$}}})]),H=(W)=>{for(let K of H3(W))f.set(K,(f.get(K)??0)+1)};for(let W of Y)H(W.metadata.tags);for(let W of X){let K=pIw.parseAgentContent(W.content);H(K.skills.flatMap((U)=>U.tags))}return Array.from(f.entries()).map(([W,K])=>({tag:W,count:K})).filter((W)=>W.count>=w).sort(iIw).slice(0,B)}function Kw2(A){if(A.length===0)return"";return["Current agent-directory tag vocabulary (reuse existing tags where they fit; propose new only when nothing does):",...A.map(({tag:Q,count:w})=>`- ${Q} (${w})`)].join(`
|
|
10212
10212
|
`)}var dIw={entityId:"brain-character",entityType:"brain-character"},nIw=0.25,rIw=new D7;async function GZ0(A){let[Q,w]=await Promise.all([A.entityService.listEntities({entityType:NB}),A.semantic.project({types:[NB],origin:dIw,maxNeighborDistance:nIw})]),B=new Map(w.points.filter((Y)=>Y.entityType===NB).map((Y)=>[Y.entityId,Y])),$=[];for(let Y of Q.slice().sort((X,H)=>X.id.localeCompare(H.id))){let X=B.get(Y.id);if(!X)continue;let{frontmatter:H,body:W}=rIw.parseEntity(Y);$.push({id:Y.id,name:H.name,kind:H.kind,status:H.status,tags:H3(W.skills.flatMap((K)=>K.tags)),distance:Yw2(X.distanceToOrigin),bearing:Xw2(X.coordinates,$.length)})}let f=$.filter((Y)=>Y.status!=="archived");return bb.parse({center:{kind:w.origin.kind==="entity"?"identity":"centroid"},nodes:$,clusters:Zw2(f,w.neighbors),distanceRange:w.distanceRange,pendingCount:Math.max(0,Q.length-$.length)})}class DZ0{id=HZ0;name="Agent Proximity Map DataSource";description="Builds a public semantic proximity map for saved agents";async fetch(A,Q,w){let B=await GZ0({entityService:w.entityService,semantic:{project:($)=>w.entityService.projectSemanticSpace($)}});return Q.parse(B)}}wA();L0();T6();wA();async function zZ0(A,Q){let B=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let $=await Q(B);if(!$.ok)return null;let f=await $.json();return Nm(f)}catch{return null}}function Mj(A){let Q=A.trim();if(Q.startsWith("http://")||Q.startsWith("https://"))try{return new URL(Q).hostname}catch{return Q}let w=Q.match(/https?:\/\/[^\s]+?(?=[.,;:!?)]*(?:\s|$))/);if(w)try{return new URL(w[0]).hostname}catch{return w[0]}if(/^[^\s]+\.[^\s]+$/.test(Q))return Q;return""}D2();var oIw=new D7;function qZ0(A,Q={}){let w=A.anchor?.name??A.brainName,B=A.anchor?.kind??"professional",$=[];if(A.anchor?.description)$.push(A.anchor.description);if(A.description)$.push(A.description);let f=Q.status??"discovered",Y=new Date().toISOString();return{content:oIw.createAgentContent({name:w,kind:B,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:f,discoveredAt:Y,about:$.join(`
|
|
@@ -10674,7 +10674,7 @@ ${A.guidance}`:$}}function zQ2(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10674
10674
|
.agent-proximity-site .proximity-bulb-glow,
|
|
10675
10675
|
.agent-proximity-site .proximity-spore { animation: none; }
|
|
10676
10676
|
}
|
|
10677
|
-
`;function Ct0(A){let Q=A.nodes.filter((B)=>B.status!=="archived").length,w=A.nodes.length-Q;return g6("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[g6("style",{children:RFw},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__grid",children:[g6("div",{class:"agent-proximity-site__copy",children:[g6("p",{class:"agent-proximity-site__kicker",children:"Agent network"},void 0,!1,void 0,this),g6("h2",{class:"agent-proximity-site__heading",children:["The rhizome grows ",g6("em",{children:"beneath this brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("p",{class:"agent-proximity-site__lede",children:"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."},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"archived traces"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g6("a",{class:"agent-proximity-site__cta",href:"/agents",children:"Meet the agents"},void 0,!1,void 0,this),A.pendingCount>0&&g6("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&g6("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),g6("div",{class:"agent-proximity-site__map",children:g6(JZ0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[g6("span",{children:[g6("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\xB7"},void 0,!1,void 0,this)," archived trace"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var hFw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),CFw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),gFw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),gt0=Z.enum(["discovered","approved","archived"]),yFw=Z.enum(["professional","team","collective"]),EFw=Z.object({name:Z.string(),kind:yFw,organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional(),status:gt0,discoveredAt:Z.string()}),TFw=Z.object({name:Z.string(),url:Z.url(),status:gt0,discoveredAt:Z.string().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional()}),_Z0=Z.object({id:Z.string(),entityType:Z.literal(NB),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:hFw,metadata:TFw,contentHash:Z.string(),frontmatter:EFw,about:Z.string(),skills:Z.array(gFw),notes:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional()}),SFw=Z.object({agents:Z.array(_Z0),pageTitle:Z.string().optional(),pagination:CFw.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.union([Z.literal("all"),gt0])}),mFw=`data:text/javascript;charset=utf-8,${encodeURIComponent(py)}`;function Mw2(){return{[Nt0]:l1({name:Nt0,description:"Semantic agent proximity map site section",schema:bb,dataSourceId:HZ0,requiredPermission:"public",runtimeScripts:[{src:mFw,defer:!0}],layout:{component:Ct0}}),[Pt0]:l1({name:Pt0,description:"Agent directory list page template",schema:SFw,dataSourceId:ws,requiredPermission:"public",layout:{component:Pw2}}),[jt0]:l1({name:jt0,description:"Individual agent profile template",schema:Z.object({agent:_Z0,prevAgent:_Z0.nullable(),nextAgent:_Z0.nullable()}),dataSourceId:ws,requiredPermission:"public",layout:{component:jw2}})}}var iy={name:"@brains/agent-discovery",version:"0.2.0-alpha.163",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 cFw=new D7;class yt0 extends sQ{entityType=NB;schema=Bs;adapter=cFw;constructor(){super(pQ2,iy,{},P7)}createGenerationHandler(A){return new Mt0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return Mw2()}getDataSources(){return[new UZ0(this.logger.child("AgentDataSource")),new DZ0]}async onRegister(A){kw2(A),Iw2(A,this.id)}async getInstructions(){return Lw2()}}function Et0(){return new yt0}wA();L0();X9();L0();var xw2=Z.object({source:Z.object({kind:Z.literal("url"),url:Z.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional()}),lFw=new D7;function pFw(A){let Q=Mj(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function iFw(A,Q){return(Mj(Q)||A).toLowerCase()}async function dFw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:NB,id:w}),Y=qZ0(B,{status:"approved"}),H={...lFw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:B.url};if(f){let K={...f,content:Y.content,metadata:H,updated:$};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let W={id:w,entityType:NB,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:W}),{entity:W,created:!0}}function Ow2(A,Q=globalThis.fetch){let B=new TX;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. 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:xw2.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let Y=xw2.safeParse($);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let X=Y.data,H=pFw(X.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(NB,"create",f)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(X.confirmed){let K=X.confirmationToken,U=B.validate(K,X);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let G=await zZ0(H.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=iFw(H.domain,G.url),{entity:b,created:J}=await dFw({context:A,entityId:q,sourceUrl:X.source.url,card:G});return{success:!0,data:{status:b.metadata.status,entityId:b.id,connected:!0,created:J,a2aEndpoint:G.url,skills:G.skills.map((V)=>({name:V.name,description:V.description,tags:V.tags}))}}}let W=B.create((K)=>({source:X.source,confirmed:!0,confirmationToken:K}));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:W}}}}X9();L0();var nFw=Z.enum(["public","trusted"]),vw2=Z.object({agent:Z.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:nFw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),keyFingerprint:Z.string().optional()}),rFw=Z.object({keys:Z.array(Z.unknown())}),oFw=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),kid:Z.string().optional(),alg:Z.literal("EdDSA").optional()}).passthrough();function Rw2(A){return(Mj(A)||A.trim()).toLowerCase()}async function sFw(A,Q){let w=Rw2(Q),B=await A.entityService.getEntity({entityType:NB,id:w});if(!B)return null;let $=Rw2(B.metadata.a2aEndpoint??B.metadata.url);if(!$)return null;return{domain:$}}async function aFw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let B=rFw.safeParse(await w.json());if(!B.success)return null;let $=B.data.keys.map((f)=>oFw.safeParse(f)).find((f)=>f.success);if(!$?.success)return null;return gu0($.data)}catch{return null}}function hw2(A,Q=globalThis.fetch){let B=new TX;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:vw2.shape,visibility:"anchor",sideEffects:"external",handler:async($)=>{let f=vw2.safeParse($);if(!f.success)return{success:!1,error:`Invalid input: ${f.error.issues.map((G)=>`${G.path.join(".")}: ${G.message}`).join(", ")}`};let Y=v7();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let X=await sFw(A,f.data.agent);if(!X)return{success:!1,error:`No saved agent contact found for ${f.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=f.data;if(H.confirmed){let G=B.validate(H.confirmationToken,H);if(G.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(G.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:X.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:X.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(X.domain),{success:!0,data:{agent:X.domain,level:"public"}}}let W=H.level==="trusted"?await aFw(X.domain,Q):void 0;if(H.level==="trusted"&&!W)return{success:!1,error:`Could not fetch an A2A signing key from ${X.domain}.`,code:"jwks_unavailable"};let K=B.create((G)=>({agent:X.domain,level:H.level,confirmed:!0,confirmationToken:G,...W?{keyFingerprint:W}:{}})),U=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${X.domain}?`:`Revoke inbound trusted A2A access from ${X.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${X.domain} and pin key fingerprint ${W}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${X.domain}. The directory contact remains saved for outbound calls.`,args:K}}}}var tFw=Z.object({}).strict();class Tt0 extends Aw{fetchFn;constructor(A){super("agent",iy,{},tFw);this.fetchFn=A}async getTools(){return[Ow2(this.getContext(),this.fetchFn),hw2(this.getContext(),this.fetchFn)]}}function St0(){return new Tt0}wA();wA();L0();var xj=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),Cw2=xj,Zs=N$.extend({entityType:Z.literal(M8),metadata:Cw2});wA();class dy extends E2{constructor(){super({entityType:M8,purpose:"A capability advertised by a remote agent.",schema:Zs,frontmatterSchema:xj})}fromMarkdown(A){let Q=this.parseFrontMatter(A,xj);return{content:A,entityType:M8,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}wA();L0();var eFw=Z.object({skills:Z.array(xj).max(8)}),gw2=l1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:eFw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10677
|
+
`;function Ct0(A){let Q=A.nodes.filter((B)=>B.status!=="archived").length,w=A.nodes.length-Q;return g6("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[g6("style",{children:RFw},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__grid",children:[g6("div",{class:"agent-proximity-site__copy",children:[g6("p",{class:"agent-proximity-site__kicker",children:"Agent network"},void 0,!1,void 0,this),g6("h2",{class:"agent-proximity-site__heading",children:["The rhizome grows ",g6("em",{children:"beneath this brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("p",{class:"agent-proximity-site__lede",children:"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."},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{children:[g6("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),g6("div",{class:"agent-proximity-site__stat-label",children:"archived traces"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g6("a",{class:"agent-proximity-site__cta",href:"/agents",children:"Meet the agents"},void 0,!1,void 0,this),A.pendingCount>0&&g6("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&g6("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),g6("div",{class:"agent-proximity-site__map",children:g6(JZ0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),g6("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[g6("span",{children:[g6("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),g6("span",{children:[g6("b",{children:"\xB7"},void 0,!1,void 0,this)," archived trace"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var hFw=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),CFw=Z.object({currentPage:Z.number(),totalPages:Z.number(),totalItems:Z.number(),pageSize:Z.number(),hasNextPage:Z.boolean(),hasPrevPage:Z.boolean()}),gFw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),gt0=Z.enum(["discovered","approved","archived"]),yFw=Z.enum(["professional","team","collective"]),EFw=Z.object({name:Z.string(),kind:yFw,organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional(),status:gt0,discoveredAt:Z.string()}),TFw=Z.object({name:Z.string(),url:Z.url(),status:gt0,discoveredAt:Z.string().optional(),slug:Z.string(),repoDid:Z.string().optional(),brainDid:Z.string().optional(),anchorDid:Z.string().optional(),cardUri:Z.string().optional(),cardCid:Z.string().optional(),a2aEndpoint:Z.url().optional()}),_Z0=Z.object({id:Z.string(),entityType:Z.literal(NB),content:Z.string(),created:Z.string(),updated:Z.string(),visibility:hFw,metadata:TFw,contentHash:Z.string(),frontmatter:EFw,about:Z.string(),skills:Z.array(gFw),notes:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional()}),SFw=Z.object({agents:Z.array(_Z0),pageTitle:Z.string().optional(),pagination:CFw.nullable(),baseUrl:Z.string().optional(),selectedStatus:Z.union([Z.literal("all"),gt0])}),mFw=`data:text/javascript;charset=utf-8,${encodeURIComponent(py)}`;function Mw2(){return{[Nt0]:l1({name:Nt0,description:"Semantic agent proximity map site section",schema:bb,dataSourceId:HZ0,requiredPermission:"public",runtimeScripts:[{src:mFw,defer:!0}],layout:{component:Ct0}}),[Pt0]:l1({name:Pt0,description:"Agent directory list page template",schema:SFw,dataSourceId:ws,requiredPermission:"public",layout:{component:Pw2}}),[jt0]:l1({name:jt0,description:"Individual agent profile template",schema:Z.object({agent:_Z0,prevAgent:_Z0.nullable(),nextAgent:_Z0.nullable()}),dataSourceId:ws,requiredPermission:"public",layout:{component:jw2}})}}var iy={name:"@brains/agent-discovery",version:"0.2.0-alpha.164",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 cFw=new D7;class yt0 extends sQ{entityType=NB;schema=Bs;adapter=cFw;constructor(){super(pQ2,iy,{},P7)}createGenerationHandler(A){return new Mt0(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return Mw2()}getDataSources(){return[new UZ0(this.logger.child("AgentDataSource")),new DZ0]}async onRegister(A){kw2(A),Iw2(A,this.id)}async getInstructions(){return Lw2()}}function Et0(){return new yt0}wA();L0();X9();L0();var xw2=Z.object({source:Z.object({kind:Z.literal("url"),url:Z.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional()}),lFw=new D7;function pFw(A){let Q=Mj(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function iFw(A,Q){return(Mj(Q)||A).toLowerCase()}async function dFw(A){let{context:Q,entityId:w,card:B}=A,$=new Date().toISOString(),f=await Q.entityService.getEntity({entityType:NB,id:w}),Y=qZ0(B,{status:"approved"}),H={...lFw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:B.url};if(f){let K={...f,content:Y.content,metadata:H,updated:$};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let W={id:w,entityType:NB,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:$,updated:$};return await Q.entityService.createEntity({entity:W}),{entity:W,created:!0}}function Ow2(A,Q=globalThis.fetch){let B=new TX;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. 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:xw2.shape,visibility:"trusted",sideEffects:"external",handler:async($,f)=>{let Y=xw2.safeParse($);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let X=Y.data,H=pFw(X.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(NB,"create",f)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(X.confirmed){let K=X.confirmationToken,U=B.validate(K,X);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let G=await zZ0(H.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=iFw(H.domain,G.url),{entity:b,created:J}=await dFw({context:A,entityId:q,sourceUrl:X.source.url,card:G});return{success:!0,data:{status:b.metadata.status,entityId:b.id,connected:!0,created:J,a2aEndpoint:G.url,skills:G.skills.map((V)=>({name:V.name,description:V.description,tags:V.tags}))}}}let W=B.create((K)=>({source:X.source,confirmed:!0,confirmationToken:K}));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:W}}}}X9();L0();var nFw=Z.enum(["public","trusted"]),vw2=Z.object({agent:Z.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:nFw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:Z.boolean().optional(),confirmationToken:Z.string().optional(),keyFingerprint:Z.string().optional()}),rFw=Z.object({keys:Z.array(Z.unknown())}),oFw=Z.object({kty:Z.literal("OKP"),crv:Z.literal("Ed25519"),x:Z.string(),kid:Z.string().optional(),alg:Z.literal("EdDSA").optional()}).passthrough();function Rw2(A){return(Mj(A)||A.trim()).toLowerCase()}async function sFw(A,Q){let w=Rw2(Q),B=await A.entityService.getEntity({entityType:NB,id:w});if(!B)return null;let $=Rw2(B.metadata.a2aEndpoint??B.metadata.url);if(!$)return null;return{domain:$}}async function aFw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let B=rFw.safeParse(await w.json());if(!B.success)return null;let $=B.data.keys.map((f)=>oFw.safeParse(f)).find((f)=>f.success);if(!$?.success)return null;return gu0($.data)}catch{return null}}function hw2(A,Q=globalThis.fetch){let B=new TX;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:vw2.shape,visibility:"anchor",sideEffects:"external",handler:async($)=>{let f=vw2.safeParse($);if(!f.success)return{success:!1,error:`Invalid input: ${f.error.issues.map((G)=>`${G.path.join(".")}: ${G.message}`).join(", ")}`};let Y=v7();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let X=await sFw(A,f.data.agent);if(!X)return{success:!1,error:`No saved agent contact found for ${f.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=f.data;if(H.confirmed){let G=B.validate(H.confirmationToken,H);if(G.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(G.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:X.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:X.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(X.domain),{success:!0,data:{agent:X.domain,level:"public"}}}let W=H.level==="trusted"?await aFw(X.domain,Q):void 0;if(H.level==="trusted"&&!W)return{success:!1,error:`Could not fetch an A2A signing key from ${X.domain}.`,code:"jwks_unavailable"};let K=B.create((G)=>({agent:X.domain,level:H.level,confirmed:!0,confirmationToken:G,...W?{keyFingerprint:W}:{}})),U=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${X.domain}?`:`Revoke inbound trusted A2A access from ${X.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${X.domain} and pin key fingerprint ${W}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${X.domain}. The directory contact remains saved for outbound calls.`,args:K}}}}var tFw=Z.object({}).strict();class Tt0 extends Aw{fetchFn;constructor(A){super("agent",iy,{},tFw);this.fetchFn=A}async getTools(){return[Ow2(this.getContext(),this.fetchFn),hw2(this.getContext(),this.fetchFn)]}}function St0(){return new Tt0}wA();wA();L0();var xj=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),Cw2=xj,Zs=N$.extend({entityType:Z.literal(M8),metadata:Cw2});wA();class dy extends E2{constructor(){super({entityType:M8,purpose:"A capability advertised by a remote agent.",schema:Zs,frontmatterSchema:xj})}fromMarkdown(A){let Q=this.parseFrontMatter(A,xj);return{content:A,entityType:M8,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}wA();L0();var eFw=Z.object({skills:Z.array(xj).max(8)}),gw2=l1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:eFw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10678
10678
|
|
|
10679
10679
|
Given knowledge domains, CONSOLIDATE related topics into broader skills.
|
|
10680
10680
|
There should be FEWER skills than topics \u2014 combine related domains.
|
|
@@ -10824,9 +10824,9 @@ Context:
|
|
|
10824
10824
|
${JSON.stringify(B,null,2)}
|
|
10825
10825
|
|
|
10826
10826
|
Draft SWOT:
|
|
10827
|
-
${JSON.stringify(w,null,2)}`}function RZ0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function Lkw(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let B of w){let $=new Set(A[B].map((f)=>f.theme.trim().toLowerCase()));for(let f of Q[B]){let Y=f.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class hZ0{logger;context;adapter=new Vb;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=ct0.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let B=await nt0(this.context),$;if(B.summary.brainSkillCount+B.summary.approvedAgentCount+B.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:W}=await this.context.ai.generateObject(await Ikw(this.context,B),lt0),K=lt0.parse(W);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await kkw(this.context,B,K),xZ0);$=xZ0.parse(U.object),Lkw(K,$)}let Y=new Date().toISOString(),X=this.adapter.createSwotContent({strengths:RZ0($.strengths),weaknesses:RZ0($.weaknesses),opportunities:RZ0($.opportunities),threats:RZ0($.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let H=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(H)await this.context.entityService.updateEntity({entity:{...H,content:X,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:X,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}L0();import{jsxDEV as o4}from"preact/jsx-dev-runtime";var CZ0=Z.object({title:Z.string(),detail:Z.string().optional()}),_kw=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(CZ0).default([]),weaknesses:Z.array(CZ0).default([]),opportunities:Z.array(CZ0).default([]),threats:Z.array(CZ0).default([]),derivedAt:Z.string()})]);function Nkw({items:A}){if(A.length===0)return o4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return o4("ul",{class:"swot-list",children:A.map((Q)=>o4("li",{class:"swot-item",children:[o4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?o4("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function gZ0({title:A,tone:Q,items:w}){return o4("section",{class:`swot-cell is-${Q}`,children:[o4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),o4(Nkw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function st0({data:A}){let Q=_kw.safeParse(A);if(!Q.success||Q.data.status==="generating")return o4("div",{"data-swot-widget":!0,children:o4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return o4("div",{"data-swot-widget":!0,children:o4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[o4(gZ0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),o4(gZ0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),o4(gZ0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),o4(gZ0,{title:"Threats",tone:"t",items:w.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var at0={name:"@brains/assessment",version:"0.2.0-alpha.
|
|
10827
|
+
${JSON.stringify(w,null,2)}`}function RZ0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function Lkw(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let B of w){let $=new Set(A[B].map((f)=>f.theme.trim().toLowerCase()));for(let f of Q[B]){let Y=f.sourceTheme.trim().toLowerCase();if(!$.has(Y))throw Error(`SWOT refinement invented theme "${f.sourceTheme}" in ${B}`)}}}class hZ0{logger;context;adapter=new Vb;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=ct0.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let B=await nt0(this.context),$;if(B.summary.brainSkillCount+B.summary.approvedAgentCount+B.summary.discoveredAgentCount===0)$={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:W}=await this.context.ai.generateObject(await Ikw(this.context,B),lt0),K=lt0.parse(W);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await kkw(this.context,B,K),xZ0);$=xZ0.parse(U.object),Lkw(K,$)}let Y=new Date().toISOString(),X=this.adapter.createSwotContent({strengths:RZ0($.strengths),weaknesses:RZ0($.weaknesses),opportunities:RZ0($.opportunities),threats:RZ0($.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let H=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(H)await this.context.entityService.updateEntity({entity:{...H,content:X,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:X,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:B.summary.brainSkillCount,approvedAgentCount:B.summary.approvedAgentCount,discoveredAgentCount:B.summary.discoveredAgentCount}),{entityId:"swot"}}}L0();import{jsxDEV as o4}from"preact/jsx-dev-runtime";var CZ0=Z.object({title:Z.string(),detail:Z.string().optional()}),_kw=Z.discriminatedUnion("status",[Z.object({status:Z.literal("generating")}),Z.object({status:Z.literal("ready"),strengths:Z.array(CZ0).default([]),weaknesses:Z.array(CZ0).default([]),opportunities:Z.array(CZ0).default([]),threats:Z.array(CZ0).default([]),derivedAt:Z.string()})]);function Nkw({items:A}){if(A.length===0)return o4("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return o4("ul",{class:"swot-list",children:A.map((Q)=>o4("li",{class:"swot-item",children:[o4("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?o4("span",{children:[" \u2014 ",Q.detail]},void 0,!0,void 0,this):null]},`${Q.title}:${Q.detail??""}`,!0,void 0,this))},void 0,!1,void 0,this)}function gZ0({title:A,tone:Q,items:w}){return o4("section",{class:`swot-cell is-${Q}`,children:[o4("div",{class:"swot-head",children:A},void 0,!1,void 0,this),o4(Nkw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function st0({data:A}){let Q=_kw.safeParse(A);if(!Q.success||Q.data.status==="generating")return o4("div",{"data-swot-widget":!0,children:o4("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return o4("div",{"data-swot-widget":!0,children:o4("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[o4(gZ0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),o4(gZ0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),o4(gZ0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),o4(gZ0,{title:"Threats",tone:"t",items:w.threats},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}var at0={name:"@brains/assessment",version:"0.2.0-alpha.164",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 jkw=Z.object({status:Z.enum(["ready","generating"])}),tt0=new Vb;class et0 extends sQ{entityType="swot";schema=ny;adapter=tt0;initialSyncComplete=!1;constructor(){super("swot",at0,{},P7)}async onRegister(A){let Q=new hZ0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let f=Kf.from(async()=>{});if(!f)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",f);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return tt0.parseSwotContent(Y.content).frontmatter});let w=async(f)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:f},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${f}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:f}),null}},B=async(f)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await w(f)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await B("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",group:"network",section:"secondary",priority:14,rendererName:"SwotWidget",digestProvider:(f)=>{let{status:Y}=jkw.parse(f);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:st0,dataProvider:async()=>{let f=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!f)return{status:"generating"};let{frontmatter:Y}=tt0.parseSwotContent(f.content);return{status:"ready",...Y}}}}),{success:!0}});let $=async(f)=>{let{entityType:Y}=f.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await w("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",$),A.messaging.subscribe("entity:updated",$),A.messaging.subscribe("entity:deleted",$)}}function Ae0(){return new et0}wA();q5();L0();var jI$=new Vb,ow2=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string())}),sw2=Z.enum(["discovered","approved"]),Mkw=Z.object({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.string().url(),did:Z.string().optional(),status:sw2,discoveredAt:Z.string().datetime()}),xkw=N$.extend({entityType:Z.literal("agent"),metadata:Z.object({name:Z.string(),url:Z.string().url(),status:sw2,slug:Z.string()})}),Qe0=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),Okw=N$.extend({entityType:Z.literal("skill"),metadata:Qe0}),vkw=Z.object({about:Z.string(),skills:Z.array(ow2),notes:Z.string()});function Rkw(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((w)=>{let B=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${B}`}).join(`
|
|
10828
10828
|
`)}function hkw(A){if(!A.trim())return[];return A.split(`
|
|
10829
|
-
`).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map((w)=>w.trim()).filter(Boolean):[]}))}var Ckw=new $6(vkw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:Rkw,parser:hkw},{key:"notes",label:"Notes",type:"string"}]});class aw2 extends E2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:xkw,frontmatterSchema:Mkw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=Ckw.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 tw2 extends E2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:Okw,frontmatterSchema:Qe0})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Qe0);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var MI$=new aw2,xI$=new tw2,gkw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),OI$=Z.object({skills:Z.array(gkw),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),status:Z.enum(["discovered","approved"]),discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(ow2),notes:Z.string().default("")}))});var ykw=Z.object({}).strict();function yZ0(A={}){return ykw.parse(A),[Ae0()]}wA();L0();L0();var we0=Z.object({enabled:Z.boolean().default(!0),pdsEndpoint:Z.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:Z.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:Z.string().optional().describe("DID of the PDS repo that owns records"),appPassword:Z.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:Z.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:Z.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});L0();var Ekw=Z.looseObject({message:Z.string()}),Tkw=Z.looseObject({did:Z.string(),handle:Z.string(),accessJwt:Z.string(),refreshJwt:Z.string()}),Be0=Z.looseObject({uri:Z.string(),cid:Z.string()}),Skw=Be0.extend({value:Z.record(Z.string(),Z.unknown())}),mkw=Z.looseObject({$type:Z.literal("blob").optional(),ref:Z.looseObject({$link:Z.string()}),mimeType:Z.string(),size:Z.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),ukw=Z.looseObject({blob:mkw});function ckw(A){return A.replace(/\/+$/,"")}var lkw=(A,Q)=>fetch(A,Q);async function Ws(A,Q){let w=await A.text(),B;try{B=w.length>0?JSON.parse(w):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 $=Ekw.safeParse(B);throw Error($.success?$.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(B)}class Ks{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=ckw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??lkw}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 Ws(A,Tkw);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return Ws(w,Be0)}async putRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return Ws(w,Be0)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return Ws(w,Skw)}async uploadBlob(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return Ws(w,ukw)}async getSession(){return this.session??=await this.createSession(),this.session}}function vj(A){return A?.startsWith("did:web:")??!1}function EZ0(A){if(!vj(A))return;let Q=A.slice(8);if(!Q)return;let[w]=Q.split(":");if(!w)return;try{return decodeURIComponent(w)}catch{return w}}function A62(A){if(!vj(A))return;let Q=A.slice(8);if(!Q)return;let[,...w]=Q.split(":");if(w.length===0)return"/.well-known/did.json";return`/${w.map(($)=>{try{return decodeURIComponent($)}catch{return $}}).join("/")}/did.json`}function Q62(A){return A.replace(/\/+$/,"")}function Us(A){return`did:web:${encodeURIComponent(A)}`}function TZ0(A){return`${Us(A)}:anchor`}function $e0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function w62(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...$e0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:Q62(A.pdsEndpoint)}]}}function B62(A){if(!vj(A.brainDid))return null;return w62(A,A.brainDid)}function ew2(A,Q){if(!A||!Q)return;let w=EZ0(A),B=A62(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function SZ0(A){let Q=[],w=ew2(A.brainDid,B62(A));if(w)Q.push(w);if(vj(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=ew2(A.anchorDid,$e0(A.anchorDid));if(B)Q.push(B)}return Q}function fe0(A,Q){let w=[];if(!A.brainDid){let B=Us(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:w62(A,B)})}if(!A.anchorDid){let B=TZ0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:$e0(B)})}return w}function pkw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function ikw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function $62(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function f62(A,Q){let w=A[Q];if(!Array.isArray(w))return;let B=w.filter(($)=>typeof $==="string"&&$.length>0);return B.length>0?B:void 0}function dkw(A){let Q=A.metadata,w=$62(Q,"name"),B=$62(Q,"description");if(!w||!B)return;let $=f62(Q,"tags"),f=f62(Q,"examples");return{id:ikw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function nkw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>dkw(w)).filter((w)=>w!==void 0).slice(0,100)}async function Ye0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),Y=pkw(A.siteUrl??$.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let X=new URL(Y).hostname,H=Q.brainDid??Us(X),W=Q.anchorDid??TZ0(X);if(vj(H)){if(EZ0(H)!==X)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await nkw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:W,name:$.name,kind:$.kind},skills:K,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var Y62={name:"@brains/atproto",version:"0.2.0-alpha.163",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 X62=_6["ai.rizom.brain.card"],okw=Z.looseObject({did:Z.string()}),skw=Z.looseObject({service:Z.array(Z.looseObject({id:Z.string().optional(),type:Z.string().optional(),serviceEndpoint:Z.string().optional()})).optional()}),akw="ai.rizom.brain.card",tkw="self",Z62=50;class Xe0 extends Aw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",Y62,A,we0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??B8.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=SZ0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((B)=>B.path),...Q])].map((B)=>({path:B,method:"GET",public:!0,handler:($)=>{let f=new URL($.url).hostname,Y=[...SZ0(this.config),...fe0(this.config,f)].filter((H)=>H.path===B),X=Y.find((H)=>H.hostname===f)??Y[0];if(!X)return new Response("Not found",{status:404});return new Response(JSON.stringify(X.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await Ye0(A,this.config);gq(X62,w);let B=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...B&&{repo:B}};let $=this.resolveAppPassword();if(!this.config.identifier||!$)throw Error("AT Protocol publishing requires identifier and app password configuration");let f=this.createPdsClient($),Y=await f.createSession(),X=B??Y.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let H=await f.putRecord({repo:X,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:X,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((f)=>f.trim()))].filter((f)=>f.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>Z62)throw Error(`AT Protocol discovery accepts at most ${Z62} repos per batch`);let B=new Set,$=[];for(let f of w)try{let Y=await this.resolveRepoPdsEndpoint(f),X=this.createPublicPdsClient(Y.pdsEndpoint);if(!X.getRecord)throw Error("AT Protocol PDS client does not support record reads");let H=await X.getRecord({repo:Y.repoDid,collection:akw,rkey:tkw});gq(X62,H.value);let W=ALw(H.uri)??Y.repoDid,K=`${W}:${H.uri}:${H.cid}`;if(B.has(K)){$.push({repo:f,status:"skipped",repoDid:W,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(K),await A.messaging.send({type:ld,payload:{repoDid:W,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:W,uri:H.uri,cid:H.cid})}catch(Y){$.push({repo:f,status:"skipped",error:SA(Y)})}return{discovered:$.filter((f)=>f.status==="discovered").length,skipped:$.filter((f)=>f.status==="skipped").length,results:$}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:SA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let B=await this.findPublishEntity(A,Q),$=Q.entityId??Q.slug;if(!$)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!B)throw Error(`${Q.entityType} not found: ${$}`);if(B.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${$}`);let f=this.config.repoDid;if(Q.dryRun){let G=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return gq(w.lexicon,G),{record:G,dryRun:!0,...f&&{repo:f}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(Y),H=await X.createSession(),W=f??H.did,K=await w.buildRecord({entity:B,context:A,config:this.config,client:X,...Q.topics&&{topics:Q.topics}});if(gq(w.lexicon,K),!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await X.putRecord({repo:W,collection:w.collection,rkey:ekw(B.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:B,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:W,uri:U.uri,cid:U.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 Ks({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let w=await this.resolveDidToPdsEndpoint(Q);if(!w)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:w}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let w=await this.fetch(Q.toString());if(!w.ok)return;let B=okw.safeParse(await w.json());return B.success?B.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(QLw(A)):void 0,w=skw.safeParse(Q);if(!w.success)return;return w.data.service?.find(($)=>$.id==="#atproto_pds"||$.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 Ks({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function ekw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function ALw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function QLw(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...B]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if(B.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${B.join("/")}/did.json`}function mZ0(A,Q){return new Xe0(A,Q)}wA();L0();var uZ0={name:"@brains/rover",version:"0.2.0-alpha.163",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",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var BLw=Z.looseObject({});class H62 extends Aw{constructor(A={}){super("rover-profile",uZ0,A,BLw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",OL)}}function W62(A={}){return new H62(A)}wA();L0();xB();wA();wA();var Gs=Fz.extend(OL.shape);class cZ0{postsListUrl;decksListUrl;id="professional:homepage-list";name="Homepage List DataSource";description="Fetches profile, blog posts, and presentation decks for homepage";constructor(A,Q){this.postsListUrl=A,this.decksListUrl=Q}async fetch(A,Q,w){let B=w.entityService,[$,f,Y,X]=await Promise.all([IO(B,Gs),mf0(B,{entityType:"post",count:3,parse:mr}),mf0(B,{entityType:"deck",count:3,parse:nr}),Tr(B)]),H={profile:$,posts:f,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:zr0(X.cta),sections:X.sections??{}};return Q.parse(H)}}wA();class lZ0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let $={profile:await IO(w.entityService,Gs)};return Q.parse($)}}import{jsxDEV as CB,Fragment as YLw}from"preact/jsx-dev-runtime";var $Lw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",fLw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",Ze0=({number:A,title:Q,blurb:w,children:B})=>CB("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:CB("div",{className:"max-w-6xl mx-auto",children:CB("div",{className:$Lw,children:[CB(ki0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),CB("div",{className:fLw,"aria-hidden":"true"},void 0,!1,void 0,this),CB("div",{className:"mt-6 md:mt-0",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),He0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:Y})=>{let X=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})),W=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,X].find((q)=>q)??"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return CB(YLw,{children:[CB(dQ,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),CB("div",{className:"homepage-list bg-theme",children:[CB("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:CB("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&CB("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[CB("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),CB("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X&&CB("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:e70(X,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&CB("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:e70(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),CB(Ze0,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:CB(t70,{items:H,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),W.length>0&&CB(Ze0,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:CB(t70,{items:W,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&CB(Ze0,{number:"03",title:"About",blurb:Y.about?.blurb,children:CB("div",{className:"flex flex-col gap-8",children:[A.description&&CB("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&&CB(Li0,{subjects:A.expertise},void 0,!1,void 0,this),CB("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",CB("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),CB(Xi0,{cta:f,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as e6,Fragment as XLw}from"preact/jsx-dev-runtime";var We0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find(($)=>$)??"About page",B=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 e6(XLw,{children:[e6(dQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),e6("div",{className:"about-page bg-theme",children:[e6("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:e6("div",{className:"relative z-10 max-w-4xl mx-auto",children:[e6("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&&e6("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),e6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&e6("section",{className:"content-section-reveal mb-20 md:mb-28",children:e6(_9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&e6("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),e6("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>e6("li",{className:Cn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),e6("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&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),e6("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)&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),e6("div",{className:"space-y-4",children:[A.email&&e6("p",{className:"text-lg",children:e6("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&&e6("p",{className:"text-lg",children:e6("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&&e6("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>e6(L9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label?.length?$.label:$.platform},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as s4,Fragment as K62}from"preact/jsx-dev-runtime";var Ke0=()=>{return s4(K62,{children:[s4(dQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),s4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:s4("div",{className:"text-center max-w-md",children:[s4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),s4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),s4("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),s4(L9,{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)},Ue0=()=>{return s4(K62,{children:[s4(dQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),s4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:s4("div",{className:"text-center max-w-md",children:[s4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),s4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),s4("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),s4(L9,{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)};L0();var U62=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),ZLw={post:{label:"Post"},deck:{label:"Deck"}},G62=Z.object({entityDisplay:Z.object({post:U62,deck:U62}).default(ZLw).describe("Display metadata for post and deck entity types used by the homepage")});var D62={name:"@brains/site-professional",version:"0.2.0-alpha.163",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 WLw=Z.object({blurb:Z.string().optional().describe("Short italic subtitle under the section title")}),KLw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),z62=Z.looseObject({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),description:Z.string().optional(),avatar:Z.string().optional(),website:Z.string().optional(),email:Z.string().optional(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]),url:Z.string(),label:Z.string().optional()})).optional(),tagline:Z.string().optional(),intro:Z.string().optional(),story:Z.string().optional(),role:Z.string().optional(),audience:Z.string().optional(),expertise:Z.array(Z.string()).optional(),currentFocus:Z.string().optional(),availability:Z.string().optional(),desiredTone:Z.string().optional()}),ULw=Z.looseObject({id:Z.string(),entityType:Z.literal("post"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({excerpt:Z.string(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),seriesUrl:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional(),coverImageSrcset:Z.string().optional(),coverImageSizes:Z.string().optional()}),GLw=Z.looseObject({id:Z.string(),entityType:Z.literal("deck"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({title:Z.string(),description:Z.string().optional(),publishedAt:Z.string().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class Ge0 extends Aw{dependencies=["blog","decks"];constructor(A){super("professional-site",D62,A,G62)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,B=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${w.pluralName??w.label.toLowerCase()+"s"}`,f=new cZ0(B,$);A.entities.registerDataSource(f);let Y=new lZ0;A.entities.registerDataSource(Y);let X=Z.object({profile:z62,posts:Z.array(ULw),decks:Z.array(GLw),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:KLw,sections:Z.record(Z.string(),WLw)}),H=Z.object({profile:z62}),W=Z.object({});A.templates.register({"homepage-list":l1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:He0}}),about:l1({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:We0}}),"subscribe-thanks":l1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:W,requiredPermission:"public",layout:{component:Ke0}}),"subscribe-error":l1({name:"subscribe-error",description:"Newsletter subscription error page",schema:W,requiredPermission:"public",layout:{component:Ue0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function q62(A){return new Ge0(A??{})}var b62=[{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 pZ0}from"preact/jsx-dev-runtime";function V62({sections:A,siteInfo:Q,slots:w,wordmark:B}){return pZ0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[pZ0(Ki0,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...B!==void 0?{wordmark:B}:{}},void 0,!1,void 0,this),pZ0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),pZ0(Wi0,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:w?.getSlot("footer-top").map(($)=>$.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var DLw={layouts:{default:V62},routes:b62,plugin:q62,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"}}}},Ds=DLw;var J62=`/*
|
|
10829
|
+
`).map((Q)=>Q.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/)).filter((Q)=>Q!==null).map((Q)=>({name:Q[1]??"",description:Q[2]??"",tags:Q[3]?Q[3].split(",").map((w)=>w.trim()).filter(Boolean):[]}))}var Ckw=new $6(vkw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:Rkw,parser:hkw},{key:"notes",label:"Notes",type:"string"}]});class aw2 extends E2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:xkw,frontmatterSchema:Mkw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=Ckw.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 tw2 extends E2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:Okw,frontmatterSchema:Qe0})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Qe0);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var MI$=new aw2,xI$=new tw2,gkw=Z.object({name:Z.string(),description:Z.string(),tags:Z.array(Z.string()),examples:Z.array(Z.string())}),OI$=Z.object({skills:Z.array(gkw),agents:Z.array(Z.object({id:Z.string().optional(),name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),brainName:Z.string(),url:Z.url(),did:Z.string().optional(),status:Z.enum(["discovered","approved"]),discoveredAt:Z.string().datetime().optional(),about:Z.string(),skills:Z.array(ow2),notes:Z.string().default("")}))});var ykw=Z.object({}).strict();function yZ0(A={}){return ykw.parse(A),[Ae0()]}wA();L0();L0();var we0=Z.object({enabled:Z.boolean().default(!0),pdsEndpoint:Z.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:Z.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:Z.string().optional().describe("DID of the PDS repo that owns records"),appPassword:Z.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:Z.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:Z.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});L0();var Ekw=Z.looseObject({message:Z.string()}),Tkw=Z.looseObject({did:Z.string(),handle:Z.string(),accessJwt:Z.string(),refreshJwt:Z.string()}),Be0=Z.looseObject({uri:Z.string(),cid:Z.string()}),Skw=Be0.extend({value:Z.record(Z.string(),Z.unknown())}),mkw=Z.looseObject({$type:Z.literal("blob").optional(),ref:Z.looseObject({$link:Z.string()}),mimeType:Z.string(),size:Z.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),ukw=Z.looseObject({blob:mkw});function ckw(A){return A.replace(/\/+$/,"")}var lkw=(A,Q)=>fetch(A,Q);async function Ws(A,Q){let w=await A.text(),B;try{B=w.length>0?JSON.parse(w):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 $=Ekw.safeParse(B);throw Error($.success?$.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse(B)}class Ks{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=ckw(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??lkw}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 Ws(A,Tkw);return this.session=Q,Q}async createRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.createRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,...A.rkey&&{rkey:A.rkey},...A.validate!==void 0&&{validate:A.validate}})});return Ws(w,Be0)}async putRecord(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.putRecord`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":"application/json"},body:JSON.stringify({repo:A.repo,collection:A.collection,record:A.record,rkey:A.rkey,...A.validate!==void 0&&{validate:A.validate},...A.swapRecord!==void 0&&{swapRecord:A.swapRecord}})});return Ws(w,Be0)}async getRecord(A){let Q=new URLSearchParams({repo:A.repo,collection:A.collection,rkey:A.rkey}),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.getRecord?${Q.toString()}`,{method:"GET"});return Ws(w,Skw)}async uploadBlob(A){let Q=await this.getSession(),w=await this.fetchFn(`${this.pdsEndpoint}/xrpc/com.atproto.repo.uploadBlob`,{method:"POST",headers:{Authorization:`Bearer ${Q.accessJwt}`,"Content-Type":A.mimeType},body:new Blob([new Uint8Array(A.data)],{type:A.mimeType})});return Ws(w,ukw)}async getSession(){return this.session??=await this.createSession(),this.session}}function vj(A){return A?.startsWith("did:web:")??!1}function EZ0(A){if(!vj(A))return;let Q=A.slice(8);if(!Q)return;let[w]=Q.split(":");if(!w)return;try{return decodeURIComponent(w)}catch{return w}}function A62(A){if(!vj(A))return;let Q=A.slice(8);if(!Q)return;let[,...w]=Q.split(":");if(w.length===0)return"/.well-known/did.json";return`/${w.map(($)=>{try{return decodeURIComponent($)}catch{return $}}).join("/")}/did.json`}function Q62(A){return A.replace(/\/+$/,"")}function Us(A){return`did:web:${encodeURIComponent(A)}`}function TZ0(A){return`${Us(A)}:anchor`}function $e0(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function w62(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...$e0(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:Q62(A.pdsEndpoint)}]}}function B62(A){if(!vj(A.brainDid))return null;return w62(A,A.brainDid)}function ew2(A,Q){if(!A||!Q)return;let w=EZ0(A),B=A62(A);if(!w||!B)return;return{path:B,hostname:w,document:Q}}function SZ0(A){let Q=[],w=ew2(A.brainDid,B62(A));if(w)Q.push(w);if(vj(A.anchorDid)&&A.anchorDid!==A.brainDid){let B=ew2(A.anchorDid,$e0(A.anchorDid));if(B)Q.push(B)}return Q}function fe0(A,Q){let w=[];if(!A.brainDid){let B=Us(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:w62(A,B)})}if(!A.anchorDid){let B=TZ0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:$e0(B)})}return w}function pkw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function ikw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function $62(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function f62(A,Q){let w=A[Q];if(!Array.isArray(w))return;let B=w.filter(($)=>typeof $==="string"&&$.length>0);return B.length>0?B:void 0}function dkw(A){let Q=A.metadata,w=$62(Q,"name"),B=$62(Q,"description");if(!w||!B)return;let $=f62(Q,"tags"),f=f62(Q,"examples");return{id:ikw(w),name:w,description:B,...$&&{tags:$},...f&&{examples:f}}}async function nkw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>dkw(w)).filter((w)=>w!==void 0).slice(0,100)}async function Ye0(A,Q,w=new Date){let B=A.identity.get(),$=A.identity.getProfile(),f=await A.identity.getAppInfo(),Y=pkw(A.siteUrl??$.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let X=new URL(Y).hostname,H=Q.brainDid??Us(X),W=Q.anchorDid??TZ0(X);if(vj(H)){if(EZ0(H)!==X)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await nkw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:B.name,role:B.role,purpose:B.purpose,values:B.values},anchor:{did:W,name:$.name,kind:$.kind},skills:K,model:f.model,version:f.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var Y62={name:"@brains/atproto",version:"0.2.0-alpha.164",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 X62=_6["ai.rizom.brain.card"],okw=Z.looseObject({did:Z.string()}),skw=Z.looseObject({service:Z.array(Z.looseObject({id:Z.string().optional(),type:Z.string().optional(),serviceEndpoint:Z.string().optional()})).optional()}),akw="ai.rizom.brain.card",tkw="self",Z62=50;class Xe0 extends Aw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",Y62,A,we0);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??B8.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=SZ0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map((B)=>B.path),...Q])].map((B)=>({path:B,method:"GET",public:!0,handler:($)=>{let f=new URL($.url).hostname,Y=[...SZ0(this.config),...fe0(this.config,f)].filter((H)=>H.path===B),X=Y.find((H)=>H.hostname===f)??Y[0];if(!X)return new Response("Not found",{status:404});return new Response(JSON.stringify(X.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await Ye0(A,this.config);gq(X62,w);let B=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...B&&{repo:B}};let $=this.resolveAppPassword();if(!this.config.identifier||!$)throw Error("AT Protocol publishing requires identifier and app password configuration");let f=this.createPdsClient($),Y=await f.createSession(),X=B??Y.did;if(!f.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let H=await f.putRecord({repo:X,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:X,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((f)=>f.trim()))].filter((f)=>f.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>Z62)throw Error(`AT Protocol discovery accepts at most ${Z62} repos per batch`);let B=new Set,$=[];for(let f of w)try{let Y=await this.resolveRepoPdsEndpoint(f),X=this.createPublicPdsClient(Y.pdsEndpoint);if(!X.getRecord)throw Error("AT Protocol PDS client does not support record reads");let H=await X.getRecord({repo:Y.repoDid,collection:akw,rkey:tkw});gq(X62,H.value);let W=ALw(H.uri)??Y.repoDid,K=`${W}:${H.uri}:${H.cid}`;if(B.has(K)){$.push({repo:f,status:"skipped",repoDid:W,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}B.add(K),await A.messaging.send({type:ld,payload:{repoDid:W,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),$.push({repo:f,status:"discovered",repoDid:W,uri:H.uri,cid:H.cid})}catch(Y){$.push({repo:f,status:"skipped",error:SA(Y)})}return{discovered:$.filter((f)=>f.status==="discovered").length,skipped:$.filter((f)=>f.status==="skipped").length,results:$}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:SA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let B=await this.findPublishEntity(A,Q),$=Q.entityId??Q.slug;if(!$)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!B)throw Error(`${Q.entityType} not found: ${$}`);if(B.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${$}`);let f=this.config.repoDid;if(Q.dryRun){let G=await w.buildRecord({entity:B,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return gq(w.lexicon,G),{record:G,dryRun:!0,...f&&{repo:f}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(Y),H=await X.createSession(),W=f??H.did,K=await w.buildRecord({entity:B,context:A,config:this.config,client:X,...Q.topics&&{topics:Q.topics}});if(gq(w.lexicon,K),!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await X.putRecord({repo:W,collection:w.collection,rkey:ekw(B.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:B,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:W,uri:U.uri,cid:U.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 Ks({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""})}async resolveRepoPdsEndpoint(A){let Q=A.startsWith("did:")?A:await this.resolveHandleToDid(A);if(!Q)throw Error(`Could not resolve AT Protocol repo: ${A}`);let w=await this.resolveDidToPdsEndpoint(Q);if(!w)throw Error(`Could not resolve AT Protocol PDS for repo: ${Q}`);return{repoDid:Q,pdsEndpoint:w}}async resolveHandleToDid(A){let Q=new URL("/xrpc/com.atproto.identity.resolveHandle",this.config.pdsEndpoint);Q.searchParams.set("handle",A);let w=await this.fetch(Q.toString());if(!w.ok)return;let B=okw.safeParse(await w.json());return B.success?B.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(QLw(A)):void 0,w=skw.safeParse(Q);if(!w.success)return;return w.data.service?.find(($)=>$.id==="#atproto_pds"||$.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 Ks({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function ekw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function ALw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function QLw(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...B]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if(B.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${B.join("/")}/did.json`}function mZ0(A,Q){return new Xe0(A,Q)}wA();L0();var uZ0={name:"@brains/rover",version:"0.2.0-alpha.164",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",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var BLw=Z.looseObject({});class H62 extends Aw{constructor(A={}){super("rover-profile",uZ0,A,BLw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",OL)}}function W62(A={}){return new H62(A)}wA();L0();xB();wA();wA();var Gs=Fz.extend(OL.shape);class cZ0{postsListUrl;decksListUrl;id="professional:homepage-list";name="Homepage List DataSource";description="Fetches profile, blog posts, and presentation decks for homepage";constructor(A,Q){this.postsListUrl=A,this.decksListUrl=Q}async fetch(A,Q,w){let B=w.entityService,[$,f,Y,X]=await Promise.all([IO(B,Gs),mf0(B,{entityType:"post",count:3,parse:mr}),mf0(B,{entityType:"deck",count:3,parse:nr}),Tr(B)]),H={profile:$,posts:f,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:zr0(X.cta),sections:X.sections??{}};return Q.parse(H)}}wA();class lZ0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let $={profile:await IO(w.entityService,Gs)};return Q.parse($)}}import{jsxDEV as CB,Fragment as YLw}from"preact/jsx-dev-runtime";var $Lw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",fLw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",Ze0=({number:A,title:Q,blurb:w,children:B})=>CB("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:CB("div",{className:"max-w-6xl mx-auto",children:CB("div",{className:$Lw,children:[CB(ki0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),CB("div",{className:fLw,"aria-hidden":"true"},void 0,!1,void 0,this),CB("div",{className:"mt-6 md:mt-0",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),He0=({profile:A,posts:Q,decks:w,postsListUrl:B,decksListUrl:$,cta:f,sections:Y})=>{let X=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})),W=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,X].find((q)=>q)??"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return CB(YLw,{children:[CB(dQ,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),CB("div",{className:"homepage-list bg-theme",children:[CB("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:CB("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&CB("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[CB("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),CB("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X&&CB("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:e70(X,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&CB("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:e70(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),CB(Ze0,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:CB(t70,{items:H,viewAllUrl:B,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),W.length>0&&CB(Ze0,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:CB(t70,{items:W,viewAllUrl:$,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&CB(Ze0,{number:"03",title:"About",blurb:Y.about?.blurb,children:CB("div",{className:"flex flex-col gap-8",children:[A.description&&CB("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&&CB(Li0,{subjects:A.expertise},void 0,!1,void 0,this),CB("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",CB("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),CB(Xi0,{cta:f,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as e6,Fragment as XLw}from"preact/jsx-dev-runtime";var We0=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find(($)=>$)??"About page",B=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 e6(XLw,{children:[e6(dQ,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),e6("div",{className:"about-page bg-theme",children:[e6("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:e6("div",{className:"relative z-10 max-w-4xl mx-auto",children:[e6("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&&e6("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),e6("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&e6("section",{className:"content-section-reveal mb-20 md:mb-28",children:e6(_9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&e6("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),e6("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map(($,f)=>e6("li",{className:Cn({variant:"accent",size:"lg"}),children:$},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),e6("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&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),e6("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)&&e6("section",{children:[e6("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),e6("div",{className:"space-y-4",children:[A.email&&e6("p",{className:"text-lg",children:e6("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&&e6("p",{className:"text-lg",children:e6("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&&e6("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map(($,f)=>e6(L9,{href:$.url,external:!0,variant:"secondary",size:"md",children:$.label?.length?$.label:$.platform},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as s4,Fragment as K62}from"preact/jsx-dev-runtime";var Ke0=()=>{return s4(K62,{children:[s4(dQ,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),s4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:s4("div",{className:"text-center max-w-md",children:[s4("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),s4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),s4("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),s4(L9,{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)},Ue0=()=>{return s4(K62,{children:[s4(dQ,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),s4("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:s4("div",{className:"text-center max-w-md",children:[s4("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),s4("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),s4("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),s4(L9,{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)};L0();var U62=Z.object({label:Z.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:Z.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),ZLw={post:{label:"Post"},deck:{label:"Deck"}},G62=Z.object({entityDisplay:Z.object({post:U62,deck:U62}).default(ZLw).describe("Display metadata for post and deck entity types used by the homepage")});var D62={name:"@brains/site-professional",version:"0.2.0-alpha.164",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 WLw=Z.object({blurb:Z.string().optional().describe("Short italic subtitle under the section title")}),KLw=Z.object({heading:Z.string(),buttonText:Z.string(),buttonLink:Z.string()}),z62=Z.looseObject({name:Z.string(),kind:Z.enum(["professional","team","collective"]),organization:Z.string().optional(),description:Z.string().optional(),avatar:Z.string().optional(),website:Z.string().optional(),email:Z.string().optional(),socialLinks:Z.array(Z.object({platform:Z.enum(["github","instagram","linkedin","email","website"]),url:Z.string(),label:Z.string().optional()})).optional(),tagline:Z.string().optional(),intro:Z.string().optional(),story:Z.string().optional(),role:Z.string().optional(),audience:Z.string().optional(),expertise:Z.array(Z.string()).optional(),currentFocus:Z.string().optional(),availability:Z.string().optional(),desiredTone:Z.string().optional()}),ULw=Z.looseObject({id:Z.string(),entityType:Z.literal("post"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({excerpt:Z.string(),seriesName:Z.string().optional(),seriesIndex:Z.number().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),seriesUrl:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional(),coverImageSrcset:Z.string().optional(),coverImageSizes:Z.string().optional()}),GLw=Z.looseObject({id:Z.string(),entityType:Z.literal("deck"),content:Z.string(),created:Z.string(),updated:Z.string(),contentHash:Z.string(),metadata:Z.looseObject({title:Z.string(),publishedAt:Z.string().optional()}),frontmatter:Z.looseObject({title:Z.string(),description:Z.string().optional(),publishedAt:Z.string().optional()}),body:Z.string(),url:Z.string().optional(),typeLabel:Z.string().optional(),listUrl:Z.string().optional(),listLabel:Z.string().optional(),coverImageUrl:Z.string().optional(),ogImageUrl:Z.string().optional(),coverImageWidth:Z.number().optional(),coverImageHeight:Z.number().optional()});class Ge0 extends Aw{dependencies=["blog","decks"];constructor(A){super("professional-site",D62,A,G62)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,B=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,$=`/${w.pluralName??w.label.toLowerCase()+"s"}`,f=new cZ0(B,$);A.entities.registerDataSource(f);let Y=new lZ0;A.entities.registerDataSource(Y);let X=Z.object({profile:z62,posts:Z.array(ULw),decks:Z.array(GLw),postsListUrl:Z.string(),decksListUrl:Z.string(),cta:KLw,sections:Z.record(Z.string(),WLw)}),H=Z.object({profile:z62}),W=Z.object({});A.templates.register({"homepage-list":l1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:X,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:He0}}),about:l1({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:We0}}),"subscribe-thanks":l1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:W,requiredPermission:"public",layout:{component:Ke0}}),"subscribe-error":l1({name:"subscribe-error",description:"Newsletter subscription error page",schema:W,requiredPermission:"public",layout:{component:Ue0}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function q62(A){return new Ge0(A??{})}var b62=[{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 pZ0}from"preact/jsx-dev-runtime";function V62({sections:A,siteInfo:Q,slots:w,wordmark:B}){return pZ0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[pZ0(Ki0,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...B!==void 0?{wordmark:B}:{}},void 0,!1,void 0,this),pZ0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),pZ0(Wi0,{primaryNavigation:Q.navigation.primary,secondaryNavigation:Q.navigation.secondary,copyright:Q.copyright,socialLinks:Q.socialLinks,title:Q.title,tagline:Q.description,children:w?.getSlot("footer-top").map(($)=>$.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var DLw={layouts:{default:V62},routes:b62,plugin:q62,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"}}}},Ds=DLw;var J62=`/*
|
|
10830
10830
|
* Default theme \u2014 simplified editorial base inspired by the Rizom family.
|
|
10831
10831
|
*
|
|
10832
10832
|
* This theme is intentionally less branded than @brains/theme-rizom. It
|
|
@@ -13704,7 +13704,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});L0();var P
|
|
|
13704
13704
|
`);return this.truncateContent(B||Q||fE(A))}truncateContent(A){if(A.length<=UB2)return A;let Q=A.slice(0,UB2-1),w=Q.search(/\s\S*$/);return`${(w>0?Q.slice(0,w):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===x8}isDecisionEntity(A){return A.entityType===tZ}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return CU(Q)}}var ANw=5,QNw=3;function Ne0(A){A.messaging.subscribe(nk,async(Q)=>{let w=YS.parse(Q.payload);return{success:!0,data:await XH0(A,w)}})}async function XH0(A,Q){let w=Y$(Q.userPermissionLevel);if(!Q.channelId)return GB2(A,Q,{visibilityScope:w,reason:"no-channel-context",items:[]}),{items:[]};let B=new YE(A),$=await B.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:ANw,visibilityScope:w}),f=$.results.length===0?await B.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:QNw,visibilityScope:w}):void 0,Y=$.results.length>0,X=Y?$.results:f?.results??[];return GB2(A,Q,{visibilityScope:w,spaceId:$.spaceId??f?.spaceId,reason:X.length>0?"memory-injected":"no-same-space-memory",items:X.map((H)=>wNw(H,Y))}),{items:X.map(BNw)}}function GB2(A,Q,w){A.logger.info("Conversation memory agent context audit",{conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,channelName:Q.channelName,userPermissionLevel:Q.userPermissionLevel,visibilityScope:w.visibilityScope,spaceId:w.spaceId,reason:w.reason,itemCount:w.items.length,items:w.items})}function wNw(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 BNw(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}}}L0();yX();var qB2=Z.union([Z.enum(["public","shared","restricted"]),Z.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),bB2=Z.enum(["user","assistant"]),$Nw=Z.object({actorId:Z.string(),canonicalId:Z.string().optional(),interfaceType:Z.string(),role:bB2,displayName:Z.string().optional(),username:Z.string().optional(),isBot:Z.boolean().optional()}),fNw=Z.object({messageId:Z.string().optional(),channelId:Z.string().optional(),channelName:Z.string().optional(),threadId:Z.string().optional(),metadata:Z.record(Z.string(),Z.unknown()).optional()}),je0=Z.object({role:bB2,content:Z.string(),timestamp:Z.string().datetime().optional(),actor:$Nw.optional(),source:fNw.optional()}),YNw=Z.object({conversationId:Z.string().default("eval-conversation"),messages:Z.array(je0)}),XNw=Z.object({conversationId:Z.string()}),ZNw=Z.object({conversationId:Z.string().default("eval-conversation"),interfaceType:Z.string().default("eval"),channelId:Z.string().default("eval-channel"),channelName:Z.string().optional(),projectionDecision:Z.enum(["update","append"]).default("update"),existingSummary:Z.string().optional(),existingMessageCount:Z.number().int().min(0).default(0),messages:Z.array(je0)}),ZH0=Z.object({actorId:Z.string(),canonicalId:Z.string().optional(),displayName:Z.string().optional()}),HNw=ZH0.extend({roles:Z.array(Z.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:Z.array(Z.string()).optional()}),WNw=Z.object({actorId:Z.string().optional(),canonicalId:Z.string().optional(),displayName:Z.string()}),VB2=Z.object({id:Z.string(),entityType:Z.enum(["summary","decision","action-item"]),content:Z.string(),excerpt:Z.string().optional(),score:Z.number().optional(),conversationId:Z.string(),interfaceType:Z.string(),channelId:Z.string(),channelName:Z.string().optional(),updated:Z.string().datetime().optional(),visibility:qB2,status:Z.string().optional(),participants:Z.array(HNw).optional(),decidedBy:Z.array(ZH0).optional(),mentionedBy:Z.array(ZH0).optional(),assignedTo:Z.array(WNw).optional(),requestedBy:Z.array(ZH0).optional()}),KNw=Z.object({query:Z.string().optional(),conversationId:Z.string().optional(),interfaceType:Z.string().optional(),channelId:Z.string().optional(),limit:Z.number().int().min(1).optional(),includeOtherSpaces:Z.boolean().optional(),actorId:Z.string().optional(),canonicalId:Z.string().optional(),visibilityScope:qB2.optional(),memory:Z.array(VB2).optional()}),UNw=Z.object({conversationId:Z.string().default("eval-conversation"),message:Z.string(),interfaceType:Z.string().default("eval"),channelId:Z.string().optional(),channelName:Z.string().optional(),userPermissionLevel:Z.enum(["anchor","trusted","public"]).default("trusted"),memory:Z.array(VB2).optional()}),GNw=Z.object({conversationId:Z.string().default("eval-conversation"),existingSummary:Z.string().optional(),existingMessageCount:Z.number().int().min(0).default(0),messages:Z.array(je0)});function JB2(A){let{context:Q,logger:w,config:B}=A;Q.eval.registerHandler("summarizeMessages",async($)=>{let f=YNw.parse($),Y=Pe0(f.messages,f.conversationId),H=await new wE(Q,w,B).extract(Y);return H.entries.map((W)=>{let K=H.decisions.filter((G)=>G.timeRange.start>=W.timeRange.start).filter((G)=>G.timeRange.end<=W.timeRange.end).map((G)=>G.text),U=H.actionItems.filter((G)=>G.timeRange.start>=W.timeRange.start).filter((G)=>G.timeRange.end<=W.timeRange.end).map((G)=>G.text);return{...W,decisions:K,actionItems:U,keyPointsText:W.keyPoints.join(`
|
|
13705
13705
|
`),decisionsText:K.join(`
|
|
13706
13706
|
`),actionItemsText:U.join(`
|
|
13707
|
-
`)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=GNw.parse($),Y=Pe0(f.messages,f.conversationId),X=f.existingSummary?DB2({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new lF(Q,w,B).decideProjection(Y,X)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=KNw.parse($),Y=f.memory?zB2(Q,f.memory):Q;return new YE(Y).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=UNw.parse($),Y=f.memory?zB2(Q,f.memory):Q;return XH0(Y,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=ZNw.parse($),Y=Pe0(f.messages,f.conversationId),X=DNw({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:Y}),H=f.existingSummary?DB2({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,W=[],K=[],U=zNw({context:Q,conversation:X,messages:Y,existing:H,upserted:W,deleted:K,projectionDecision:f.projectionDecision});return{result:await new lF(U,w,B).projectConversation(f.conversationId),summaries:W.filter((b)=>b.entityType==="summary"),decisions:W.filter((b)=>b.entityType==="decision"),actionItems:W.filter((b)=>b.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=XNw.parse($);return new lF(Q,w,B).projectConversation(f.conversationId)})}function DB2(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 Pe0(A,Q){return A.map((w,B)=>{let $=w.timestamp??new Date(Date.UTC(2026,0,1,0,B)).toISOString();return{id:`eval-message-${B+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:$,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function DNw(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],B=Q?.timestamp??"2026-01-01T00:00:00.000Z",$=w?.timestamp??B;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:B,lastActiveAt:$,createdAt:B,updatedAt:$,metadata:{}}}function zNw(A){let Q=CU(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:w})=>w==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async(w)=>{return A.deleted.push(w),!0},upsertEntity:async({entity:w})=>{return A.upserted.push(w),{entityId:w.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function zB2(A,Q){let w=Q.map(qNw),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??fE($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function qNw(A){if(A.entityType==="summary")return bNw(A);if(A.entityType==="decision")return VNw(A);return JNw(A)}function Me0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:f6(A.content),visibility:A.visibility,created:Q,updated:Q}}function bNw(A){return{...Me0(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 VNw(A){return{...Me0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:CU(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 JNw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Me0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:CU(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 IB2={name:"@brains/conversation-memory",version:"0.2.0-alpha.163",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 FNw=new RW,kNw=new ey,LNw=new AE,_Nw=Z.object({conversationId:Z.string()});class xe0 extends sQ{entityType=x8;schema=qs;adapter=FNw;constructor(A={}){super(sZ0,IB2,A,Fe0)}getConfig(){return this.config}getTemplates(){return{"summary-list":p62,"summary-detail":i62,"ai-response":d62}}getDataSources(){return[new _e0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:x8,job:{type:C62,handler:new wH0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await kL(A,x8,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:be0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:sZ0}}},sourceChange:{sourceKind:mS,sourceTypes:[mS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[cx],jobData:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:w,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:be0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:sZ0}}}}}]}parseConversationMessagePayload(A){return _Nw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return gj({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(tZ,bs,kNw),A.entities.register(vW,Vs,LNw),o62({context:A,pluginId:this.id}),a62({context:A,pluginId:this.id}),XB2({context:A,pluginId:this.id}),WB2({context:A,pluginId:this.id,config:this.config}),Ne0(A),JB2({context:A,logger:this.logger,config:this.config})}}function Oe0(A={}){return new xe0(A)}wA();L0();L0();q5();var FB2=Z.object({label:Z.string(),href:Z.string()}),kB2=Z.object({label:Z.string(),title:Z.string(),detail:Z.string()}),NNw=Z.object({eyebrow:Z.string(),name:Z.string(),sub:Z.string()}),PNw=Z.object({tone:Z.enum(["capture","synthesis","share"]),title:Z.string(),text:Z.string()}),ve0=Z.object({captures:Z.number(),links:Z.number(),topics:Z.number(),summaries:Z.number(),peers:Z.number()}),XE=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:FB2,secondaryCta:FB2,inputs:Z.array(kB2).min(1),outputs:Z.array(kB2).min(1),core:NNw,legend:Z.array(PNw).min(1)}),Re0=XE.extend({counts:ve0}),LB2={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."}]},_B2=new $6(XE,{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 HH0(A){return _B2.parse(A)}function NB2(A){return _B2.format(A)}L0();var jNw=Z.looseObject({query:Z.object({routeId:Z.string().default("home"),sectionId:Z.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),MNw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class he0{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,w){let B=jNw.parse(A??{}),$=await this.fetchContent(w,B.query.routeId,B.query.sectionId),f=await this.fetchCounts(w);return Q.parse({...$,counts:f})}async fetchContent(A,Q,w){let B=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!B?.content)return LB2;return XE.parse(HH0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(MNw).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return ve0.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 D1}from"preact/jsx-dev-runtime";var PB2=Z.object({label:Z.string(),href:Z.string()}),xNw=Z.object({label:Z.string(),value:Z.string(),note:Z.string()}),ONw=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:PB2,secondaryCta:PB2,signals:Z.array(xNw)}),vNw=Z.object({phase:Z.string(),title:Z.string(),text:Z.string()}),RNw=Z.object({eyebrow:Z.string(),title:Z.string(),intro:Z.string(),steps:Z.array(vNw)}),hNw=Z.object({label:Z.string(),title:Z.string(),text:Z.string()}),CNw=Z.object({title:Z.string(),intro:Z.string(),cards:Z.array(hNw)}),gNw=Z.object({title:Z.string(),intro:Z.string(),points:Z.array(Z.string())}),yNw={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."]},ENw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function jB2({href:A,label:Q}){return D1("a",{href:A,className:ENw,children:Q},void 0,!1,void 0,this)}function TNw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return D1(oy,{children:[D1("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:[D1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[D1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),D1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),D1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex items-center gap-5 md:gap-8",children:[D1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>D1(jB2,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),D1("a",{href:B.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:B.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("main",{children:Q},void 0,!1,void 0,this),D1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:D1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),D1("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),D1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>D1(jB2,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),D1("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 SNw=({sections:A,siteInfo:Q})=>D1(TNw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function mNw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return D1(cF,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:D1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[D1(hj,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(hj,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("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:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),D1("div",{className:"mt-5 grid gap-3",children:f.map((Y)=>D1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[D1("div",{className:"flex items-center justify-between gap-4",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),D1("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),D1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),D1("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 uNw({eyebrow:A,title:Q,intro:w,steps:B}){return D1(cF,{id:"operating-loop",className:"py-section",children:[D1("div",{className:"max-w-[840px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),D1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>D1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[D1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),D1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function cNw({title:A,intro:Q,cards:w}){return D1(cF,{className:"py-section",children:D1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:D1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[D1("div",{children:[D1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),D1("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),D1("div",{className:"grid gap-4",children:w.map((B)=>D1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),D1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function lNw({title:A,intro:Q,points:w}){return D1(cF,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[D1("div",{className:"max-w-[920px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),D1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),D1("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),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>D1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:B},B,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var pNw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},iNw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),Fs=(A,Q,w=`${Q}s`)=>`${iNw(A)} ${A===1?Q:w}`;function dNw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:Y,core:X,legend:H,counts:W}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:Fs(W.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:Fs(W.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:Fs(W.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:Fs(W.summaries,"summary","summaries")}];return D1(cF,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[D1("div",{className:"mx-auto max-w-[1040px] text-center",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[D1(hj,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(hj,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("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:[D1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[D1("div",{className:"flex flex-col gap-3.5",children:f.map((U)=>D1("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:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),D1("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:[D1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),D1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),K.map((U)=>D1("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 ${U.className}`,children:U.label},U.key,!1,void 0,this)),D1("div",{className:"relative z-[1] px-6 text-center",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:X.eyebrow},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:X.name},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:X.sub},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[Fs(W.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-col gap-3.5",children:Y.map((U)=>D1("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:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((U)=>D1("div",{className:"text-left",children:[D1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[D1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${pNw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),D1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var nNw=l1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:Re0,formatter:{parse:(A)=>Re0.parse({...HH0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>NB2(XE.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:dNw}}),rNw=(A)=>mNw(ONw.parse(A)),oNw=(A)=>uNw(RNw.parse(A)),sNw=(A)=>cNw(CNw.parse(A)),aNw=(A)=>lNw(gNw.parse(A)),MB2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},xB2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:rNw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...MB2,label:"Primary CTA"},secondaryCta:{...MB2,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:oNw,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:sNw,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:aNw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},tNw=[{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:yNw}]}],OB2=qe0({packageName:"@brains/relay/site",themeProfile:"studio",layout:SNw,routes:tNw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":nNw},dataSources:[new he0]}});var vB2={name:"@brains/relay",version:"0.2.0-alpha.163",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 RB2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],hB2=[...RB2,"image","site-info","site-content","site-builder"],QPw=[...hB2,"docs","decks"],wPw=["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."],BPw=zJ({name:"relay",version:vB2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:OB2,theme:ay,presets:{core:RB2,default:hB2,full:QPw},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:wPw,capabilities:[["prompt",Pj,void 0],["note",Wj,{}],["link",Uj,{}],["image",uc,void 0],["topics",qX0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",Oe0,{memoryVisibility:"shared"}],["docs",ar,void 0],["decks",rr,void 0],["agents",PZ0,void 0],["assessment",yZ0,void 0],["auth-service",vp,void 0],["notifications",QB0,void 0],["email-resend",e90,void 0],["cms",Jj,{}],["dashboard",mF,void 0],["directory-sync",UP,{seedContent:!0,seedContentPath:APw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",sP,{definitions:xB2}],["rizom-ecosystem",jj,void 0],["site-info",aP,void 0],["site-builder",oP,{}]],interfaces:[["mcp",AI,()=>({})],["discord",SI,()=>({captureUrls:!0})],["a2a",uC,()=>({})],["webserver",iI,()=>({})],["web-chat",mC,()=>({})]],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"}}}),CB2=BPw;import{readFileSync as Txw}from"fs";import{join as Sxw}from"path";import{execSync as mxw}from"child_process";import{parseArgs as YPw}from"util";var XPw={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 gU(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function pF(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function gB2(A){let{values:Q,positionals:w}=YPw({args:A,options:XPw,allowPositionals:!0,strict:!1});if(Q.help)return{command:"help",args:[],flags:{help:!0}};if(Q.version)return{command:"version",args:[],flags:{version:!0}};return{command:w[0]??"help",args:w.slice(1),flags:{model:gU(Q,"model"),domain:gU(Q,"domain"),"content-repo":gU(Q,"content-repo"),backend:gU(Q,"backend"),"push-to":gU(Q,"push-to"),"ai-api-key":gU(Q,"ai-api-key"),"no-interactive":pF(Q,"no-interactive"),preview:pF(Q,"preview"),deploy:pF(Q,"deploy"),regen:pF(Q,"regen"),all:pF(Q,"all"),only:gU(Q,"only"),"dry-run":pF(Q,"dry-run"),"startup-check":pF(Q,"startup-check"),"storage-dir":gU(Q,"storage-dir"),yes:pF(Q,"yes"),remote:gU(Q,"remote"),token:gU(Q,"token"),outputDir:gU(Q,"outputDir")}}}ks();import{mkdirSync as Mxw}from"fs";import{join as xxw}from"path";import{execSync as Oxw}from"child_process";var KH0={name:"@rizom/brain",version:"0.2.0-alpha.163",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 sB2,writeFileSync as _s,chmodSync as Ns,existsSync as le0,readFileSync as pe0}from"fs";import{basename as ie0,dirname as de0,join as m$,resolve as uPw}from"path";import{fileURLToPath as cPw}from"url";var yB2=`ARG BUN_VERSION=1.3.10
|
|
13707
|
+
`)}})}),Q.eval.registerHandler("decideProjection",async($)=>{let f=GNw.parse($),Y=Pe0(f.messages,f.conversationId),X=f.existingSummary?DB2({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null;return new lF(Q,w,B).decideProjection(Y,X)}),Q.eval.registerHandler("retrieveMemory",async($)=>{let f=KNw.parse($),Y=f.memory?zB2(Q,f.memory):Q;return new YE(Y).retrieve(f)}),Q.eval.registerHandler("buildAgentContext",async($)=>{let f=UNw.parse($),Y=f.memory?zB2(Q,f.memory):Q;return XH0(Y,f)}),Q.eval.registerHandler("projectMessages",async($)=>{let f=ZNw.parse($),Y=Pe0(f.messages,f.conversationId),X=DNw({conversationId:f.conversationId,interfaceType:f.interfaceType,channelId:f.channelId,channelName:f.channelName,messages:Y}),H=f.existingSummary?DB2({conversationId:f.conversationId,content:f.existingSummary,messageCount:f.existingMessageCount,projectionVersion:B.projectionVersion,visibility:B.memoryVisibility}):null,W=[],K=[],U=zNw({context:Q,conversation:X,messages:Y,existing:H,upserted:W,deleted:K,projectionDecision:f.projectionDecision});return{result:await new lF(U,w,B).projectConversation(f.conversationId),summaries:W.filter((b)=>b.entityType==="summary"),decisions:W.filter((b)=>b.entityType==="decision"),actionItems:W.filter((b)=>b.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async($)=>{let f=XNw.parse($);return new lF(Q,w,B).projectConversation(f.conversationId)})}function DB2(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 Pe0(A,Q){return A.map((w,B)=>{let $=w.timestamp??new Date(Date.UTC(2026,0,1,0,B)).toISOString();return{id:`eval-message-${B+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:$,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function DNw(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],B=Q?.timestamp??"2026-01-01T00:00:00.000Z",$=w?.timestamp??B;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:B,lastActiveAt:$,createdAt:B,updatedAt:$,metadata:{}}}function zNw(A){let Q=CU(A.conversation);return{...A.context,spaces:[Q],conversations:{...A.context.conversations,get:async()=>A.conversation,getMessages:async()=>A.messages},ai:{...A.context.ai,generateObject:async()=>({object:{decision:A.projectionDecision,rationale:"Forced by eval input"}})},entityService:{...A.context.entityService,getEntity:async({entityType:w})=>w==="summary"?A.existing:null,listEntities:async()=>[],deleteEntity:async(w)=>{return A.deleted.push(w),!0},upsertEntity:async({entity:w})=>{return A.upserted.push(w),{entityId:w.id,jobId:"eval-upsert",created:!0,skipped:!1}}}}}function zB2(A,Q){let w=Q.map(qNw),B=w.map(($,f)=>({entity:$,score:Q[f]?.score??1,excerpt:Q[f]?.excerpt??fE($)}));return{...A,entityService:{...A.entityService,search:async()=>B,listEntities:async({entityType:$})=>w.filter((f)=>f.entityType===$)}}}function qNw(A){if(A.entityType==="summary")return bNw(A);if(A.entityType==="decision")return VNw(A);return JNw(A)}function Me0(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:f6(A.content),visibility:A.visibility,created:Q,updated:Q}}function bNw(A){return{...Me0(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 VNw(A){return{...Me0(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:CU(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 JNw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...Me0(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:CU(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 IB2={name:"@brains/conversation-memory",version:"0.2.0-alpha.164",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 FNw=new RW,kNw=new ey,LNw=new AE,_Nw=Z.object({conversationId:Z.string()});class xe0 extends sQ{entityType=x8;schema=qs;adapter=FNw;constructor(A={}){super(sZ0,IB2,A,Fe0)}getConfig(){return this.config}getTemplates(){return{"summary-list":p62,"summary-detail":i62,"ai-response":d62}}getDataSources(){return[new _e0(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:x8,job:{type:C62,handler:new wH0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await kL(A,x8,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:be0,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:sZ0}}},sourceChange:{sourceKind:mS,sourceTypes:[mS],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[cx],jobData:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{mode:"conversation",conversationId:w,reason:"message-added"}},jobOptions:(Q)=>{let{conversationId:w}=this.parseConversationMessagePayload(Q);return{priority:5,delayMs:this.config.projectionDelayMs,source:be0,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:sZ0}}}}}]}parseConversationMessagePayload(A){return _Nw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),B=await A.conversations.get(w);if(!B)return!1;return gj({conversation:B,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(tZ,bs,kNw),A.entities.register(vW,Vs,LNw),o62({context:A,pluginId:this.id}),a62({context:A,pluginId:this.id}),XB2({context:A,pluginId:this.id}),WB2({context:A,pluginId:this.id,config:this.config}),Ne0(A),JB2({context:A,logger:this.logger,config:this.config})}}function Oe0(A={}){return new xe0(A)}wA();L0();L0();q5();var FB2=Z.object({label:Z.string(),href:Z.string()}),kB2=Z.object({label:Z.string(),title:Z.string(),detail:Z.string()}),NNw=Z.object({eyebrow:Z.string(),name:Z.string(),sub:Z.string()}),PNw=Z.object({tone:Z.enum(["capture","synthesis","share"]),title:Z.string(),text:Z.string()}),ve0=Z.object({captures:Z.number(),links:Z.number(),topics:Z.number(),summaries:Z.number(),peers:Z.number()}),XE=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:FB2,secondaryCta:FB2,inputs:Z.array(kB2).min(1),outputs:Z.array(kB2).min(1),core:NNw,legend:Z.array(PNw).min(1)}),Re0=XE.extend({counts:ve0}),LB2={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."}]},_B2=new $6(XE,{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 HH0(A){return _B2.parse(A)}function NB2(A){return _B2.format(A)}L0();var jNw=Z.looseObject({query:Z.object({routeId:Z.string().default("home"),sectionId:Z.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),MNw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class he0{id="relay-site:home-counts";name="Relay homepage counts";description="Fetches Relay homepage content and live entity counts for the system diagram";async fetch(A,Q,w){let B=jNw.parse(A??{}),$=await this.fetchContent(w,B.query.routeId,B.query.sectionId),f=await this.fetchCounts(w);return Q.parse({...$,counts:f})}async fetchContent(A,Q,w){let B=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!B?.content)return LB2;return XE.parse(HH0(B.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(MNw).map(async([w,B])=>[w,await this.countOrZero(A,B)]));return ve0.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 D1}from"preact/jsx-dev-runtime";var PB2=Z.object({label:Z.string(),href:Z.string()}),xNw=Z.object({label:Z.string(),value:Z.string(),note:Z.string()}),ONw=Z.object({eyebrow:Z.string(),headline:Z.string(),intro:Z.string(),primaryCta:PB2,secondaryCta:PB2,signals:Z.array(xNw)}),vNw=Z.object({phase:Z.string(),title:Z.string(),text:Z.string()}),RNw=Z.object({eyebrow:Z.string(),title:Z.string(),intro:Z.string(),steps:Z.array(vNw)}),hNw=Z.object({label:Z.string(),title:Z.string(),text:Z.string()}),CNw=Z.object({title:Z.string(),intro:Z.string(),cards:Z.array(hNw)}),gNw=Z.object({title:Z.string(),intro:Z.string(),points:Z.array(Z.string())}),yNw={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."]},ENw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function jB2({href:A,label:Q}){return D1("a",{href:A,className:ENw,children:Q},void 0,!1,void 0,this)}function TNw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],B=A.cta??{buttonText:"Start here",buttonLink:"/about"};return D1(oy,{children:[D1("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:[D1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[D1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),D1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),D1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex items-center gap-5 md:gap-8",children:[D1("div",{className:"hidden items-center gap-6 md:flex",children:w.map(($)=>D1(jB2,{...$},`${$.href}-${$.label}`,!1,void 0,this))},void 0,!1,void 0,this),D1("a",{href:B.buttonLink,className:"rounded-[999px] border border-theme px-4 py-2 font-body text-[13px] font-semibold text-theme transition-colors hover:border-accent hover:text-accent md:px-5",children:B.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("main",{children:Q},void 0,!1,void 0,this),D1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:D1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),D1("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),D1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map(($)=>D1(jB2,{...$},`footer-${$.href}-${$.label}`,!1,void 0,this)),D1("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 SNw=({sections:A,siteInfo:Q})=>D1(TNw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function mNw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,signals:f}){return D1(cF,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:D1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[D1("div",{children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[D1(hj,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(hj,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("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:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),D1("div",{className:"mt-5 grid gap-3",children:f.map((Y)=>D1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[D1("div",{className:"flex items-center justify-between gap-4",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),D1("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),D1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),D1("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 uNw({eyebrow:A,title:Q,intro:w,steps:B}){return D1(cF,{id:"operating-loop",className:"py-section",children:[D1("div",{className:"max-w-[840px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),D1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mt-5 font-body text-body-md text-theme-muted",children:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:B.map(($)=>D1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[D1("p",{className:"font-label text-label-sm text-accent",children:$.phase},void 0,!1,void 0,this),D1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:$.title},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function cNw({title:A,intro:Q,cards:w}){return D1(cF,{className:"py-section",children:D1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:D1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[D1("div",{children:[D1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),D1("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),D1("div",{className:"grid gap-4",children:w.map((B)=>D1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[D1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:B.label},void 0,!1,void 0,this),D1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:B.title},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)}function lNw({title:A,intro:Q,points:w}){return D1(cF,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[D1("div",{className:"max-w-[920px]",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),D1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),D1("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),D1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map((B)=>D1("div",{className:"rounded-[24px] border border-card-panel-current-border bg-card-panel-current-bg p-6 font-body text-body-md text-theme",children:B},B,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var pNw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},iNw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),Fs=(A,Q,w=`${Q}s`)=>`${iNw(A)} ${A===1?Q:w}`;function dNw({eyebrow:A,headline:Q,intro:w,primaryCta:B,secondaryCta:$,inputs:f,outputs:Y,core:X,legend:H,counts:W}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:Fs(W.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:Fs(W.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:Fs(W.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:Fs(W.summaries,"summary","summaries")}];return D1(cF,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[D1("div",{className:"mx-auto max-w-[1040px] text-center",children:[D1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),D1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),D1("p",{className:"mx-auto mt-7 max-w-[64ch] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),D1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[D1(hj,{href:B.href,size:"lg",variant:"primary-strong",children:B.label},void 0,!1,void 0,this),D1(hj,{href:$.href,size:"lg",variant:"secondary",children:$.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("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:[D1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[D1("div",{className:"flex flex-col gap-3.5",children:f.map((U)=>D1("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:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),D1("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:[D1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),D1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),K.map((U)=>D1("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 ${U.className}`,children:U.label},U.key,!1,void 0,this)),D1("div",{className:"relative z-[1] px-6 text-center",children:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:X.eyebrow},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:X.name},void 0,!1,void 0,this),D1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:X.sub},void 0,!1,void 0,this),D1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[Fs(W.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"flex flex-col gap-3.5",children:Y.map((U)=>D1("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:[D1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:U.label},void 0,!1,void 0,this),D1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),D1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((U)=>D1("div",{className:"text-left",children:[D1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[D1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${pNw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),D1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var nNw=l1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:Re0,formatter:{parse:(A)=>Re0.parse({...HH0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>NB2(XE.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:dNw}}),rNw=(A)=>mNw(ONw.parse(A)),oNw=(A)=>uNw(RNw.parse(A)),sNw=(A)=>cNw(CNw.parse(A)),aNw=(A)=>lNw(gNw.parse(A)),MB2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},xB2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:rNw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...MB2,label:"Primary CTA"},secondaryCta:{...MB2,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:oNw,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:sNw,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:aNw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},tNw=[{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:yNw}]}],OB2=qe0({packageName:"@brains/relay/site",themeProfile:"studio",layout:SNw,routes:tNw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":nNw},dataSources:[new he0]}});var vB2={name:"@brains/relay",version:"0.2.0-alpha.164",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 RB2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],hB2=[...RB2,"image","site-info","site-content","site-builder"],QPw=[...hB2,"docs","decks"],wPw=["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."],BPw=zJ({name:"relay",version:vB2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:OB2,theme:ay,presets:{core:RB2,default:hB2,full:QPw},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:wPw,capabilities:[["prompt",Pj,void 0],["note",Wj,{}],["link",Uj,{}],["image",uc,void 0],["topics",qX0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",Oe0,{memoryVisibility:"shared"}],["docs",ar,void 0],["decks",rr,void 0],["agents",PZ0,void 0],["assessment",yZ0,void 0],["auth-service",vp,void 0],["notifications",QB0,void 0],["email-resend",e90,void 0],["cms",Jj,{}],["dashboard",mF,void 0],["directory-sync",UP,{seedContent:!0,seedContentPath:APw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",sP,{definitions:xB2}],["rizom-ecosystem",jj,void 0],["site-info",aP,void 0],["site-builder",oP,{}]],interfaces:[["mcp",AI,()=>({})],["discord",SI,()=>({captureUrls:!0})],["a2a",uC,()=>({})],["webserver",iI,()=>({})],["web-chat",mC,()=>({})]],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"}}}),CB2=BPw;import{readFileSync as Txw}from"fs";import{join as Sxw}from"path";import{execSync as mxw}from"child_process";import{parseArgs as YPw}from"util";var XPw={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 gU(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function pF(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function gB2(A){let{values:Q,positionals:w}=YPw({args:A,options:XPw,allowPositionals:!0,strict:!1});if(Q.help)return{command:"help",args:[],flags:{help:!0}};if(Q.version)return{command:"version",args:[],flags:{version:!0}};return{command:w[0]??"help",args:w.slice(1),flags:{model:gU(Q,"model"),domain:gU(Q,"domain"),"content-repo":gU(Q,"content-repo"),backend:gU(Q,"backend"),"push-to":gU(Q,"push-to"),"ai-api-key":gU(Q,"ai-api-key"),"no-interactive":pF(Q,"no-interactive"),preview:pF(Q,"preview"),deploy:pF(Q,"deploy"),regen:pF(Q,"regen"),all:pF(Q,"all"),only:gU(Q,"only"),"dry-run":pF(Q,"dry-run"),"startup-check":pF(Q,"startup-check"),"storage-dir":gU(Q,"storage-dir"),yes:pF(Q,"yes"),remote:gU(Q,"remote"),token:gU(Q,"token"),outputDir:gU(Q,"outputDir")}}}ks();import{mkdirSync as Mxw}from"fs";import{join as xxw}from"path";import{execSync as Oxw}from"child_process";var KH0={name:"@rizom/brain",version:"0.2.0-alpha.164",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 sB2,writeFileSync as _s,chmodSync as Ns,existsSync as le0,readFileSync as pe0}from"fs";import{basename as ie0,dirname as de0,join as m$,resolve as uPw}from"path";import{fileURLToPath as cPw}from"url";var yB2=`ARG BUN_VERSION=1.3.10
|
|
13708
13708
|
FROM oven/bun:\${BUN_VERSION}-slim AS runtime
|
|
13709
13709
|
|
|
13710
13710
|
WORKDIR /app
|