@rizom/brain 0.2.0-alpha.180 → 0.2.0-alpha.181
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 +55 -37
- 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
|
@@ -460,7 +460,7 @@ ${X}`:"")}function $r0(A,Q,w,$){return async(B,X)=>{if($){let Y={toolName:A,args
|
|
|
460
460
|
hash text NOT NULL,
|
|
461
461
|
created_at numeric
|
|
462
462
|
)
|
|
463
|
-
`;await A.session.run(B);let Y=(await A.values(r0`SELECT id, hash, created_at FROM ${r0.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let W of w)if(!Y||Number(Y[2])<W.folderMillis){for(let K of W.sql)Z.push(A.run(r0.raw(K)));Z.push(A.run(r0`INSERT INTO ${r0.identifier($)} ("hash", "created_at") VALUES(${W.hash}, ${W.folderMillis})`))}await A.session.migrate(Z)}var ae=m(()=>{j51();p7()});async function O51(A,Q){let w=Q?.child("entity-migrate")??oQ.getInstance().child("entity-migrate"),{db:$,client:B,url:X}=PH0(A);w.debug("Running entity database migrations...");try{await MH0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),await jH0(B),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{B.close()}}var f51=m(()=>{ae();fc0();g4()});async function x51(A,Q){let w=Q?.child("job-queue-migrate")??oQ.getInstance().child("job-queue-migrate"),{db:$,client:B,url:X}=e70(A);w.debug("Running job queue migrations...");try{await A40(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{B.close()}}var R51=m(()=>{ae();pE0();g4()});async function v51(A,Q){let w=Q?.child("conversation-migrate")??oQ.getInstance().child("conversation-migrate"),{db:$,client:B,url:X}=dx(A);w.debug("Running conversation database migrations...");try{if(X.startsWith("file:"))await B.execute("PRAGMA journal_mode = WAL");let Z=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var C51=m(()=>{ae();NH0();g4()});async function h51(A,Q){let w=Q?.child("runtime-state-migrate")??oQ.getInstance().child("runtime-state-migrate"),{db:$,client:B,url:X}=oK0(A);w.debug("Running runtime state migrations...");try{await sK0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var E51=m(()=>{ae();g4();br0()});import{mkdir as er0}from"fs/promises";function UU0(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function GU0(A=process.env){return WP(UU0(A))}async function DU0(A=process.env){let Q=UU0(A);try{await er0(Q.dataDir,{recursive:!0}),await er0(Q.cacheDir,{recursive:!0}),await er0(Q.distDir,{recursive:!0})}catch(w){let $=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($,{cause:w})}return WP(Q)}var qU0=m(()=>{WU0()});class te{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>DU0(),migrateEntities:O51,migrateJobQueue:x51,migrateConversations:v51,migrateRuntimeState:h51}}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 Ao0=m(()=>{f51();R51();C51();E51();qU0()});function zhQ(){return process.env[qhQ]}function g51(){return zhQ()!=="production"}var qhQ="NODE_ENV";var zU0;var Qo0=m(()=>{b0();zU0=H.object({theme:H.object({primaryColor:H.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:H.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var T51;var y51=m(()=>{T51={name:"@brains/chat-repl",version:"0.2.0-alpha.180",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 vw=x((VhQ,JU0)=>{(function(){function A(X0,k0){Object.defineProperty($.prototype,X0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",k0[0],k0[1])}})}function Q(X0){if(X0===null||typeof X0!=="object")return null;return X0=P0&&X0[P0]||X0["@@iterator"],typeof X0==="function"?X0:null}function w(X0,k0){X0=(X0=X0.constructor)&&(X0.displayName||X0.name)||"ReactClass";var h0=X0+"."+k0;M0[h0]||(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,X0),M0[h0]=!0)}function $(X0,k0,h0){this.props=X0,this.context=k0,this.refs=S0,this.updater=h0||O0}function B(){}function X(X0,k0,h0){this.props=X0,this.context=k0,this.refs=S0,this.updater=h0||O0}function Y(){}function Z(X0){return""+X0}function W(X0){try{Z(X0);var k0=!1}catch(R0){k0=!0}if(k0){k0=console;var h0=k0.error,u0=typeof Symbol==="function"&&Symbol.toStringTag&&X0[Symbol.toStringTag]||X0.constructor.name||"Object";return h0.call(k0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",u0),Z(X0)}}function K(X0){if(X0==null)return null;if(typeof X0==="function")return X0.$$typeof===UA?null:X0.displayName||X0.name||null;if(typeof X0==="string")return X0;switch(X0){case G0:return"Fragment";case H0:return"Profiler";case p:return"StrictMode";case m0:return"Suspense";case I0:return"SuspenseList";case E0:return"Activity"}if(typeof X0==="object")switch(typeof X0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),X0.$$typeof){case r:return"Portal";case Q0:return X0.displayName||"Context";case V0:return(X0._context.displayName||"Context")+".Consumer";case C0:var k0=X0.render;return X0=X0.displayName,X0||(X0=k0.displayName||k0.name||"",X0=X0!==""?"ForwardRef("+X0+")":"ForwardRef"),X0;case L0:return k0=X0.displayName||null,k0!==null?k0:K(X0.type)||"Memo";case j0:k0=X0._payload,X0=X0._init;try{return K(X0(k0))}catch(h0){}}return null}function U(X0){if(X0===G0)return"<>";if(typeof X0==="object"&&X0!==null&&X0.$$typeof===j0)return"<...>";try{var k0=K(X0);return k0?"<"+k0+">":"<...>"}catch(h0){return"<...>"}}function G(){var X0=WA.A;return X0===null?null:X0.getOwner()}function D(){return Error("react-stack-top-frame")}function z(X0){if(c0.call(X0,"key")){var k0=Object.getOwnPropertyDescriptor(X0,"key").get;if(k0&&k0.isReactWarning)return!1}return X0.key!==void 0}function V(X0,k0){function h0(){JA||(JA=!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))}h0.isReactWarning=!0,Object.defineProperty(X0,"key",{get:h0,configurable:!0})}function I(){var X0=K(this.type);return yA[X0]||(yA[X0]=!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.")),X0=this.props.ref,X0!==void 0?X0:null}function F(X0,k0,h0,u0,R0,QA){var o0=h0.ref;return X0={$$typeof:n,type:X0,key:k0,props:h0,_owner:u0},(o0!==void 0?o0:null)!==null?Object.defineProperty(X0,"ref",{enumerable:!1,get:I}):Object.defineProperty(X0,"ref",{enumerable:!1,value:null}),X0._store={},Object.defineProperty(X0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(X0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(X0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:R0}),Object.defineProperty(X0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:QA}),Object.freeze&&(Object.freeze(X0.props),Object.freeze(X0)),X0}function _(X0,k0){return k0=F(X0.type,k0,X0.props,X0._owner,X0._debugStack,X0._debugTask),X0._store&&(k0._store.validated=X0._store.validated),k0}function k(X0){b(X0)?X0._store&&(X0._store.validated=1):typeof X0==="object"&&X0!==null&&X0.$$typeof===j0&&(X0._payload.status==="fulfilled"?b(X0._payload.value)&&X0._payload.value._store&&(X0._payload.value._store.validated=1):X0._store&&(X0._store.validated=1))}function b(X0){return typeof X0==="object"&&X0!==null&&X0.$$typeof===n}function f(X0){var k0={"=":"=0",":":"=2"};return"$"+X0.replace(/[=:]/g,function(h0){return k0[h0]})}function R(X0,k0){return typeof X0==="object"&&X0!==null&&X0.key!=null?(W(X0.key),f(""+X0.key)):k0.toString(36)}function v(X0){switch(X0.status){case"fulfilled":return X0.value;case"rejected":throw X0.reason;default:switch(typeof X0.status==="string"?X0.then(Y,Y):(X0.status="pending",X0.then(function(k0){X0.status==="pending"&&(X0.status="fulfilled",X0.value=k0)},function(k0){X0.status==="pending"&&(X0.status="rejected",X0.reason=k0)})),X0.status){case"fulfilled":return X0.value;case"rejected":throw X0.reason}}throw X0}function M(X0,k0,h0,u0,R0){var QA=typeof X0;if(QA==="undefined"||QA==="boolean")X0=null;var o0=!1;if(X0===null)o0=!0;else switch(QA){case"bigint":case"string":case"number":o0=!0;break;case"object":switch(X0.$$typeof){case n:case r:o0=!0;break;case j0:return o0=X0._init,M(o0(X0._payload),k0,h0,u0,R0)}}if(o0){o0=X0,R0=R0(o0);var MA=u0===""?"."+R(o0,0):u0;return IA(R0)?(h0="",MA!=null&&(h0=MA.replace(a0,"$&/")+"/"),M(R0,k0,h0,"",function(B1){return B1})):R0!=null&&(b(R0)&&(R0.key!=null&&(o0&&o0.key===R0.key||W(R0.key)),h0=_(R0,h0+(R0.key==null||o0&&o0.key===R0.key?"":(""+R0.key).replace(a0,"$&/")+"/")+MA),u0!==""&&o0!=null&&b(o0)&&o0.key==null&&o0._store&&!o0._store.validated&&(h0._store.validated=2),R0=h0),k0.push(R0)),1}if(o0=0,MA=u0===""?".":u0+":",IA(X0))for(var jA=0;jA<X0.length;jA++)u0=X0[jA],QA=MA+R(u0,jA),o0+=M(u0,k0,h0,QA,R0);else if(jA=Q(X0),typeof jA==="function")for(jA===X0.entries&&(BA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),BA=!0),X0=jA.call(X0),jA=0;!(u0=X0.next()).done;)u0=u0.value,QA=MA+R(u0,jA++),o0+=M(u0,k0,h0,QA,R0);else if(QA==="object"){if(typeof X0.then==="function")return M(v(X0),k0,h0,u0,R0);throw k0=String(X0),Error("Objects are not valid as a React child (found: "+(k0==="[object Object]"?"object with keys {"+Object.keys(X0).join(", ")+"}":k0)+"). If you meant to render a collection of children, use an array instead.")}return o0}function y(X0,k0,h0){if(X0==null)return X0;var u0=[],R0=0;return M(X0,u0,"","",function(QA){return k0.call(h0,QA,R0++)}),u0}function S(X0){if(X0._status===-1){var k0=X0._ioInfo;k0!=null&&(k0.start=k0.end=performance.now()),k0=X0._result;var h0=k0();if(h0.then(function(R0){if(X0._status===0||X0._status===-1){X0._status=1,X0._result=R0;var QA=X0._ioInfo;QA!=null&&(QA.end=performance.now()),h0.status===void 0&&(h0.status="fulfilled",h0.value=R0)}},function(R0){if(X0._status===0||X0._status===-1){X0._status=2,X0._result=R0;var QA=X0._ioInfo;QA!=null&&(QA.end=performance.now()),h0.status===void 0&&(h0.status="rejected",h0.reason=R0)}}),k0=X0._ioInfo,k0!=null){k0.value=h0;var u0=h0.displayName;typeof u0==="string"&&(k0.name=u0)}X0._status===-1&&(X0._status=0,X0._result=h0)}if(X0._status===1)return k0=X0._result,k0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
463
|
+
`;await A.session.run(B);let Y=(await A.values(r0`SELECT id, hash, created_at FROM ${r0.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let W of w)if(!Y||Number(Y[2])<W.folderMillis){for(let K of W.sql)Z.push(A.run(r0.raw(K)));Z.push(A.run(r0`INSERT INTO ${r0.identifier($)} ("hash", "created_at") VALUES(${W.hash}, ${W.folderMillis})`))}await A.session.migrate(Z)}var ae=m(()=>{j51();p7()});async function O51(A,Q){let w=Q?.child("entity-migrate")??oQ.getInstance().child("entity-migrate"),{db:$,client:B,url:X}=PH0(A);w.debug("Running entity database migrations...");try{await MH0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/entity-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),await jH0(B),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{B.close()}}var f51=m(()=>{ae();fc0();g4()});async function x51(A,Q){let w=Q?.child("job-queue-migrate")??oQ.getInstance().child("job-queue-migrate"),{db:$,client:B,url:X}=e70(A);w.debug("Running job queue migrations...");try{await A40(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/job-queue",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{B.close()}}var R51=m(()=>{ae();pE0();g4()});async function v51(A,Q){let w=Q?.child("conversation-migrate")??oQ.getInstance().child("conversation-migrate"),{db:$,client:B,url:X}=dx(A);w.debug("Running conversation database migrations...");try{if(X.startsWith("file:"))await B.execute("PRAGMA journal_mode = WAL");let Z=import.meta.url.includes("/dist/")?new URL("./migrations/conversation-service",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var C51=m(()=>{ae();NH0();g4()});async function h51(A,Q){let w=Q?.child("runtime-state-migrate")??oQ.getInstance().child("runtime-state-migrate"),{db:$,client:B,url:X}=oK0(A);w.debug("Running runtime state migrations...");try{await sK0(B,X);let Z=import.meta.url.includes("/dist/")?new URL("./migrations/runtime-state",import.meta.url).pathname:new URL("../drizzle",import.meta.url).pathname;await NP($,{migrationsFolder:Z}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var E51=m(()=>{ae();g4();br0()});import{mkdir as er0}from"fs/promises";function UU0(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function GU0(A=process.env){return WP(UU0(A))}async function DU0(A=process.env){let Q=UU0(A);try{await er0(Q.dataDir,{recursive:!0}),await er0(Q.cacheDir,{recursive:!0}),await er0(Q.distDir,{recursive:!0})}catch(w){let $=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($,{cause:w})}return WP(Q)}var qU0=m(()=>{WU0()});class te{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>DU0(),migrateEntities:O51,migrateJobQueue:x51,migrateConversations:v51,migrateRuntimeState:h51}}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 Ao0=m(()=>{f51();R51();C51();E51();qU0()});function zhQ(){return process.env[qhQ]}function g51(){return zhQ()!=="production"}var qhQ="NODE_ENV";var zU0;var Qo0=m(()=>{b0();zU0=H.object({theme:H.object({primaryColor:H.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:H.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var T51;var y51=m(()=>{T51={name:"@brains/chat-repl",version:"0.2.0-alpha.181",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 vw=x((VhQ,JU0)=>{(function(){function A(X0,k0){Object.defineProperty($.prototype,X0,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",k0[0],k0[1])}})}function Q(X0){if(X0===null||typeof X0!=="object")return null;return X0=P0&&X0[P0]||X0["@@iterator"],typeof X0==="function"?X0:null}function w(X0,k0){X0=(X0=X0.constructor)&&(X0.displayName||X0.name)||"ReactClass";var h0=X0+"."+k0;M0[h0]||(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,X0),M0[h0]=!0)}function $(X0,k0,h0){this.props=X0,this.context=k0,this.refs=S0,this.updater=h0||O0}function B(){}function X(X0,k0,h0){this.props=X0,this.context=k0,this.refs=S0,this.updater=h0||O0}function Y(){}function Z(X0){return""+X0}function W(X0){try{Z(X0);var k0=!1}catch(R0){k0=!0}if(k0){k0=console;var h0=k0.error,u0=typeof Symbol==="function"&&Symbol.toStringTag&&X0[Symbol.toStringTag]||X0.constructor.name||"Object";return h0.call(k0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",u0),Z(X0)}}function K(X0){if(X0==null)return null;if(typeof X0==="function")return X0.$$typeof===UA?null:X0.displayName||X0.name||null;if(typeof X0==="string")return X0;switch(X0){case G0:return"Fragment";case H0:return"Profiler";case p:return"StrictMode";case m0:return"Suspense";case I0:return"SuspenseList";case E0:return"Activity"}if(typeof X0==="object")switch(typeof X0.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),X0.$$typeof){case r:return"Portal";case Q0:return X0.displayName||"Context";case V0:return(X0._context.displayName||"Context")+".Consumer";case C0:var k0=X0.render;return X0=X0.displayName,X0||(X0=k0.displayName||k0.name||"",X0=X0!==""?"ForwardRef("+X0+")":"ForwardRef"),X0;case L0:return k0=X0.displayName||null,k0!==null?k0:K(X0.type)||"Memo";case j0:k0=X0._payload,X0=X0._init;try{return K(X0(k0))}catch(h0){}}return null}function U(X0){if(X0===G0)return"<>";if(typeof X0==="object"&&X0!==null&&X0.$$typeof===j0)return"<...>";try{var k0=K(X0);return k0?"<"+k0+">":"<...>"}catch(h0){return"<...>"}}function G(){var X0=WA.A;return X0===null?null:X0.getOwner()}function D(){return Error("react-stack-top-frame")}function z(X0){if(c0.call(X0,"key")){var k0=Object.getOwnPropertyDescriptor(X0,"key").get;if(k0&&k0.isReactWarning)return!1}return X0.key!==void 0}function V(X0,k0){function h0(){JA||(JA=!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))}h0.isReactWarning=!0,Object.defineProperty(X0,"key",{get:h0,configurable:!0})}function I(){var X0=K(this.type);return yA[X0]||(yA[X0]=!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.")),X0=this.props.ref,X0!==void 0?X0:null}function F(X0,k0,h0,u0,R0,QA){var o0=h0.ref;return X0={$$typeof:n,type:X0,key:k0,props:h0,_owner:u0},(o0!==void 0?o0:null)!==null?Object.defineProperty(X0,"ref",{enumerable:!1,get:I}):Object.defineProperty(X0,"ref",{enumerable:!1,value:null}),X0._store={},Object.defineProperty(X0._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(X0,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(X0,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:R0}),Object.defineProperty(X0,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:QA}),Object.freeze&&(Object.freeze(X0.props),Object.freeze(X0)),X0}function _(X0,k0){return k0=F(X0.type,k0,X0.props,X0._owner,X0._debugStack,X0._debugTask),X0._store&&(k0._store.validated=X0._store.validated),k0}function k(X0){b(X0)?X0._store&&(X0._store.validated=1):typeof X0==="object"&&X0!==null&&X0.$$typeof===j0&&(X0._payload.status==="fulfilled"?b(X0._payload.value)&&X0._payload.value._store&&(X0._payload.value._store.validated=1):X0._store&&(X0._store.validated=1))}function b(X0){return typeof X0==="object"&&X0!==null&&X0.$$typeof===n}function f(X0){var k0={"=":"=0",":":"=2"};return"$"+X0.replace(/[=:]/g,function(h0){return k0[h0]})}function R(X0,k0){return typeof X0==="object"&&X0!==null&&X0.key!=null?(W(X0.key),f(""+X0.key)):k0.toString(36)}function v(X0){switch(X0.status){case"fulfilled":return X0.value;case"rejected":throw X0.reason;default:switch(typeof X0.status==="string"?X0.then(Y,Y):(X0.status="pending",X0.then(function(k0){X0.status==="pending"&&(X0.status="fulfilled",X0.value=k0)},function(k0){X0.status==="pending"&&(X0.status="rejected",X0.reason=k0)})),X0.status){case"fulfilled":return X0.value;case"rejected":throw X0.reason}}throw X0}function M(X0,k0,h0,u0,R0){var QA=typeof X0;if(QA==="undefined"||QA==="boolean")X0=null;var o0=!1;if(X0===null)o0=!0;else switch(QA){case"bigint":case"string":case"number":o0=!0;break;case"object":switch(X0.$$typeof){case n:case r:o0=!0;break;case j0:return o0=X0._init,M(o0(X0._payload),k0,h0,u0,R0)}}if(o0){o0=X0,R0=R0(o0);var MA=u0===""?"."+R(o0,0):u0;return IA(R0)?(h0="",MA!=null&&(h0=MA.replace(a0,"$&/")+"/"),M(R0,k0,h0,"",function(B1){return B1})):R0!=null&&(b(R0)&&(R0.key!=null&&(o0&&o0.key===R0.key||W(R0.key)),h0=_(R0,h0+(R0.key==null||o0&&o0.key===R0.key?"":(""+R0.key).replace(a0,"$&/")+"/")+MA),u0!==""&&o0!=null&&b(o0)&&o0.key==null&&o0._store&&!o0._store.validated&&(h0._store.validated=2),R0=h0),k0.push(R0)),1}if(o0=0,MA=u0===""?".":u0+":",IA(X0))for(var jA=0;jA<X0.length;jA++)u0=X0[jA],QA=MA+R(u0,jA),o0+=M(u0,k0,h0,QA,R0);else if(jA=Q(X0),typeof jA==="function")for(jA===X0.entries&&(BA||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),BA=!0),X0=jA.call(X0),jA=0;!(u0=X0.next()).done;)u0=u0.value,QA=MA+R(u0,jA++),o0+=M(u0,k0,h0,QA,R0);else if(QA==="object"){if(typeof X0.then==="function")return M(v(X0),k0,h0,u0,R0);throw k0=String(X0),Error("Objects are not valid as a React child (found: "+(k0==="[object Object]"?"object with keys {"+Object.keys(X0).join(", ")+"}":k0)+"). If you meant to render a collection of children, use an array instead.")}return o0}function y(X0,k0,h0){if(X0==null)return X0;var u0=[],R0=0;return M(X0,u0,"","",function(QA){return k0.call(h0,QA,R0++)}),u0}function S(X0){if(X0._status===-1){var k0=X0._ioInfo;k0!=null&&(k0.start=k0.end=performance.now()),k0=X0._result;var h0=k0();if(h0.then(function(R0){if(X0._status===0||X0._status===-1){X0._status=1,X0._result=R0;var QA=X0._ioInfo;QA!=null&&(QA.end=performance.now()),h0.status===void 0&&(h0.status="fulfilled",h0.value=R0)}},function(R0){if(X0._status===0||X0._status===-1){X0._status=2,X0._result=R0;var QA=X0._ioInfo;QA!=null&&(QA.end=performance.now()),h0.status===void 0&&(h0.status="rejected",h0.reason=R0)}}),k0=X0._ioInfo,k0!=null){k0.value=h0;var u0=h0.displayName;typeof u0==="string"&&(k0.name=u0)}X0._status===-1&&(X0._status=0,X0._result=h0)}if(X0._status===1)return k0=X0._result,k0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
464
464
|
|
|
465
465
|
Your code should look like:
|
|
466
466
|
const MyComponent = lazy(() => import('./MyComponent'))
|
|
@@ -1747,7 +1747,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
|
|
|
1747
1747
|
Title: "${A.entityTitle??Z}"
|
|
1748
1748
|
|
|
1749
1749
|
Content:
|
|
1750
|
-
${U}`,CuQ);K=`${$.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:lA(_)})}}await this.reportProgress(w,{progress:kw.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),V=DZ1(G,D)+K,I;try{I=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:lA(_)}),J5.failure(_)}await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let F=nK.createImageEntity({dataUrl:I.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await $H({entityService:this.context.entityService,entity:{...F,id:W}}),this.logger.debug("Created image entity",{imageId:W}),X&&Y){await this.reportProgress(w,{progress:kw.SAVE,message:`Updating ${X} with cover image`});let _=await $R(this.context.entityService,X,Y,this.logger);if(!_)return J5.failure(Error(`Target entity not found: ${X}/${Y}`));let k=gR(_,W);await this.context.entities.update(k),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:W})}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:W,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:W}}catch(K){let U=lA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await dJ({entityService:this.context.entityService,entityType:"image",id:W,error:U}),J5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}$A();b0();g$();rY();var EuQ=H.object({sourceEntityType:H.string().min(1),sourceEntityId:H.string().min(1),attachmentType:H.string().min(1),imageId:H.string().min(1),dedupKey:H.string().min(1).optional(),replace:H.boolean().optional(),targetEntityType:H.string().min(1).optional(),targetEntityId:H.string().min(1).optional(),targetImageField:H.enum(["coverImageId","ogImageId"]).optional()});class ka0 extends p6{context;constructor(A,Q){super(Q,{schema:EuQ,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:kw.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:kw.PROCESS,message:"Rendering source image"});let $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)return J5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if($.type!=="image")return J5.failure(Error(`Attachment provider returned ${$.type}; expected image`));await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let B=$.mimeType.split("/")[1]??"png",X=nK.createImageEntity({dataUrl:lr0($.data.toString("base64"),B),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await $H({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:kw.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch($){let B=lA($);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await dJ({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),J5.failure($)}}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 $R(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let B=(A.targetImageField??"coverImageId")==="ogImageId"?oe(w,Q):gR(w,Q);await this.context.entities.update(B)}}$A();b0();g$();rY();R2();var Gu={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function mG0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function uG0(A){let Q=guQ(A.title,A.filename),w=F1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function qZ1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function guQ(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var yuQ=H.object({uploadId:H.string().min(1),imageId:H.string().min(1).optional(),title:H.string().optional()});class Pa0 extends p6{context;constructor(A,Q){super(A,{schema:yuQ,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let $=await this.context.uploads.scoped(Gu).read(A.uploadId);if(!mG0($.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=uG0({filename:$.record.filename,...A.title!==void 0?{title:A.title}:{}}),X=A.imageId??B.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),Z=nK.createImageEntity({dataUrl:qZ1($.record.mediaType,$.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:$.record.filename,sourceMediaType:$.record.mediaType,attachmentType:"uploaded"}),W=await $H({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:W.entityId,status:"created"}}catch($){if(A.imageId)await dJ({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:lA($)});return J5.failure($)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var zZ1={name:"@brains/image-plugin",version:"0.2.0-alpha.180",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 SuQ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",muQ=H.object({defaultAspectRatio:H.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function _q(A){let Q=A?.trim();if(!Q)return;return Q}function uuQ(A){let Q=_q(A.prompt);if(Q)return Q;let w=_q(A.content);if(w&&!ba0(w))return w;return}function cuQ(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return F1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function JZ1(A){let Q=_q(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return F1(Q)}async function puQ(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,$=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return $?`${w}:${$.contentHash}`:w}function Ma0(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 luQ(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 ja0 extends jw{entityType=nK.entityType;schema=ne;adapter=nK;constructor(A={}){super("image",zZ1,A,muQ)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===Gu.refKind)return this.promoteUpload(A,w);let $=uuQ(A),B=_q(A.targetEntityType),X=_q(A.targetEntityId),Y=B===this.entityType?X:void 0,Z=A.from;if(Z?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Z},w);if(!B||!X||Y){if(!$)return{kind:"continue",input:A};let D=_q(A.title)??Y,z=JZ1({prompt:$,...D&&{title:D}});await this.createPendingImage(w,{id:z,title:D??$.slice(0,60).trim(),alt:D??$.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:z,status:"generating",jobId:V,attachment:Ma0(z)}}}}let W=await cY(w.entityService,B,X,this.logger,"Target entity");if(!W.ok)return{kind:"handled",result:{success:!1,error:W.error}};if(!$)return{kind:"continue",input:{...A,targetEntityId:W.entity.id}};let K=TG0(W.entity.content),U=JZ1({prompt:$,...A.title&&{title:A.title},targetEntityId:W.entity.id});await this.createPendingImage(w,{id:U,title:A.title??`cover-${W.entity.id}`,alt:A.title??`cover-${W.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:W.entity.id});let G=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:W.entity.id,entityTitle:typeof W.entity.metadata.title==="string"?W.entity.metadata.title:W.entity.id,...K&&{entityContent:K}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:Ma0(U)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==Gu.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $=w.id,B;try{B=await Q.uploads.scoped(Gu).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!mG0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=uG0({filename:B.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Z){return{kind:"handled",result:{success:!1,error:Z instanceof Error?Z.message:String(Z)}}}await this.createPendingImage(Q,{id:X.id,title:X.title,alt:X.title,sourceUploadId:$,sourceFilename:B.filename,sourceMediaType:B.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:$,imageId:X.id,title:X.title}});return{kind:"handled",result:{success:!0,data:{entityId:X.id,status:"generating",jobId:Y,attachment:luQ({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let w=_q(A.from.sourceEntityType),$=_q(A.from.sourceEntityId),B=_q(A.from.attachmentType);if(!w||!$||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await cY(Q.entityService,w,$,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=_q(A.targetEntityType),Z=_q(A.targetEntityId),W;if(Y&&Z){let z=await cY(Q.entityService,Y,Z,this.logger,"Target entity");if(!z.ok)return{kind:"handled",result:{success:!1,error:z.error}};W=z.entity.id}let K={sourceEntityType:w,sourceEntityId:X.entity.id,attachmentType:B},U=await puQ(Q,K),G=cuQ(K);await this.createPendingImage(Q,{id:G,title:G,alt:G,sourceEntityType:K.sourceEntityType,sourceEntityId:K.sourceEntityId,attachmentType:B,dedupKey:U});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...K,imageId:G,dedupKey:U,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...W&&{targetEntityId:W},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:G,status:"generating",jobId:D,attachment:Ma0(G,B)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),$=nK.createImageEntity({dataUrl:SuQ,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 XR({entityService:A.entityService,entity:{id:Q.id,...$,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 SG0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let $=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return $.kind==="handled"?$.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new SG0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new ka0(A,this.logger)),A.jobs.registerHandler("upload-promote",new Pa0(this.logger.child("UploadPromotionJobHandler"),A))}}function a00(A={}){return new ja0(A)}$A();import{StdioServerTransport as iuQ}from"@modelcontextprotocol/sdk/server/stdio.js";b0();var duQ=H.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 VZ1(){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 Oa0(){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 cG0(A){let Q=duQ.safeParse(A);if(Q.success)return{info:(w,...$)=>Q.data.info(w,...$),debug:(w,...$)=>Q.data.debug(w,...$),error:(w,...$)=>Q.data.error(w,...$),warn:(w,...$)=>Q.data.warn(w,...$)};return Oa0()}class bq{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return bq.instance??=new bq(A),bq.instance}static resetInstance(){if(bq.instance)bq.instance.stop(),bq.instance=null}static createFresh(A){return new bq(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?cG0(this.config.logger):VZ1()}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 iuQ,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 nuQ,timingSafeEqual as ruQ}from"crypto";import{WebStandardStreamableHTTPServerTransport as ouQ}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as suQ}from"@modelcontextprotocol/sdk/types.js";b0();var auQ=1800000,tuQ=60000,euQ={"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"},AcQ=H.looseObject({code:H.string().optional()});function QcQ(A){let Q=new URL(A.url),$=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),B=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!B)return Q.origin;return`${$??Q.protocol.replace(":","")}://${B}`}class KN{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?cG0(this.config.logger):Oa0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??auQ,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,tuQ)),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 KN.instance??=new KN(A),KN.instance}static resetInstance(){KN.instance=null}static createFresh(A){return new KN(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(euQ))Q.set(w,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let $=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return $;let B=new Headers($.headers);return B.set("WWW-Authenticate",w),new Response($.body,{status:$.status,statusText:$.statusText,headers:B})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${QcQ(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([B,X])=>`${B}="${wcQ(X)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let 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 $=w.substring(7);if(!$cQ($,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:$,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let $=await this.authConfig.verifyBearerToken?.(A);if(!$)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let B=this.authConfig.requiredScopes??[],X=B.filter((Y)=>!$.scope?.includes(Y));if(X.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${X.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:B.join(" ")}));return this.logger.debug("Authentication successful"),{token:w.substring(7),clientId:$.subject,scopes:$.scope??[],extra:{subject:$.subject}}}catch($){return this.logger.warn("Authentication failed: Invalid token",$),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 $=this.transports[Q];if($)delete this.transports[Q],$.close().catch((B)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,B)})}}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 $;try{$=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 B;if(w&&this.transports[w])B=this.transports[w],this.touchSession(w);else if(!w&&suQ($))B=new ouQ({sessionIdGenerator:()=>nuQ(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=B,this.touchSession(Y)},onsessionclosed:(Y)=>{this.logger.info(`Session closed: ${Y}`),delete this.transports[Y],this.sessionLastActivity.delete(Y)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:$,authInfo:Q}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let w=await this.authenticate(A);if(w instanceof Response)return w;let $=w??void 0;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A,$);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 $=AcQ.safeParse(w);if($.success&&$.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 wcQ(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function $cQ(A,Q){let w=Buffer.from(A),$=Buffer.from(Q);if(w.length!==$.length)return!1;return ruQ(w,$)}import{randomUUID as KcQ}from"crypto";import{chmod as BcQ,mkdir as XcQ,readFile as YcQ,rename as FZ1,writeFile as ZcQ}from"fs/promises";import{dirname as HcQ}from"path";class KH{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 YcQ(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 XcQ(HcQ(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await ZcQ(Q,`${JSON.stringify(A,null,2)}
|
|
1750
|
+
${U}`,CuQ);K=`${$.trim()} ${_.imagePrompt}`}catch(_){this.logger.warn("AI prompt distillation failed, using fallback",{error:lA(_)})}}await this.reportProgress(w,{progress:kw.PROCESS,message:"Generating image"});let G=this.context.identity.get(),D=this.context.identity.getProfile(),V=DZ1(G,D)+K,I;try{I=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(_){return this.logger.error("Image generation failed",{jobId:Q,error:lA(_)}),J5.failure(_)}await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let F=nK.createImageEntity({dataUrl:I.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await $H({entityService:this.context.entityService,entity:{...F,id:W}}),this.logger.debug("Created image entity",{imageId:W}),X&&Y){await this.reportProgress(w,{progress:kw.SAVE,message:`Updating ${X} with cover image`});let _=await $R(this.context.entityService,X,Y,this.logger);if(!_)return J5.failure(Error(`Target entity not found: ${X}/${Y}`));let k=gR(_,W);await this.context.entities.update(k),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:W})}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:W,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:W}}catch(K){let U=lA(K);return this.logger.error("Image generation job failed",{jobId:Q,error:U}),await dJ({entityService:this.context.entityService,entityType:"image",id:W,error:U}),J5.failure(K)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}$A();b0();g$();rY();var EuQ=H.object({sourceEntityType:H.string().min(1),sourceEntityId:H.string().min(1),attachmentType:H.string().min(1),imageId:H.string().min(1),dedupKey:H.string().min(1).optional(),replace:H.boolean().optional(),targetEntityType:H.string().min(1).optional(),targetEntityId:H.string().min(1).optional(),targetImageField:H.enum(["coverImageId","ogImageId"]).optional()});class ka0 extends p6{context;constructor(A,Q){super(Q,{schema:EuQ,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:kw.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:kw.PROCESS,message:"Rendering source image"});let $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)return J5.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if($.type!=="image")return J5.failure(Error(`Attachment provider returned ${$.type}; expected image`));await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let B=$.mimeType.split("/")[1]??"png",X=nK.createImageEntity({dataUrl:lr0($.data.toString("base64"),B),title:A.imageId,status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,...A.dedupKey&&{dedupKey:A.dedupKey}});return await $H({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:kw.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch($){let B=lA($);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await dJ({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),J5.failure($)}}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 $R(this.context.entityService,A.targetEntityType,A.targetEntityId,this.logger);if(!w)throw Error(`Target entity not found: ${A.targetEntityType}/${A.targetEntityId}`);let B=(A.targetImageField??"coverImageId")==="ogImageId"?oe(w,Q):gR(w,Q);await this.context.entities.update(B)}}$A();b0();g$();rY();R2();var Gu={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function mG0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function uG0(A){let Q=guQ(A.title,A.filename),w=F1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function qZ1(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function guQ(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var yuQ=H.object({uploadId:H.string().min(1),imageId:H.string().min(1).optional(),title:H.string().optional()});class Pa0 extends p6{context;constructor(A,Q){super(A,{schema:yuQ,jobTypeName:"upload-promote"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded image"});let $=await this.context.uploads.scoped(Gu).read(A.uploadId);if(!mG0($.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=uG0({filename:$.record.filename,...A.title!==void 0?{title:A.title}:{}}),X=A.imageId??B.id;await this.reportProgress(w,{progress:60,message:"Saving uploaded image"});let Y=new Date().toISOString(),Z=nK.createImageEntity({dataUrl:qZ1($.record.mediaType,$.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:$.record.filename,sourceMediaType:$.record.mediaType,attachmentType:"uploaded"}),W=await $H({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:W.entityId,status:"created"}}catch($){if(A.imageId)await dJ({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:lA($)});return J5.failure($)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var zZ1={name:"@brains/image-plugin",version:"0.2.0-alpha.181",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 SuQ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",muQ=H.object({defaultAspectRatio:H.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function _q(A){let Q=A?.trim();if(!Q)return;return Q}function uuQ(A){let Q=_q(A.prompt);if(Q)return Q;let w=_q(A.content);if(w&&!ba0(w))return w;return}function cuQ(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return F1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function JZ1(A){let Q=_q(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return F1(Q)}async function puQ(A,Q){let w=`${Q.attachmentType}:${Q.sourceEntityType}:${Q.sourceEntityId}:resolved-attachment`,$=await A.entityService.getEntity({entityType:Q.sourceEntityType,id:Q.sourceEntityId});return $?`${w}:${$.contentHash}`:w}function Ma0(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 luQ(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 ja0 extends jw{entityType=nK.entityType;schema=ne;adapter=nK;constructor(A={}){super("image",zZ1,A,muQ)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===Gu.refKind)return this.promoteUpload(A,w);let $=uuQ(A),B=_q(A.targetEntityType),X=_q(A.targetEntityId),Y=B===this.entityType?X:void 0,Z=A.from;if(Z?.kind==="entity-attachment")return this.enqueueSourceImageRender({...A,from:Z},w);if(!B||!X||Y){if(!$)return{kind:"continue",input:A};let D=_q(A.title)??Y,z=JZ1({prompt:$,...D&&{title:D}});await this.createPendingImage(w,{id:z,title:D??$.slice(0,60).trim(),alt:D??$.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...D&&{title:D}}});return{kind:"handled",result:{success:!0,data:{entityId:z,status:"generating",jobId:V,attachment:Ma0(z)}}}}let W=await cY(w.entityService,B,X,this.logger,"Target entity");if(!W.ok)return{kind:"handled",result:{success:!1,error:W.error}};if(!$)return{kind:"continue",input:{...A,targetEntityId:W.entity.id}};let K=TG0(W.entity.content),U=JZ1({prompt:$,...A.title&&{title:A.title},targetEntityId:W.entity.id});await this.createPendingImage(w,{id:U,title:A.title??`cover-${W.entity.id}`,alt:A.title??`cover-${W.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:W.entity.id});let G=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:W.entity.id,entityTitle:typeof W.entity.metadata.title==="string"?W.entity.metadata.title:W.entity.id,...K&&{entityContent:K}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:Ma0(U)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==Gu.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $=w.id,B;try{B=await Q.uploads.scoped(Gu).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!mG0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=uG0({filename:B.filename,...A.title!==void 0?{title:A.title}:{}})}catch(Z){return{kind:"handled",result:{success:!1,error:Z instanceof Error?Z.message:String(Z)}}}await this.createPendingImage(Q,{id:X.id,title:X.title,alt:X.title,sourceUploadId:$,sourceFilename:B.filename,sourceMediaType:B.mediaType,attachmentType:"uploaded"});let Y=await Q.jobs.enqueue({type:"upload-promote",data:{uploadId:$,imageId:X.id,title:X.title}});return{kind:"handled",result:{success:!0,data:{entityId:X.id,status:"generating",jobId:Y,attachment:luQ({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let w=_q(A.from.sourceEntityType),$=_q(A.from.sourceEntityId),B=_q(A.from.attachmentType);if(!w||!$||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await cY(Q.entityService,w,$,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=_q(A.targetEntityType),Z=_q(A.targetEntityId),W;if(Y&&Z){let z=await cY(Q.entityService,Y,Z,this.logger,"Target entity");if(!z.ok)return{kind:"handled",result:{success:!1,error:z.error}};W=z.entity.id}let K={sourceEntityType:w,sourceEntityId:X.entity.id,attachmentType:B},U=await puQ(Q,K),G=cuQ(K);await this.createPendingImage(Q,{id:G,title:G,alt:G,sourceEntityType:K.sourceEntityType,sourceEntityId:K.sourceEntityId,attachmentType:B,dedupKey:U});let D=await Q.jobs.enqueue({type:"image-render-source",data:{...K,imageId:G,dedupKey:U,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...W&&{targetEntityId:W},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:G,status:"generating",jobId:D,attachment:Ma0(G,B)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),$=nK.createImageEntity({dataUrl:SuQ,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 XR({entityService:A.entityService,entity:{id:Q.id,...$,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 SG0(A,this.logger)}async onRegister(A){A.entities.registerUploadSaveHandler({entityType:this.entityType,mediaTypes:["image/*"],handler:async(w)=>{let $=await this.promoteUpload({entityType:this.entityType,...w.title!==void 0?{title:w.title}:{},from:w.upload},A);return $.kind==="handled"?$.result:{success:!1,error:"Image upload save was not handled"}}});let Q=new SG0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new ka0(A,this.logger)),A.jobs.registerHandler("upload-promote",new Pa0(this.logger.child("UploadPromotionJobHandler"),A))}}function a00(A={}){return new ja0(A)}$A();import{StdioServerTransport as iuQ}from"@modelcontextprotocol/sdk/server/stdio.js";b0();var duQ=H.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 VZ1(){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 Oa0(){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 cG0(A){let Q=duQ.safeParse(A);if(Q.success)return{info:(w,...$)=>Q.data.info(w,...$),debug:(w,...$)=>Q.data.debug(w,...$),error:(w,...$)=>Q.data.error(w,...$),warn:(w,...$)=>Q.data.warn(w,...$)};return Oa0()}class bq{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return bq.instance??=new bq(A),bq.instance}static resetInstance(){if(bq.instance)bq.instance.stop(),bq.instance=null}static createFresh(A){return new bq(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?cG0(this.config.logger):VZ1()}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 iuQ,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 nuQ,timingSafeEqual as ruQ}from"crypto";import{WebStandardStreamableHTTPServerTransport as ouQ}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as suQ}from"@modelcontextprotocol/sdk/types.js";b0();var auQ=1800000,tuQ=60000,euQ={"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"},AcQ=H.looseObject({code:H.string().optional()});function QcQ(A){let Q=new URL(A.url),$=A.headers.get("x-forwarded-proto")?.split(",")[0]?.trim(),B=A.headers.get("x-forwarded-host")??A.headers.get("host");if(!B)return Q.origin;return`${$??Q.protocol.replace(":","")}://${B}`}class KN{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?cG0(this.config.logger):Oa0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??auQ,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,tuQ)),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 KN.instance??=new KN(A),KN.instance}static resetInstance(){KN.instance=null}static createFresh(A){return new KN(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(euQ))Q.set(w,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}createJsonResponse(A,Q=200){return this.withCors(new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json"}}))}createTextResponse(A,Q=200){return this.withCors(new Response(A,{status:Q,headers:{"Content-Type":"text/plain; charset=utf-8"}}))}getAuthErrorResponse(A,Q=401,w){let $=this.createJsonResponse({jsonrpc:"2.0",error:{code:-32001,message:A},id:null},Q);if(!w)return $;let B=new Headers($.headers);return B.set("WWW-Authenticate",w),new Response($.body,{status:$.status,statusText:$.statusText,headers:B})}getBearerChallenge(A,Q={}){let w={...this.authConfig.token?{}:{resource_metadata:`${QcQ(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([B,X])=>`${B}="${wcQ(X)}"`).join(", ")}`}async authenticate(A){let Q=new URL(A.url).pathname;if(Q==="/health"||Q==="/status"||Q==="/mcp"&&A.method==="OPTIONS")return null;if(this.authConfig.disabled)return null;let 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 $=w.substring(7);if(!$cQ($,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:$,clientId:"static-token-client",scopes:this.authConfig.requiredScopes??[],extra:{subject:"static-token-operator"}}}try{let $=await this.authConfig.verifyBearerToken?.(A);if(!$)return this.logger.warn("Authentication failed: Invalid token"),this.getAuthErrorResponse("Unauthorized: Invalid token",401,this.getBearerChallenge(A,{error:"invalid_token"}));let B=this.authConfig.requiredScopes??[],X=B.filter((Y)=>!$.scope?.includes(Y));if(X.length>0)return this.logger.warn(`Authentication failed: Missing required scope(s): ${X.join(", ")}`),this.getAuthErrorResponse("Forbidden: Missing required scope",403,this.getBearerChallenge(A,{error:"insufficient_scope",scope:B.join(" ")}));return this.logger.debug("Authentication successful"),{token:w.substring(7),clientId:$.subject,scopes:$.scope??[],extra:{subject:$.subject}}}catch($){return this.logger.warn("Authentication failed: Invalid token",$),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 $=this.transports[Q];if($)delete this.transports[Q],$.close().catch((B)=>{this.logger.error(`Error closing idle transport for session ${Q}:`,B)})}}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 $;try{$=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 B;if(w&&this.transports[w])B=this.transports[w],this.touchSession(w);else if(!w&&suQ($))B=new ouQ({sessionIdGenerator:()=>nuQ(),onsessioninitialized:(Y)=>{this.logger.info(`Session initialized: ${Y}`),this.transports[Y]=B,this.touchSession(Y)},onsessionclosed:(Y)=>{this.logger.info(`Session closed: ${Y}`),delete this.transports[Y],this.sessionLastActivity.delete(Y)}}),await(this.mcpTransport?this.mcpTransport.createMcpServer():this.mcpServer).connect(B);else return this.createJsonResponse({jsonrpc:"2.0",error:{code:-32000,message:"Bad Request: Server not initialized"},id:null},400);return this.withCors(await B.handleRequest(A,{parsedBody:$,authInfo:Q}))}catch(B){return this.logger.error("MCP transport error:",B),this.createJsonResponse({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}},500)}}async handleRequest(A){let Q=new URL(A.url);this.logger.debug(`${A.method} ${Q.pathname}`);let w=await this.authenticate(A);if(w instanceof Response)return w;let $=w??void 0;if(Q.pathname==="/health")return this.createJsonResponse({status:"ok",transport:"streamable-http",timestamp:new Date().toISOString()});if(Q.pathname==="/status")return this.createJsonResponse({status:"ok",sessions:Object.keys(this.transports).length});if(Q.pathname==="/mcp")return this.handleMcpRequest(A,$);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 $=AcQ.safeParse(w);if($.success&&$.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 wcQ(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function $cQ(A,Q){let w=Buffer.from(A),$=Buffer.from(Q);if(w.length!==$.length)return!1;return ruQ(w,$)}import{randomUUID as KcQ}from"crypto";import{chmod as BcQ,mkdir as XcQ,readFile as YcQ,rename as FZ1,writeFile as ZcQ}from"fs/promises";import{dirname as HcQ}from"path";class KH{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 YcQ(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 XcQ(HcQ(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await ZcQ(Q,`${JSON.stringify(A,null,2)}
|
|
1751
1751
|
`,{mode:384}),await BcQ(Q,384),await FZ1(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 FZ1(this.filePath,Q)}catch(w){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,w)}}}function Du(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function pG0(){let A=new Date;return A.setDate(A.getDate()-1),A}function IZ1(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function Z4(){return Math.floor(Date.now()/1000)}b0();import{join as UcQ}from"path";function LZ1(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function NZ1(A){try{return new URL(A)}catch{return}}function fa0(A,Q){if(A===Q)return!0;let w=NZ1(A),$=NZ1(Q);if(!w||!$)return!1;if(!LZ1(w.hostname)||!LZ1($.hostname))return!1;return w.protocol===$.protocol&&w.port===$.port&&WcQ(w.pathname,$.pathname)&&w.search===$.search&&w.hash===$.hash}function WcQ(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function xa0(A,Q){return A.some((w)=>fa0(w,Q))}var GcQ="oauth-auth-codes.json",DcQ=600,qcQ=H.looseObject({code:H.string(),client_id:H.string(),redirect_uri:H.string(),code_challenge:H.string(),code_challenge_method:H.literal("S256"),scope:H.string().optional(),subject:H.string(),created_at:H.number(),expires_at:H.number(),consumed_at:H.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}:{}})),zcQ=H.looseObject({codes:H.array(H.unknown()).optional()});function JcQ(A){let Q=zcQ.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap(VcQ)??[]}}function VcQ(A){let Q=qcQ.safeParse(A);return Q.success?[Q.data]:[]}async function FcQ(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class lG0{store;constructor(A){this.store=new KH({filePath:UcQ(A.storageDir,A.storeFile??GcQ),parse:JcQ,empty:()=>({codes:[]})})}async createCode(A){let Q=Z4(),w={code:`ocd_${KcQ()}`,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+DcQ};return await this.store.enqueueWrite(async()=>{let $=await this.store.read();$.codes=$.codes.filter((B)=>B.expires_at>Q),$.codes.push(w),await this.store.write($)}),w}async consumeCode(A){let Q=Z4(),w;if(await this.store.enqueueWrite(async()=>{let $=await this.store.read(),B=$.codes.findIndex((Z)=>Z.code===A.code),X=B>=0?$.codes[B]:void 0;if(!X)throw new kq("Authorization code not found");if(X.consumed_at!==void 0)throw new kq("Authorization code already consumed");if(X.expires_at<=Q)throw new kq("Authorization code expired");if(X.client_id!==A.clientId)throw new kq("Authorization code client mismatch");if(!fa0(X.redirect_uri,A.redirectUri))throw new kq("Authorization code redirect URI mismatch");let Y=await FcQ(A.codeVerifier);if(X.code_challenge!==Y)throw new kq("PKCE verification failed");w={...X,consumed_at:Q},$.codes[B]=w,await this.store.write($)}),!w)throw new kq("Authorization code not consumed");return w}}class kq extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as _Z1}from"crypto";b0();import{join as IcQ}from"path";var LcQ="oauth-clients.json",NcQ=H.enum(["none","client_secret_basic","client_secret_post"]),_cQ=H.object({redirect_uris:H.array(H.url()).min(1),token_endpoint_auth_method:NcQ.default("none"),grant_types:H.array(H.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:H.array(H.literal("code")).default(["code"]),scope:H.string().optional(),client_name:H.string().optional(),client_uri:H.url().optional(),logo_uri:H.url().optional(),contacts:H.array(H.string()).optional()}),bcQ=H.looseObject({client_id:H.string(),client_id_issued_at:H.number(),redirect_uris:H.array(H.string()),token_endpoint_auth_method:H.string().optional(),grant_types:H.array(H.string()).optional(),response_types:H.array(H.string()).optional(),scope:H.string().optional(),client_name:H.string().optional(),client_uri:H.string().optional(),logo_uri:H.string().optional(),contacts:H.array(H.string()).optional(),client_secret:H.string().optional(),client_secret_expires_at:H.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}:{}})),kcQ=H.looseObject({clients:H.array(H.unknown()).optional()});function PcQ(){return`ocs_${_Z1().replaceAll("-","")}`}function McQ(A){let Q=kcQ.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(jcQ)??[]}}function jcQ(A){let Q=bcQ.safeParse(A);return Q.success?[Q.data]:[]}class dG0{store;constructor(A){this.store=new KH({filePath:IcQ(A.storageDir,A.storeFile??LcQ),parse:McQ,empty:()=>({clients:[]})})}async registerClient(A){let Q=_cQ.safeParse(A);if(!Q.success)throw new t00(Q.error.message);let w=Q.data,$=Z4(),B=`oc_${_Z1()}`,X=w.token_endpoint_auth_method==="none",Y={client_id:B,client_id_issued_at:$,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}:{},...!X?{client_secret:PcQ(),client_secret_expires_at:0}:{}};return await this.store.enqueueWrite(async()=>{let Z=await this.store.read();Z.clients.push(Y),await this.store.write(Z)}),Y}async getClient(A){return(await this.store.read()).clients.find((w)=>w.client_id===A)}}class t00 extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}b0();import{createHash as bZ1,generateKeyPairSync as OcQ}from"crypto";import{mkdir as fcQ,readFile as kZ1,writeFile as xcQ,chmod as RcQ}from"fs/promises";import{dirname as vcQ,join as PZ1}from"path";var CcQ="oauth-signing-key.jwk",hcQ="a2a-signing-key.jwk",MZ1=H.object({kty:H.literal("EC"),crv:H.literal("P-256"),x:H.string(),y:H.string(),d:H.string(),kid:H.string().optional()}),jZ1=H.object({kty:H.literal("OKP"),crv:H.literal("Ed25519"),x:H.string(),d:H.string(),kid:H.string().optional()});function EcQ(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return bZ1("sha256").update(Q).digest("base64url")}function gcQ(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return bZ1("sha256").update(Q).digest("base64url")}function ycQ(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function TcQ(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function ScQ(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=MZ1.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 OZ1(Q.data)}function mcQ(){let{privateKey:A}=OcQ("ed25519"),Q=jZ1.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return fZ1(Q.data)}function OZ1(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??EcQ(A),use:"sig",alg:"ES256"}}function fZ1(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??gcQ(A),use:"sig",alg:"EdDSA"}}class iG0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=PZ1(A.storageDir,A.keyFile??CcQ)}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 ScQ();return await xZ1(this.keyFile,Q),Q}async getPublicJwk(){return ycQ(await this.getPrivateJwk())}async readExistingKey(){try{let A=MZ1.safeParse(JSON.parse(await kZ1(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return OZ1(A.data)}catch(A){if(RZ1(A))return;throw A}}}class Ra0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=PZ1(A.storageDir,A.keyFile??hcQ)}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=mcQ();return await xZ1(this.keyFile,Q),Q}async getPublicJwk(){return TcQ(await this.getPrivateJwk())}async readExistingKey(){try{let A=jZ1.safeParse(JSON.parse(await kZ1(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return fZ1(A.data)}catch(A){if(RZ1(A))return;throw A}}}async function xZ1(A,Q){await fcQ(vcQ(A),{recursive:!0,mode:448}),await xcQ(A,`${JSON.stringify(Q,null,2)}
|
|
1752
1752
|
`,{mode:384}),await RcQ(A,384)}function RZ1(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var Aw={};Kw(Aw,{trimPadding:()=>CZ1,toUTF8String:()=>ocQ,toBuffer:()=>dcQ,toBase64:()=>ncQ,isBase64URL:()=>acQ,isBase64:()=>scQ,fromUTF8String:()=>rcQ,fromBuffer:()=>icQ});var vZ1=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),w=64;for(let $=0;$<64;$++)Q[A.charCodeAt($)]=$;return Q},ucQ=vZ1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),ccQ=vZ1("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),pcQ=/^[-A-Za-z0-9\-_]*$/,lcQ=/^[-A-Za-z0-9+/]*={0,3}$/,WV={};WV.toArrayBuffer=(A,Q)=>{let w=A.length,$=A.length*0.75,B,X=0,Y,Z,W,K;if(A[A.length-1]==="="){if($--,A[A.length-2]==="=")$--}let U=new ArrayBuffer($),G=new Uint8Array(U),D=Q?ccQ:ucQ;for(B=0;B<w;B+=4)Y=D[A.charCodeAt(B)],Z=D[A.charCodeAt(B+1)],W=D[A.charCodeAt(B+2)],K=D[A.charCodeAt(B+3)],G[X++]=Y<<2|Z>>4,G[X++]=(Z&15)<<4|W>>2,G[X++]=(W&3)<<6|K&63;return U};WV.fromArrayBuffer=(A,Q)=>{let w=new Uint8Array(A),$,B="",X=w.length,Y=Q?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for($=0;$<X;$+=3)B+=Y[w[$]>>2],B+=Y[(w[$]&3)<<4|w[$+1]>>4],B+=Y[(w[$+1]&15)<<2|w[$+2]>>6],B+=Y[w[$+2]&63];let Z=X%3;if(Z===2)B=B.substring(0,B.length-1)+(Q?"":"=");else if(Z===1)B=B.substring(0,B.length-2)+(Q?"":"==");return B};WV.toString=(A,Q)=>{return new TextDecoder().decode(WV.toArrayBuffer(A,Q))};WV.fromString=(A,Q)=>{return WV.fromArrayBuffer(new TextEncoder().encode(A),Q)};WV.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?pcQ.test(A):lcQ.test(A)}catch(w){return!1}};WV.base64=WV;var UN=WV;function dcQ(A,Q="base64url"){let w=UN.toArrayBuffer(A,Q==="base64url");return new Uint8Array(w)}function icQ(A,Q="base64url"){let w=new Uint8Array(A);return UN.fromArrayBuffer(w.buffer,Q==="base64url")}function ncQ(A){let Q=UN.toArrayBuffer(A,!0);return UN.fromArrayBuffer(Q)}function rcQ(A){return UN.fromString(A,!0)}function ocQ(A){return UN.toString(A,!0)}function scQ(A){return UN.validate(A,!1)}function acQ(A){return A=CZ1(A),UN.validate(A,!0)}function CZ1(A){return A.replace(/=/g,"")}var UH={};Kw(UH,{encode:()=>FpQ,decodeFirst:()=>VpQ});function qu(A,Q,w){if(Q<24)return[Q,1];let $=A.byteLength-w-1,B=new DataView(A.buffer,w+1),X,Y=0;switch(Q){case 24:{if($>0)X=B.getUint8(0),Y=2;break}case 25:{if($>1)X=B.getUint16(0,!1),Y=3;break}case 26:{if($>3)X=B.getUint32(0,!1),Y=5;break}case 27:{if($>7){let Z=B.getBigUint64(0,!1);if(Z>=24n&&Z<=Number.MAX_SAFE_INTEGER)return[Number(Z),9]}break}}if(X&&X>=24)return[X,Y];throw Error("Length not supported or not well formed")}var nG0=0,e00=1,va0=2,Ca0=3,ha0=4,Ea0=5,ga0=6,hZ1=7;function KV(A,Q){let w=A<<5;if(Q<0)throw Error("CBOR Data Item argument must not be negative");let $;if(typeof Q=="number"){if(!Number.isInteger(Q))throw Error("CBOR Data Item argument must be an integer");$=BigInt(Q)}else $=Q;if(A==e00){if($==0n)throw Error("CBOR Data Item argument cannot be zero when negative");$=$-1n}if($>18446744073709551615n)throw Error("CBOR number out of range");let B=new Uint8Array(8);if(new DataView(B.buffer).setBigUint64(0,$,!1),$<=23)return[w|B[7]];else if($<=255)return[w|24,B[7]];else if($<=65535)return[w|25,...B.slice(6)];else if($<=4294967295)return[w|26,...B.slice(4)];else return[w|27,...B]}class oG0{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 EZ1(A,Q,w){return qu(A,Q,w)}function tcQ(A,Q,w){let[$,B]=EZ1(A,Q,w);return[-$-1,B]}function gZ1(A,Q,w){let[$,B]=qu(A,Q,w),X=w+B;return[new Uint8Array(A.buffer.slice(X,X+$)),B+$]}var ecQ=new TextDecoder;function ApQ(A,Q,w){let[$,B]=gZ1(A,Q,w);return[ecQ.decode($),B]}function QpQ(A,Q,w){if(Q===0)return[[],1];let[$,B]=qu(A,Q,w),X=B,Y=[];for(let Z=0;Z<$;Z++){if(A.byteLength-w-X<=0)throw Error("array is not supported or well formed");let[K,U]=wv(A,w+X);Y.push(K),X+=U}return[Y,X]}var rG0="Map is not supported or well formed";function wpQ(A,Q,w){if(Q===0)return[new Map,1];let[$,B]=qu(A,Q,w),X=B,Y=new Map;for(let Z=0;Z<$;Z++){let W=A.byteLength-w-X;if(W<=0)throw Error(rG0);let[K,U]=wv(A,w+X);if(X+=U,W-=U,W<=0)throw Error(rG0);if(typeof K!=="string"&&typeof K!=="number")throw Error(rG0);if(Y.has(K))throw Error(rG0);let[G,D]=wv(A,w+X);X+=D,Y.set(K,G)}return[Y,X]}function $pQ(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 BpQ(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 XpQ(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 YpQ(A,Q,w){let[$,B]=qu(A,Q,w),[X,Y]=wv(A,w+B);return[new oG0($,X),B+Y]}function wv(A,Q){if(Q>=A.byteLength)throw Error("CBOR stream ended before tag value");let w=A.getUint8(Q),$=w>>5,B=w&31;switch($){case nG0:return EZ1(A,B,Q);case e00:return tcQ(A,B,Q);case va0:return gZ1(A,B,Q);case Ca0:return ApQ(A,B,Q);case ha0:return QpQ(A,B,Q);case Ea0:return wpQ(A,B,Q);case ga0:return YpQ(A,B,Q);case hZ1:switch(B){case 20:return[!1,1];case 21:return[!0,1];case 22:return[null,1];case 23:return[void 0,1];case 25:return $pQ(A,Q);case 26:return BpQ(A,Q);case 27:return XpQ(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function ZpQ(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function HpQ(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 WpQ(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return KV(e00,Math.abs(A));else return KV(nG0,A);return[HpQ(A)]}else if(A<0n)return KV(e00,A*-1n);else return KV(nG0,A)}var KpQ=new TextEncoder;function UpQ(A,Q){Q.push(...KV(Ca0,A.length)),Q.push(KpQ.encode(A))}function GpQ(A,Q){Q.push(...KV(va0,A.length)),Q.push(A)}function DpQ(A,Q){Q.push(...KV(ha0,A.length));for(let w of A)AA0(w,Q)}function qpQ(A,Q){Q.push(new Uint8Array(KV(Ea0,A.size)));for(let[w,$]of A.entries())AA0(w,Q),AA0($,Q)}function zpQ(A,Q){Q.push(...KV(ga0,A.tag)),AA0(A.value,Q)}function AA0(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(ZpQ(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...WpQ(A));return}if(typeof A=="string"){UpQ(A,Q);return}if(A instanceof Uint8Array){GpQ(A,Q);return}if(Array.isArray(A)){DpQ(A,Q);return}if(A instanceof Map){qpQ(A,Q);return}if(A instanceof oG0){zpQ(A,Q);return}throw Error("Not implemented")}function ya0(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return wv(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return wv(new DataView(A),Q);return wv(A,Q)}function Ta0(A){let Q=[];AA0(A,Q);let w=0;for(let X of Q)if(typeof X=="number")w+=1;else w+=X.length;let $=new Uint8Array(w),B=0;for(let X of Q)if(typeof X=="number")$[B]=X,B+=1;else $.set(X,B),B+=X.length;return $}function VpQ(A){let Q=new Uint8Array(A),w=ya0(Q,0),[$]=w;return $}function FpQ(A){return Ta0(A)}var GV={};Kw(GV,{verify:()=>FG1,getRandomValues:()=>uZ1,digest:()=>mZ1});function yZ1(A){let Q=A.get(nQ.kty);return Sa0(Q)&&Q===oK.OKP}function SP(A){let Q=A.get(nQ.kty);return Sa0(Q)&&Q===oK.EC2}function zu(A){let Q=A.get(nQ.kty);return Sa0(Q)&&Q===oK.RSA}var nQ;(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"})(nQ||(nQ={}));var oK;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(oK||(oK={}));function Sa0(A){return Object.values(oK).indexOf(A)>=0}var aY;(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"})(aY||(aY={}));function TZ1(A){return Object.values(aY).indexOf(A)>=0}var Cw;(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"})(Cw||(Cw={}));function UV(A){return Object.values(Cw).indexOf(A)>=0}function mP(A){if([Cw.RS1].indexOf(A)>=0)return"SHA-1";else if([Cw.ES256,Cw.PS256,Cw.RS256].indexOf(A)>=0)return"SHA-256";else if([Cw.ES384,Cw.PS384,Cw.RS384].indexOf(A)>=0)return"SHA-384";else if([Cw.ES512,Cw.PS512,Cw.RS512,Cw.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var QA0=void 0;function F3(){return new Promise((Q,w)=>{if(QA0)return Q(QA0);let $=LpQ.stubThisGlobalThisCrypto();if($)return QA0=$,Q(QA0);return w(new SZ1)})}class SZ1 extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var LpQ={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{QA0=A}};async function mZ1(A,Q){let w=await F3(),$=mP(Q),B=await w.subtle.digest($,A);return new Uint8Array(B)}async function uZ1(A){return(await F3()).getRandomValues(A),A}async function Ju(A){let Q=await F3(),{keyData:w,algorithm:$}=A;return Q.subtle.importKey("jwk",w,$,!1,["verify"])}async function sG0(A){let{cosePublicKey:Q,signature:w,data:$,shaHashOverride:B}=A,X=await F3(),Y=Q.get(nQ.alg),Z=Q.get(nQ.crv),W=Q.get(nQ.x),K=Q.get(nQ.y);if(!Y)throw Error("Public key was missing alg (EC2)");if(!Z)throw Error("Public key was missing crv (EC2)");if(!W)throw Error("Public key was missing x (EC2)");if(!K)throw Error("Public key was missing y (EC2)");let U;if(Z===aY.P256)U="P-256";else if(Z===aY.P384)U="P-384";else if(Z===aY.P521)U="P-521";else throw Error(`Unexpected COSE crv value of ${Z} (EC2)`);let G={kty:"EC",crv:U,x:Aw.fromBuffer(W),y:Aw.fromBuffer(K),ext:!1},z=await Ju({keyData:G,algorithm:{name:"ECDSA",namedCurve:U}}),V=mP(Y);if(B)V=mP(B);let I={name:"ECDSA",hash:{name:V}};return X.subtle.verify(I,z,w,$)}function ma0(A){if([Cw.EdDSA].indexOf(A)>=0)return"Ed25519";else if([Cw.ES256,Cw.ES384,Cw.ES512,Cw.ES256K].indexOf(A)>=0)return"ECDSA";else if([Cw.RS256,Cw.RS384,Cw.RS512,Cw.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([Cw.PS256,Cw.PS384,Cw.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 aG0(A){let{cosePublicKey:Q,signature:w,data:$,shaHashOverride:B}=A,X=await F3(),Y=Q.get(nQ.alg),Z=Q.get(nQ.n),W=Q.get(nQ.e);if(!Y)throw Error("Public key was missing alg (RSA)");if(!UV(Y))throw Error(`Public key had invalid alg ${Y} (RSA)`);if(!Z)throw Error("Public key was missing n (RSA)");if(!W)throw Error("Public key was missing e (RSA)");let K={kty:"RSA",alg:"",n:Aw.fromBuffer(Z),e:Aw.fromBuffer(W),ext:!1},U={name:ma0(Y),hash:{name:mP(Y)}},G={name:ma0(Y)};if(B)U.hash.name=mP(B);if(U.name==="RSASSA-PKCS1-v1_5"){if(U.hash.name==="SHA-256")K.alg="RS256";else if(U.hash.name==="SHA-384")K.alg="RS384";else if(U.hash.name==="SHA-512")K.alg="RS512";else if(U.hash.name==="SHA-1")K.alg="RS1"}else if(U.name==="RSA-PSS"){let z=0;if(U.hash.name==="SHA-256")K.alg="PS256",z=32;else if(U.hash.name==="SHA-384")K.alg="PS384",z=48;else if(U.hash.name==="SHA-512")K.alg="PS512",z=64;G.saltLength=z}else throw Error(`Unexpected RSA key algorithm ${Y} (${U.name})`);let D=await Ju({keyData:K,algorithm:U});return X.subtle.verify(G,D,w,$)}function tG0(A){let Q=t2.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 U7(A){let Q;if(typeof A==="string")if(Aw.isBase64URL(A))Q=Aw.toBase64(A);else if(Aw.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=Aw.fromBuffer(A,"base64");let w="";for(let $=0;$<Math.ceil(Q.length/64);$+=1){let B=64*$;w+=`${Q.substr(B,64)}
|
|
1753
1753
|
`}return w=`-----BEGIN CERTIFICATE-----
|
|
@@ -2319,14 +2319,14 @@ ${_}`)}if($!==void 0&&X?.algorithms!==void 0){let F=X.algorithms.map((_)=>_.alg)
|
|
|
2319
2319
|
</form>
|
|
2320
2320
|
</main>
|
|
2321
2321
|
</body>
|
|
2322
|
-
</html>`}function S10(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(QAA(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function jV(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as niQ}from"crypto";function R31(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function iiQ(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 $=Q[w+1];if($===void 0)throw Error("Invalid DER ECDSA signature");let B=w+2,X=Q.slice(B,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 Z=w+2,W=Q.slice(Z,Z+Y);return new Uint8Array([...v31(X),...v31(W)])}function v31(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 $AA(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},$=`${R31(w)}.${R31(Q)}`,B=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),X=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode($));return`${$}.${Buffer.from(iiQ(X)).toString("base64url")}`}var riQ=600;class BAA{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 S10(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let $=this.createAuthorizationApprovalToken(Q,w.params);return Cc(x31(w.params,$))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return S10(A);let w=await A.formData(),$=await this.validateAuthorizationRequest(new URLSearchParams(a0A(w)));if(!$.success)return new Response($.error,{status:400});let B=w.get("approval_token"),X=typeof B==="string"?B:void 0;if(!X||!this.consumeAuthorizationApprovalToken(X,Q,$.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:$.params.clientId,redirectUri:$.params.redirectUri,codeChallenge:$.params.codeChallenge,...$.params.scope?{scope:$.params.scope}:{},subject:Q.subject}),Z=new URL($.params.redirectUri);if(Z.searchParams.set("code",Y.code),$.params.state)Z.searchParams.set("state",$.params.state);return Response.redirect(Z.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${niQ()}`;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)+riQ}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let $=this.authorizationApprovalTokens.get(A);if(!$)return!1;return this.authorizationApprovalTokens.delete(A),$.sessionId===Q.id&&$.clientId===w.clientId&&$.redirectUri===w.redirectUri&&$.codeChallenge===w.codeChallenge&&$.scope===w.scope&&$.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"),$=A.get("redirect_uri"),B=A.get("code_challenge"),X=A.get("code_challenge_method"),Y=A.get("scope")??void 0,Z=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!$)return{success:!1,error:"Missing redirect_uri"};if(!B)return{success:!1,error:"Missing code_challenge"};if(X!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let W=await this.clientStore.getClient(w);if(!W)return{success:!1,error:"Unknown client_id"};if(!xa0(W.redirect_uris,$))return{success:!1,error:"Unregistered redirect_uri"};let K=Y??W.scope;return{success:!0,params:{clientId:w,redirectUri:$,codeChallenge:B,...K?{scope:K}:{},...Z?{state:Z}:{},clientName:W.client_name??W.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return bB("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return BU(w,201)}catch(w){if(w instanceof t00)return bB("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await s0A(A),$=w.get("grant_type"),B=e0A(A,w),X=B.clientId??w.get("client_id");if(B.error)return bB("invalid_client",B.error);if(!X)return bB("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=t0A(Y,B);if(Z)return bB("invalid_client",Z);if($==="authorization_code")return this.handleAuthorizationCodeGrant(w,X,Q);if($==="refresh_token")return this.handleRefreshTokenGrant(w,X,Q);return bB("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let $=A.get("code"),B=A.get("redirect_uri"),X=A.get("code_verifier");if(!$||!B||!X)return bB("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!xa0(Y.redirect_uris,B))return bB("invalid_grant","Unregistered redirect_uri");try{let Z=await this.authCodeStore.consumeCode({code:$,clientId:Q,redirectUri:B,codeVerifier:X});return await this.createTokenResponse({issuer:w,clientId:Q,subject:Z.subject,...Z.scope?{scope:Z.scope}:{}})}catch(Z){if(Z instanceof kq)return bB("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,w){let $=A.get("refresh_token");if(!$)return bB("invalid_request","refresh_token is required");try{let B=await this.refreshTokenStore.rotateToken($,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:B.consumed.subject,...B.consumed.scope?{scope:B.consumed.scope}:{},refreshToken:B.replacement.token})}catch(B){if(B instanceof hN)return bB("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,$=await $AA(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),B=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return BU({access_token:$,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await s0A(A),w=e0A(A,Q),$=w.clientId??Q.get("client_id")??void 0,B=Q.get("token");if(w.error)return bB("invalid_client",w.error);if(!B)return bB("invalid_request","token is required");if($){let X=await this.clientStore.getClient($),Y=t0A(X,w);if(Y)return bB("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,$),new Response(null,{status:200})}}class XAA{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 bB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return bB("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(RD0(A));return BU(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return bB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return bB("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),RD0(A));if(!Q.verified)return bB("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:E10(A)});return BU({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return bB("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(RD0(A));return BU(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),RD0(A));if(!Q.verified)return bB("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:E10(A)});return BU({verified:!0},200,{"Set-Cookie":w.cookie})}}function RD0(A){let Q=qM(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as oiQ}from"crypto";var m10=86400;class YAA{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??m10}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_${oiQ()}`,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 Eq(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:Eq(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:x0A(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 Cc(O31(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class vD0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=hq(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>hq(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??DM(this.issuer),this.keyStore=new iG0({storageDir:A.storageDir}),this.a2aKeyStore=new Ra0({storageDir:A.storageDir}),this.clientStore=new dG0({storageDir:A.storageDir}),this.authCodeStore=new lG0({storageDir:A.storageDir}),this.sessionStore=new MD0({storageDir:A.storageDir}),this.peerTrustStore=new _D0({storageDir:A.storageDir}),this.passkeyService=new ND0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new YAA({setupStateStore:new R0A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??m10}),this.oauthEndpoints=new BAA({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new bD0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new XAA({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(DM(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:Eq(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=hq(A);return{issuer:Q,authorization_endpoint:Eq(Q,"/authorize"),token_endpoint:Eq(Q,"/token"),registration_endpoint:Eq(Q,"/register"),revocation_endpoint:Eq(Q,"/revoke"),jwks_uri:Eq(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:[hq(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 S10(A)}async verifyBearerToken(A,Q={}){let w=o0A(A);if(!w)return;let $=Q.issuer?hq(Q.issuer):this.resolveRequestIssuer(A);return r0A(w,await this.getJwks(),{issuer:$,...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($){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:$ instanceof Error?$.message:String($)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&P31(w))return M31();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return FM(BU(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return FM(BU(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return FM(BU(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 FM(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return FM(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return FM(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=qM(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&DM(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=AAA(new URL(A.url).searchParams.get("return_to"));return Cc(QAA(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=AAA(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":C0A(E10(A)),"Cache-Control":"no-store"}})}}Se();$A();b0();var C31={name:"@brains/auth-service",version:"0.2.0-alpha.180",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var aiQ=H.union([H.string().email(),H.object({to:H.string().email(),subject:H.string().min(1),body:H.string().min(1)}).strict()]),tiQ=H.object({issuer:H.string().optional(),trustedIssuers:H.array(H.string()).default([]),allowLocalhostIssuers:H.boolean().optional(),storageDir:H.string().default("./data/auth"),setupTokenTtlSeconds:H.number().int().positive().default(m10),setupEmail:aiQ.optional()}),CD0;function pX(){return CD0}class ZAA extends Rw{service;constructor(A={}){super("auth-service",C31,A,tiQ)}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 vD0({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(),CD0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(CD0===this.service)CD0=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 $=eiQ(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,$.to))return;let B=await A.messaging.send({type:RR,payload:{recipient:{type:"email",address:$.to},title:$.subject,body:$.body,sensitivity:"secret"}});if(!("success"in B)||!B.success||!B.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let X=Te.safeParse(B.data);if(!X.success||X.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,$.to,X.data.deliveryId?{deliveryId:X.data.deliveryId}:{})}}function eiQ(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),$=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: ${$}/`,`MCP endpoint: ${$}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
|
|
2323
|
-
`)}}return{to:A.to,subject:h31(A.subject,Q),body:h31(A.body,Q)}}function h31(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),$=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",$)}function u10(A={}){return new ZAA(A)}b0();var HAA=H.object({transport:H.enum(["stdio","http"]).default("http"),mode:H.enum(["basic","debug"]).default("basic"),httpPort:H.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:H.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:H.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});b0();import{createHash as $nQ,randomUUID as BnQ}from"crypto";function AnQ(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function c10(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function QnQ(A){let Q=AnQ(A.data)?A.data:void 0,w=A.args,$=c10(Q,"entityId")??c10(Q,"id"),B=A.jobId??c10(Q,"jobId"),X=c10(w,"entityType")??c10(w,"type");if(!$&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...$?{entityId:$}:{},...B?{jobId:B}:{}}}function wnQ(A){return A?.map(QnQ).filter((Q)=>Q!==void 0)??[]}function WAA(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 $=wnQ(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...$.length>0?{readYourWrites:$}:{}}}}var E31=H.object({message:H.string().min(1),conversationId:H.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),g31=H.object({approvalId:H.string().min(1),confirmed:H.boolean(),conversationId:H.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function y31(A,Q,w,$){let B=A.conversationId??w??$??`conversation-${BnQ()}`,X=$nQ("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function T31(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 S31(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:E31.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=E31.parse(w),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=y31(B,$.userId,$.conversationId,$.channelId),Z=T31($),W=$.signal?await X.agent.chat(B.message,Y.internalId,Z,$.signal):await X.agent.chat(B.message,Y.internalId,Z);return WAA(W,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:g31.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=g31.parse(w),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=y31(B,$.userId,$.conversationId,$.channelId),Z=T31($),W=$.signal?await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z,$.signal):await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z);return WAA(W,{conversationId:Y.handle})}}]}$A();function KAA(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let $=Gy.safeParse(w.payload);if(!$.success)return Q.warn("Received invalid job-progress message",{error:$.error.message}),{success:!1};let B=$.data,X=B.type,Y=B.status,Z=B.id;if(Q.debug(`${X} ${Z} - ${Y}:`,{id:B.id,message:B.message,progress:B.progress,metadata:B.metadata}),B.batchDetails)Q.debug(`Batch details for ${Z}:`,{totalOperations:B.batchDetails.totalOperations,completedOperations:B.batchDetails.completedOperations,failedOperations:B.batchDetails.failedOperations,currentOperation:B.batchDetails.currentOperation,errors:B.batchDetails.errors});if(B.jobDetails)Q.debug(`Job details for ${Z}:`,{jobType:B.jobDetails.jobType,priority:B.jobDetails.priority,retryCount:B.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var m31={name:"@brains/mcp",version:"0.2.0-alpha.
|
|
2322
|
+
</html>`}function S10(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(QAA(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function jV(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as niQ}from"crypto";function R31(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function iiQ(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 $=Q[w+1];if($===void 0)throw Error("Invalid DER ECDSA signature");let B=w+2,X=Q.slice(B,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 Z=w+2,W=Q.slice(Z,Z+Y);return new Uint8Array([...v31(X),...v31(W)])}function v31(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 $AA(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},$=`${R31(w)}.${R31(Q)}`,B=await crypto.subtle.importKey("jwk",A,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),X=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},B,new TextEncoder().encode($));return`${$}.${Buffer.from(iiQ(X)).toString("base64url")}`}var riQ=600;class BAA{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 S10(A);let w=await this.validateAuthorizationRequest(new URL(A.url).searchParams);if(!w.success)return new Response(w.error,{status:400});let $=this.createAuthorizationApprovalToken(Q,w.params);return Cc(x31(w.params,$))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return S10(A);let w=await A.formData(),$=await this.validateAuthorizationRequest(new URLSearchParams(a0A(w)));if(!$.success)return new Response($.error,{status:400});let B=w.get("approval_token"),X=typeof B==="string"?B:void 0;if(!X||!this.consumeAuthorizationApprovalToken(X,Q,$.params))return new Response("Invalid authorization approval token",{status:400});let Y=await this.authCodeStore.createCode({clientId:$.params.clientId,redirectUri:$.params.redirectUri,codeChallenge:$.params.codeChallenge,...$.params.scope?{scope:$.params.scope}:{},subject:Q.subject}),Z=new URL($.params.redirectUri);if(Z.searchParams.set("code",Y.code),$.params.state)Z.searchParams.set("state",$.params.state);return Response.redirect(Z.toString(),302)}createAuthorizationApprovalToken(A,Q){this.pruneExpiredAuthorizationApprovalTokens();let w=`oat_${niQ()}`;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)+riQ}),w}consumeAuthorizationApprovalToken(A,Q,w){this.pruneExpiredAuthorizationApprovalTokens();let $=this.authorizationApprovalTokens.get(A);if(!$)return!1;return this.authorizationApprovalTokens.delete(A),$.sessionId===Q.id&&$.clientId===w.clientId&&$.redirectUri===w.redirectUri&&$.codeChallenge===w.codeChallenge&&$.scope===w.scope&&$.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"),$=A.get("redirect_uri"),B=A.get("code_challenge"),X=A.get("code_challenge_method"),Y=A.get("scope")??void 0,Z=A.get("state")??void 0;if(Q!=="code")return{success:!1,error:"Unsupported response_type"};if(!w)return{success:!1,error:"Missing client_id"};if(!$)return{success:!1,error:"Missing redirect_uri"};if(!B)return{success:!1,error:"Missing code_challenge"};if(X!=="S256")return{success:!1,error:"Unsupported code_challenge_method"};let W=await this.clientStore.getClient(w);if(!W)return{success:!1,error:"Unknown client_id"};if(!xa0(W.redirect_uris,$))return{success:!1,error:"Unregistered redirect_uri"};let K=Y??W.scope;return{success:!0,params:{clientId:w,redirectUri:$,codeChallenge:B,...K?{scope:K}:{},...Z?{state:Z}:{},clientName:W.client_name??W.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return bB("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return BU(w,201)}catch(w){if(w instanceof t00)return bB("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await s0A(A),$=w.get("grant_type"),B=e0A(A,w),X=B.clientId??w.get("client_id");if(B.error)return bB("invalid_client",B.error);if(!X)return bB("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=t0A(Y,B);if(Z)return bB("invalid_client",Z);if($==="authorization_code")return this.handleAuthorizationCodeGrant(w,X,Q);if($==="refresh_token")return this.handleRefreshTokenGrant(w,X,Q);return bB("unsupported_grant_type","Only authorization_code and refresh_token are supported")}async handleAuthorizationCodeGrant(A,Q,w){let $=A.get("code"),B=A.get("redirect_uri"),X=A.get("code_verifier");if(!$||!B||!X)return bB("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!xa0(Y.redirect_uris,B))return bB("invalid_grant","Unregistered redirect_uri");try{let Z=await this.authCodeStore.consumeCode({code:$,clientId:Q,redirectUri:B,codeVerifier:X});return await this.createTokenResponse({issuer:w,clientId:Q,subject:Z.subject,...Z.scope?{scope:Z.scope}:{}})}catch(Z){if(Z instanceof kq)return bB("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,w){let $=A.get("refresh_token");if(!$)return bB("invalid_request","refresh_token is required");try{let B=await this.refreshTokenStore.rotateToken($,Q);return await this.createTokenResponse({issuer:w,clientId:Q,subject:B.consumed.subject,...B.consumed.scope?{scope:B.consumed.scope}:{},refreshToken:B.replacement.token})}catch(B){if(B instanceof hN)return bB("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,$=await $AA(await this.keyStore.getPrivateJwk(),{iss:A.issuer,sub:A.subject,aud:A.clientId,iat:Q,exp:Q+900,...A.scope?{scope:A.scope}:{}}),B=A.refreshToken??(await this.refreshTokenStore.issueToken({clientId:A.clientId,subject:A.subject,...A.scope?{scope:A.scope}:{}})).token;return BU({access_token:$,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await s0A(A),w=e0A(A,Q),$=w.clientId??Q.get("client_id")??void 0,B=Q.get("token");if(w.error)return bB("invalid_client",w.error);if(!B)return bB("invalid_request","token is required");if($){let X=await this.clientStore.getClient($),Y=t0A(X,w);if(Y)return bB("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,$),new Response(null,{status:200})}}class XAA{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 bB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return bB("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(RD0(A));return BU(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return bB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return bB("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),RD0(A));if(!Q.verified)return bB("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:E10(A)});return BU({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return bB("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(RD0(A));return BU(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),RD0(A));if(!Q.verified)return bB("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:E10(A)});return BU({verified:!0},200,{"Set-Cookie":w.cookie})}}function RD0(A){let Q=qM(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as oiQ}from"crypto";var m10=86400;class YAA{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??m10}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_${oiQ()}`,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 Eq(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:Eq(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:x0A(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 Cc(O31(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class vD0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=hq(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>hq(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??DM(this.issuer),this.keyStore=new iG0({storageDir:A.storageDir}),this.a2aKeyStore=new Ra0({storageDir:A.storageDir}),this.clientStore=new dG0({storageDir:A.storageDir}),this.authCodeStore=new lG0({storageDir:A.storageDir}),this.sessionStore=new MD0({storageDir:A.storageDir}),this.peerTrustStore=new _D0({storageDir:A.storageDir}),this.passkeyService=new ND0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new YAA({setupStateStore:new R0A({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??m10}),this.oauthEndpoints=new BAA({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new bD0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new XAA({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(DM(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:Eq(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=hq(A);return{issuer:Q,authorization_endpoint:Eq(Q,"/authorize"),token_endpoint:Eq(Q,"/token"),registration_endpoint:Eq(Q,"/register"),revocation_endpoint:Eq(Q,"/revoke"),jwks_uri:Eq(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:[hq(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 S10(A)}async verifyBearerToken(A,Q={}){let w=o0A(A);if(!w)return;let $=Q.issuer?hq(Q.issuer):this.resolveRequestIssuer(A);return r0A(w,await this.getJwks(),{issuer:$,...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($){return this.logger?.warn("Rejected OAuth request from untrusted issuer",{error:$ instanceof Error?$.message:String($)}),new Response("Untrusted OAuth issuer",{status:400})}let w=new URL(A.url).pathname;if(A.method==="OPTIONS"&&P31(w))return M31();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return FM(BU(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return FM(BU(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return FM(BU(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 FM(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return FM(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return FM(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=qM(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&DM(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=AAA(new URL(A.url).searchParams.get("return_to"));return Cc(QAA(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=AAA(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":C0A(E10(A)),"Cache-Control":"no-store"}})}}Se();$A();b0();var C31={name:"@brains/auth-service",version:"0.2.0-alpha.181",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var aiQ=H.union([H.string().email(),H.object({to:H.string().email(),subject:H.string().min(1),body:H.string().min(1)}).strict()]),tiQ=H.object({issuer:H.string().optional(),trustedIssuers:H.array(H.string()).default([]),allowLocalhostIssuers:H.boolean().optional(),storageDir:H.string().default("./data/auth"),setupTokenTtlSeconds:H.number().int().positive().default(m10),setupEmail:aiQ.optional()}),CD0;function pX(){return CD0}class ZAA extends Rw{service;constructor(A={}){super("auth-service",C31,A,tiQ)}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 vD0({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(),CD0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(CD0===this.service)CD0=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 $=eiQ(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,$.to))return;let B=await A.messaging.send({type:RR,payload:{recipient:{type:"email",address:$.to},title:$.subject,body:$.body,sensitivity:"secret"}});if(!("success"in B)||!B.success||!B.data){A.logger.warn("Passkey setup email delivery was not confirmed");return}let X=Te.safeParse(B.data);if(!X.success||X.data.status!=="sent"){A.logger.warn("Passkey setup email delivery was not confirmed");return}await Q.recordSetupEmailDelivery(w.setupTokenId,$.to,X.data.deliveryId?{deliveryId:X.data.deliveryId}:{})}}function eiQ(A,Q){if(typeof A==="string"){let w=new Date(Q.expiresAt*1000).toISOString(),$=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: ${$}/`,`MCP endpoint: ${$}/mcp`,"The first successful passkey registration completes setup and closes this link."].join(`
|
|
2323
|
+
`)}}return{to:A.to,subject:h31(A.subject,Q),body:h31(A.body,Q)}}function h31(A,Q){let w=new Date(Q.expiresAt*1000).toISOString(),$=new URL(Q.setupUrl).origin;return A.replaceAll("{{setupUrl}}",Q.setupUrl).replaceAll("{{expiresAt}}",w).replaceAll("{{origin}}",$)}function u10(A={}){return new ZAA(A)}b0();var HAA=H.object({transport:H.enum(["stdio","http"]).default("http"),mode:H.enum(["basic","debug"]).default("basic"),httpPort:H.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:H.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:H.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});b0();import{createHash as $nQ,randomUUID as BnQ}from"crypto";function AnQ(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function c10(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function QnQ(A){let Q=AnQ(A.data)?A.data:void 0,w=A.args,$=c10(Q,"entityId")??c10(Q,"id"),B=A.jobId??c10(Q,"jobId"),X=c10(w,"entityType")??c10(w,"type");if(!$&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...$?{entityId:$}:{},...B?{jobId:B}:{}}}function wnQ(A){return A?.map(QnQ).filter((Q)=>Q!==void 0)??[]}function WAA(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 $=wnQ(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...$.length>0?{readYourWrites:$}:{}}}}var E31=H.object({message:H.string().min(1),conversationId:H.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),g31=H.object({approvalId:H.string().min(1),confirmed:H.boolean(),conversationId:H.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function y31(A,Q,w,$){let B=A.conversationId??w??$??`conversation-${BnQ()}`,X=$nQ("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function T31(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 S31(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:E31.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=E31.parse(w),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=y31(B,$.userId,$.conversationId,$.channelId),Z=T31($),W=$.signal?await X.agent.chat(B.message,Y.internalId,Z,$.signal):await X.agent.chat(B.message,Y.internalId,Z);return WAA(W,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:g31.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=g31.parse(w),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=y31(B,$.userId,$.conversationId,$.channelId),Z=T31($),W=$.signal?await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z,$.signal):await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,Z);return WAA(W,{conversationId:Y.handle})}}]}$A();function KAA(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let $=Gy.safeParse(w.payload);if(!$.success)return Q.warn("Received invalid job-progress message",{error:$.error.message}),{success:!1};let B=$.data,X=B.type,Y=B.status,Z=B.id;if(Q.debug(`${X} ${Z} - ${Y}:`,{id:B.id,message:B.message,progress:B.progress,metadata:B.metadata}),B.batchDetails)Q.debug(`Batch details for ${Z}:`,{totalOperations:B.batchDetails.totalOperations,completedOperations:B.batchDetails.completedOperations,failedOperations:B.batchDetails.failedOperations,currentOperation:B.batchDetails.currentOperation,errors:B.batchDetails.errors});if(B.jobDetails)Q.debug(`Job details for ${Z}:`,{jobType:B.jobDetails.jobType,priority:B.jobDetails.priority,retryCount:B.jobDetails.retryCount});return{success:!0}}),Q.debug("Subscribed to job progress events")}var m31={name:"@brains/mcp",version:"0.2.0-alpha.181",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 IM extends iJ{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",m31,Q,HAA)}async getTools(){return S31(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"});KAA(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=pX();return this.httpServer=KN.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),$=pX(),B=this.config.transport==="http"&&(this.config.authToken?!0:$!==void 0);if(B)w="anchor",this.logger.debug("HTTP authentication configured - authenticated users will have anchor permissions");if(this.config.mode==="debug"){if(this.config.transport==="http"&&!B)throw Error("MCP debug mode requires authenticated HTTP transport; configure authToken or OAuth auth service.");if(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=bq.createFresh();let X=this.mcpTransport.getMcpServer();this.stdioServer.connectMCPServer(X),await this.stdioServer.start(),this.logger.debug("MCP STDIO transport started")}else{this.httpServer=this.getOrCreateHttpServer();let X=this.mcpTransport.getMcpServer();this.httpServer.connectMCPServer(X,this.mcpTransport),this.logger.debug("MCP HTTP transport mounted on shared webserver host")}}async stopServer(){if(this.logger.debug(`Stopping MCP ${this.config.transport} transport`),this.stdioServer)this.stdioServer.stop(),this.stdioServer=void 0;if(this.httpServer)await this.httpServer.stop(),this.httpServer=void 0;this.mcpTransport=void 0}async handleProgressEvent(A,Q){}async onShutdown(){bq.resetInstance(),KN.resetInstance()}}$A();function p10(A,Q=2000){if(A.length<=Q)return[A];let w=HnQ(A),$=[],B="";for(let X of w){let Y=B?`
|
|
2324
2324
|
|
|
2325
2325
|
`:"";if(B.length+Y.length+X.length<=Q){B+=Y+X;continue}if(B)$.push(B),B="";if(X.length<=Q){B=X;continue}YnQ(X,Q,$,(Z)=>{B=Z})}if(B)$.push(B);return $}function YnQ(A,Q,w,$){let B="",X=A.split(`
|
|
2326
2326
|
`);for(let Y of X){let Z=B?`
|
|
2327
2327
|
`:"";if(B.length+Z.length+Y.length<=Q){B+=Z+Y;continue}if(B)w.push(B),B="";if(Y.length<=Q){B=Y;continue}ZnQ(Y,Q,w,(W)=>{B=W})}$(B)}function ZnQ(A,Q,w,$){let B="",X=A.split(" ");for(let Y of X){let Z=B?" ":"";if(B.length+Z.length+Y.length<=Q){B+=Z+Y;continue}if(B)w.push(B);if(Y.length>Q)for(let W=0;W<Y.length;W+=Q){let K=Y.slice(W,W+Q);if(W+Q>=Y.length)B=K;else w.push(K)}else B=Y}$(B)}function HnQ(A){let Q=[],w=A.split(`
|
|
2328
2328
|
`),$="",B=!1;for(let X of w){if(X.startsWith("```"))B=!B;if(!B&&X===""&&$){Q.push($),$="";continue}$+=($?`
|
|
2329
|
-
`:"")+X}if($)Q.push($);return Q}R2();var DU=V1(M8A(),1);$A();b0();var j8A=H.object({botToken:H.string().min(1).describe("Discord bot token"),allowedChannels:H.array(H.string()).default([]),requireMention:H.boolean().default(!0),allowDMs:H.boolean().default(!0),showTypingIndicator:H.boolean().default(!0),statusMessage:H.string().default("Mention me to chat"),useThreads:H.boolean().default(!0),threadAutoArchive:H.union([H.literal(60),H.literal(1440),H.literal(4320),H.literal(10080)]).default(1440),...Jt.shape,captureUrlEmoji:H.string().default("\uD83D\uDD16")});var tA2={name:"@brains/discord",version:"0.2.0-alpha.
|
|
2329
|
+
`:"")+X}if($)Q.push($);return Q}R2();var DU=V1(M8A(),1);$A();b0();var j8A=H.object({botToken:H.string().min(1).describe("Discord bot token"),allowedChannels:H.array(H.string()).default([]),requireMention:H.boolean().default(!0),allowDMs:H.boolean().default(!0),showTypingIndicator:H.boolean().default(!0),statusMessage:H.string().default("Mention me to chat"),useThreads:H.boolean().default(!0),threadAutoArchive:H.union([H.literal(60),H.literal(1440),H.literal(4320),H.literal(10080)]).default(1440),...Jt.shape,captureUrlEmoji:H.string().default("\uD83D\uDD16")});var tA2={name:"@brains/discord",version:"0.2.0-alpha.181",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 OQ0=2000,yMw={completed:"Action completed",declined:"Action declined",failed:"Action failed"},TMw={completed:2278750,declined:9741240,failed:15680580},SMw=8388608,mMw=8000,uMw=100;function eJ0(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class Bj extends wq{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",tA2,A,j8A);this.fetchText=Q.fetchText??l81}async onRegister(A){await super.onRegister(A),this.client=new DU.Client({intents:[DU.GatewayIntentBits.Guilds,DU.GatewayIntentBits.GuildMessages,DU.GatewayIntentBits.MessageContent,DU.GatewayIntentBits.DirectMessages],partials:[DU.Partials.Channel]}),this.client.on(DU.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(DU.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(DU.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(!eJ0(w))return;let $=p10(Q,OQ0);for(let B of $)w.send(B).catch((X)=>this.logger.error("Failed to send message",{error:X}))}async sendMessageWithId({channelId:A,message:Q,approvalCard:w,approvalCards:$}){let B=$??(w?[w]:[]),X=B.length>0?this.buildApprovalMessagePayload(Q,B):Q;return this.sendPayloadWithId(A,X)}async sendPayloadWithId(A,Q){if(!A||!this.client)return;let w=this.client.channels.cache.get(A);if(!eJ0(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let $=p10(Q,OQ0),B;for(let X of $)B=(await w.send(X)).id;return B}async editMessage({channelId:A,messageId:Q,newMessage:w}){if(!A||!this.client)return!1;let $=this.client.channels.cache.get(A);if(!eJ0($))return!1;try{return await(await $.messages.fetch(Q)).edit(w.slice(0,OQ0)),!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 $=!!this.client?.user&&A.mentions.has(this.client.user,{ignoreEveryone:!0});if(A.author.bot&&!$)return;let B=w&&"ownerId"in A.channel&&A.channel.ownerId===this.client?.user?.id,X=this.getSpaceChannelId(A),Y=!Q&&this.isConfiguredSpace(X),Z={channelId:X,isBot:A.author.bot};if(this.config.allowedChannels.length>0&&!Q&&!this.isAllowedChannel(A.channel.id,X))return;let W=Q||B||!this.config.requireMention||$;if(Y&&(!W||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,X).catch((G)=>this.logger.error("Passive Discord space capture failed",{error:G,channelId:X}));if(!W){if(this.config.captureUrls){let G=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(G.length>0){await A.react(this.config.captureUrlEmoji).catch((D)=>this.logger.debug("React failed",{error:D}));for(let D of G)await this.captureUrlViaAgent(D,A.channel.id,A.author.id,"discord",Z).catch((z)=>this.logger.error("URL capture failed",{error:z,url:D}))}}return}let K=this.stripMention(A.content);if(A.attachments.size>0){let G=this.context.permissions.getUserLevel("discord",A.author.id,Z);if(G==="anchor"||G==="trusted")for(let z of A.attachments.values()){let V=z.name,I=z.contentType??void 0,F=z.size;if(!this.isUploadableTextFile(V,I))continue;if(!this.isFileSizeAllowed(F))continue;try{let _=await this.fetchText(z.url);K+=`
|
|
2330
2330
|
|
|
2331
2331
|
`+this.formatFileUploadMessage(V,_)}catch(_){this.logger.error("Failed to download attachment",{error:_,filename:V})}}}if(K=K.trim(),!K)return;let U=A.channel.id;await this.routeToAgent(K,U,A,Z)}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 B=this.buildInteractionConfirmationContext(A),X=await this.context.agent.confirmPendingAction(w,Q.confirmed,Q.approvalId,B);await this.handleAgentResponseToolStatuses(X,w),this.syncPendingApprovalsAfterResolution(w,Q.approvalId,X),await this.sendApprovalResultMessage({channelId:A.channelId,response:X,userPermissionLevel:B.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 $=`discord-${Q}`,B=this.getChannelName(A);await this.context.conversations.start({sessionId:$,interfaceType:"discord",channelId:Q,metadata:{channelName:B,interfaceType:"discord",channelId:Q}}),await this.context.conversations.addMessage({conversationId:$,role:"user",content:w,metadata:this.buildUserMessageMetadata(A,Q,B,{threadId:A.channel.isThread()?A.channel.id:void 0})})}async routeToAgent(A,Q,w,$){if(!this.context)return;let B=this.context.agent,X=Q;if(this.config.useThreads&&w.guild&&!w.channel.isThread())try{X=(await w.startThread({name:uZ(A,uMw),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(K){this.logger.error("Failed to create thread",{error:K})}let Y=`discord-${X}`,Z=this.context.permissions.getUserLevel("discord",w.author.id,$),W=this.getChannelName(w);this.startProcessingInput(X);try{let K=this.client?.channels.cache.get(X);if(eJ0(K))this.startTypingIndicator(K);if(this.pendingConfirmations.has(Y)){if(await this.handleConfirmationResponse(A,Y,X,w,$))return}let U=await B.chat(A,Y,{userPermissionLevel:Z,interfaceType:"discord",channelId:X,channelName:W,...this.buildUserMessageMetadata(w,Q,W,{threadId:X!==Q||w.channel.isThread()?X:void 0})});await this.handleAgentResponseToolStatuses(U,Y);let G=WR(U.cards);if(G.length>0)this.pendingConfirmations.set(Y,new Set(G.map((z)=>z.id)));else if(U.pendingConfirmations)this.pendingConfirmations.set(Y,new Set(U.pendingConfirmations.map((z)=>z.id)));else this.pendingConfirmations.delete(Y);let D=await this.sendMessageWithId({channelId:X,message:fS(U.text,G),approvalCards:G});if(D&&U.toolResults){for(let z of U.toolResults)if(z.jobId)this.trackAgentResponseForJob(z.jobId,D,X)}}catch(K){this.logger.error("Error handling message",{error:K,channelId:X}),this.sendMessageToChannel({channelId:X,message:`**Error:** ${K instanceof Error?K.message:"Unknown error"}`})}finally{this.endProcessingInput(),this.stopTypingIndicator(X)}}buildApprovalMessagePayload(A,Q){let w=Q.length>1;return{content:uZ(A.trim().length>0?`${A}
|
|
2332
2332
|
|
|
@@ -2396,7 +2396,7 @@ ${A.value}
|
|
|
2396
2396
|
`);if($V0(A))return this.renderList(A,0,(Q)=>this.nodeToDiscordMarkdown(Q));if(A.type==="break")return`
|
|
2397
2397
|
`;if(A.type==="thematicBreak")return"---";if(T5A(A))return`\`\`\`
|
|
2398
2398
|
${S5A(A)}
|
|
2399
|
-
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var F42={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},qV0="https://discord.com/api/v10",I42=2000,Nhw=/^[0-9a-f]{64}$/,_hw=/^[0-9a-f]+$/,bhw=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new Lhw;requestContext=new Khw;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new m3("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let $=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!$)throw new m3("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let B=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!B)throw new m3("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??qV0,this.botToken=w,this.publicKey=$.trim().toLowerCase(),this.applicationId=B,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((X)=>X.trim()):[]),this.botUserId=B,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new KV0("info").child("discord"),this.userName=Q.userName??"bot",!Nhw.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:_hw.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let $=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:$.avatar?`https://cdn.discordapp.com/avatars/${$.id}/${$.avatar}.png`:void 0,email:void 0,fullName:$.global_name||$.username,isBot:$.bot??!1,userId:$.id,userName:$.username}}catch{return null}}async handleWebhook(Q,w){let $=await Q.arrayBuffer(),B=new Uint8Array($),X=new TextDecoder().decode(B),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 G=JSON.parse(X);return this.handleForwardedGatewayEvent(G,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:X.length,bodyBytesLength:B.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let Z=Q.headers.get("x-signature-ed25519"),W=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature(B,Z,W))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let U;try{U=JSON.parse(X)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:U.type,typeIsPing:U.type===rp.Ping,expectedPingType:rp.Ping,id:U.id}),U.type===rp.Ping){let G=JSON.stringify({type:mQ0.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:G,responseType:mQ0.InteractionResponseType.PONG}),new Response(G,{status:200,headers:{"Content-Type":"application/json"}})}if(U.type===rp.MessageComponent)return this.handleComponentInteraction(U,w),this.respondToInteraction({type:F42.DeferredUpdateMessage});if(U.type===rp.ApplicationCommand){let G=this.getApplicationCommandContext(U),D=this.getInteractionFlags(G);return this.handleApplicationCommandInteraction(G,w),this.respondToInteraction({...D===void 0?{}:{data:{flags:D}},type:F42.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,$){if(!(w&&$))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!$}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:$.length,publicKeyLength:this.publicKey.length,timestamp:$,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let B=await mQ0.verifyKey(Q,w,$,this.publicKey);if(!B){let X=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:$,bodyLength:Q.length,bodyPrefix:X.slice(0,50)})}return B}catch(B){return this.logger.warn("Discord signature verification failed: exception",{error:B}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let $=Q.data?.custom_id;if(!$){this.logger.warn("No custom_id in component interaction");return}let B=Q.member?.user||Q.user;if(!B){this.logger.warn("No user in component interaction");return}let X=Q.channel_id,Y=Q.guild_id||"@me",Z=Q.message?.id;if(!(X&&Z)){this.logger.warn("Missing channel_id or message_id in interaction");return}let W=Q.channel,K=W?.type===11||W?.type===12,U=K&&W?.parent_id?W.parent_id:X,G=K?this.encodeThreadId({guildId:Y,channelId:U,threadId:X}):this.encodeThreadId({guildId:Y,channelId:X}),D=Ghw($),z={actionId:D.actionId,value:D.value??D.actionId,user:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:B.bot??!1,isMe:!1},messageId:Z,threadId:G,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:$,messageId:Z,threadId:G}),this.chat.processAction(z,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let $=Q.member?.user||Q.user;if(!$)return this.logger.warn("No user in application command interaction"),null;let B=Q.channel_id;if(!B)return this.logger.warn("Missing channel_id in application command interaction"),null;let X=Q.guild_id||"@me",Y=Q.channel,Z=Y?.type===11||Y?.type===12,W=Z&&Y?.parent_id?Y.parent_id:B,K=Z?this.encodeThreadId({guildId:X,channelId:W,threadId:B}):this.encodeThreadId({guildId:X,channelId:B}),{command:U,text:G}=this.parseSlashCommand(w,Q.data?.options);return{channelId:K,command:U,interaction:Q,text:G,user:$}}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:$,command:B,interaction:X,text:Y,user:Z}=Q;this.logger.debug("Processing Discord slash command",{command:B,text:Y,userId:Z.id,channelId:$}),this.requestContext.run({slashCommand:{channelId:$,interactionToken:X.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:B,text:Y,user:{userId:Z.id,userName:Z.username,fullName:Z.global_name||Z.username,isBot:Z.bot??!1,isMe:Z.id===this.applicationId},adapter:this,raw:X,channelId:$},w)})}parseSlashCommand(Q,w){let $=[Q.startsWith("/")?Q:`/${Q}`],B=[],X=(Y)=>{for(let Z of Y){if(Z.value!==void 0){B.push(String(Z.value));continue}if(Z.options&&Z.options.length>0)$.push(Z.name),X(Z.options)}};if(w&&w.length>0)X(w);return{command:$.join(" "),text:B.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),$=this.getInteractionFlags(w);await Q.deferReply($===void 0?void 0:{flags:$}),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 $=Q.guild_id||"@me",B=Q.channel_id,X,Y=B;if(Q.thread)X=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let z=await(await this.discordFetch(`/channels/${B}`,"GET")).json();if(z.parent_id)X=B,Y=z.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:B,parentId:z.parent_id})}catch(D){this.logger.error("Failed to fetch thread parent",{error:String(D),channelId:B})}let Z=Q.is_mention||Q.mentions.some((D)=>D.id===this.applicationId),W=this.mentionRoleIds.length>0&&Q.mention_roles?.some((D)=>this.mentionRoleIds.includes(D)),K=Z||W;if(!X&&K)try{let D=await this.createDiscordThread(B,Q.id);X=D.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:B,messageId:Q.id,threadId:D.id})}catch(D){this.logger.error("Failed to create Discord thread for mention",{error:String(D),messageId:Q.id})}let U=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),G=new P9({id:Q.id,threadId:U,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((D)=>({type:this.getAttachmentType(D.content_type),url:D.url,name:D.filename,mimeType:D.content_type,size:D.size})),raw:Q,isMention:K});try{await this.chat.handleIncomingMessage(this,U,G)}catch(D){this.logger.error("Error handling forwarded message",{error:String(D),messageId:Q.id})}}async handleForwardedReaction(Q,w,$){if(!this.chat)return;let B=Q.guild_id||"@me",X=Q.channel_id,Y,Z=X;if(Q.channel_type===TC.GuildPublicThread||Q.channel_type===TC.GuildPrivateThread){let z=this.threadParentCache.get(X);if(z&&z.expiresAt>Date.now())Y=X,Z=z.parentId;else try{let I=await(await this.discordFetch(`/channels/${X}`,"GET")).json();if(I.parent_id)Y=X,Z=I.parent_id,this.threadParentCache.set(X,{parentId:I.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(V){this.logger.error("Failed to fetch thread parent for reaction",{error:String(V),channelId:X})}}let W=this.encodeThreadId({guildId:B,channelId:Z,threadId:Y}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G=Q.user??Q.member?.user;if(!G){this.logger.warn("Reaction event missing user info",{data:Q});return}let D={adapter:this,threadId:W,messageId:Q.message_id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:w,user:{userId:G.id,userName:G.username,fullName:G.username,isBot:G.bot===!0,isMe:G.id===this.applicationId},raw:Q};this.chat.processReaction(D)}async postMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=Q;if(B)$=B;let Y={},Z=[],W=[],K=DV0(w);if(K){let V=kBA(K);Z.push(...V.embeds),W.push(...V.components)}else Y.content=this.truncateContent(hC(this.formatConverter.renderPostable(w),"discord"));if(Z.length>0)Y.embeds=Z;if(W.length>0)Y.components=W;let U=wBA(w),G=this.tryPostSlashResponse(X,Y,U);if(G)return G;if(U.length>0)return this.postMessageWithFiles($,X,Y,U);this.logger.debug("Discord API: POST message",{channelId:$,contentLength:Y.content?.length||0,embedCount:Z.length,componentCount:W.length});let z=await(await this.discordFetch(`/channels/${$}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:z.id}),{id:z.id,threadId:X,raw:z}}tryPostSlashResponse(Q,w,$){let B=this.requestContext.getStore()?.slashCommand;if(!B||B.channelId!==Q)return;return this.postSlashCommandResponse(B,Q,w,$)}async postSlashCommandResponse(Q,w,$,B){let X=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=X?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,Z=X?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:X,hasFiles:B.length>0});let K=await(B.length>0?await this.discordInteractionFetchWithFiles(Y,Z,$,B):await this.discordInteractionFetch(Y,Z,$)).json();return{id:K.id,threadId:w,raw:K}}async createDiscordThread(Q,w){let $=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:$});try{let X=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:$,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:X.id,threadName:X.name}),X}catch(B){if(B instanceof Hj&&typeof B.message==="string"&&B.message.includes('"code"')&&B.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:$};throw B}}truncateContent(Q){if(Q.length<=I42)return Q;return`${Q.slice(0,I42-3)}...`}async postMessageWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let W=0;W<B.length;W++){let K=B[W];if(!K)continue;let U=await $BA(K.data,{platform:"discord"});if(!U)continue;let G=new Blob([new Uint8Array(U)],{type:K.mimeType||"application/octet-stream"});X.append(`files[${W}]`,G,K.filename)}let Y=await fetch(`${qV0}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:X});if(!Y.ok){let W=await Y.text();throw new Hj("discord",`Failed to post message: ${Y.status} ${W}`)}let Z=await Y.json();return{id:Z.id,threadId:w,raw:Z}}async discordInteractionFetch(Q,w,$){let B=await fetch(`${qV0}${Q}`,{method:w,headers:$?{"Content-Type":"application/json"}:void 0,body:$?JSON.stringify($):void 0});if(!B.ok){let X=await B.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:B.status,error:X}),new Hj("discord",`Discord interaction API error: ${B.status} ${X}`)}return B}async discordInteractionFetchWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let Z=0;Z<B.length;Z++){let W=B[Z];if(!W)continue;let K=await $BA(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});X.append(`files[${Z}]`,U,W.filename)}let Y=await fetch(`${qV0}${Q}`,{method:w,body:X});if(!Y.ok){let Z=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:Z}),new Hj("discord",`Discord interaction API error: ${Y.status} ${Z}`)}return Y}async editMessage(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z={},W=[],K=[],U=DV0($);if(U){let z=kBA(U);W.push(...z.embeds),K.push(...z.components),Z.content=""}else Z.content=this.truncateContent(hC(this.formatConverter.renderPostable($),"discord"));if(W.length>0)Z.embeds=W;if(K.length>0)Z.components=K;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:Z.content?.length||0});let D=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",Z)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:D.id}),{id:D.id,threadId:Q,raw:D}}async deleteMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$;this.logger.debug("Discord API: DELETE message",{channelId:X,messageId:w}),await this.discordFetch(`/channels/${X}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z=this.encodeEmoji($);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:Z}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${Z}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z=this.encodeEmoji($);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:Z}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${Z}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=EQ0.toDiscord?EQ0.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$;this.logger.debug("Discord API: POST typing",{channelId:X}),await this.discordFetch(`/channels/${X}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$,Y=w.limit||50,Z=w.direction??"backward",W=new URLSearchParams;if(W.set("limit",String(Y)),w.cursor)if(Z==="backward")W.set("before",w.cursor);else W.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:X,limit:Y,direction:Z,cursor:w.cursor});let U=await(await this.discordFetch(`/channels/${X}/messages?${W.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:U.length});let D=[...U].reverse().map((V)=>this.parseDiscordMessage(V,Q)),z;if(U.length===Y)if(Z==="backward")z=U.at(-1)?.id;else z=U[0]?.id;return{messages:D,nextCursor:z}}async fetchThread(Q){let{channelId:w,guildId:$}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let X=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:X.name,isDM:X.type===TC.DM||X.type===TC.GroupDM,metadata:{guildId:$,channelType:X.type,raw:X}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let $=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:$.id}),this.encodeThreadId({guildId:"@me",channelId:$.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 m3("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,$=w.guild_id||"@me",B=this.encodeThreadId({guildId:$,channelId:w.channel_id});return this.parseDiscordMessage(w,B)}parseDiscordMessage(Q,w){let $=Q.type===J82.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,B=$.author,X=B.bot??!1,Y=B.id===this.botUserId;return new P9({id:$.id,threadId:w,text:this.formatConverter.extractPlainText($.content),formatted:this.formatConverter.toAst($.content),raw:Q,author:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:X,isMe:Y},metadata:{dateSent:new Date($.timestamp),edited:$.edited_timestamp!==null,editedAt:$.edited_timestamp?new Date($.edited_timestamp):void 0},attachments:($.attachments||[]).map((Z)=>({type:this.getAttachmentType(Z.content_type),url:Z.url,name:Z.filename,mimeType:Z.content_type,size:Z.size,width:Z.width??void 0,height:Z.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($){throw new Hj("discord","Failed to download Discord attachment",$ instanceof Error?$:void 0)}if(!w.ok)throw new Hj("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,$){let B=`${this.apiBaseUrl}${Q}`,X={Authorization:`Bot ${this.botToken}`};if($)X["Content-Type"]="application/json";let Y=await fetch(B,{method:w,headers:X,body:$?JSON.stringify($):void 0});if(!Y.ok){let Z=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:Z}),new Hj("discord",`Discord API error: ${Y.status} ${Z}`)}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:B?"configured":"not configured"});let X=this.runGatewayListener(w,$,B);return Q.waitUntil(X),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,$){let B=new HX.Client({intents:[HX.GatewayIntentBits.Guilds,HX.GatewayIntentBits.GuildMessages,HX.GatewayIntentBits.MessageContent,HX.GatewayIntentBits.DirectMessages,HX.GatewayIntentBits.GuildMessageReactions,HX.GatewayIntentBits.DirectMessageReactions],partials:[HX.Partials.Channel]}),X=!1;if($)B.on("raw",async(Y)=>{if(X)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent($,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers(B,()=>X);B.on(HX.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:B.user?.username,id:B.user?.id})}),B.on(HX.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await B.login(this.botToken),await new Promise((Y)=>{let Z=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(Z),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(Z),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{X=!0,B.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(HX.Events.MessageCreate,async($)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if($.author.bot){this.logger.debug("Ignoring message from bot",{authorId:$.author.id,authorName:$.author.username,isMe:$.author.id===Q.user?.id});return}let B=$.mentions.has(Q.user?.id??""),X=this.mentionRoleIds.length>0&&$.mentions.roles.some((Z)=>this.mentionRoleIds.includes(Z.id)),Y=B||X;this.logger.info("Discord Gateway message received",{channelId:$.channelId,guildId:$.guildId,authorId:$.author.id,isMentioned:Y,isUserMentioned:B,isRoleMentioned:X,content:$.content.slice(0,100)}),await this.handleGatewayMessage($,Y)}),Q.on(HX.Events.InteractionCreate,async($)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:$.id,type:$.type});try{await this.handleGatewayInteraction($)}catch(B){this.logger.error("Error handling Gateway interaction",{error:String(B),interactionId:$.id})}}),Q.on(HX.Events.MessageReactionAdd,async($,B)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if(B.bot){this.logger.debug("Ignoring reaction from bot",{userId:B.id,isMe:B.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:$.emoji.name,messageId:$.message.id,channelId:$.message.channelId,userId:B.id}),B.username)await this.handleGatewayReaction($,B,!0)}),Q.on(HX.Events.MessageReactionRemove,async($,B)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if(B.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:B.id,isMe:B.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:$.emoji.name,messageId:$.message.id,channelId:$.message.channelId,userId:B.id}),B.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 $=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if($.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let B=await $.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:$.status,error:B})}}catch($){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String($)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let $=Q.guildId||"@me",B=Q.channelId,X=Q.channel.isThread(),Y,Z=B;if(X&&"parentId"in Q.channel&&Q.channel.parentId)Y=B,Z=Q.channel.parentId;if(!Y&&w)try{let U=await this.createDiscordThread(B,Q.id);Y=U.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:B,messageId:Q.id,threadId:U.id})}catch(U){this.logger.error("Failed to create Discord thread for mention",{error:String(U),messageId:Q.id})}let W=this.encodeThreadId({guildId:$,channelId:Z,threadId:Y}),K=new P9({id:Q.id,threadId:W,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((U)=>({type:this.getAttachmentType(U.contentType),url:U.url,name:U.name,mimeType:U.contentType??void 0,size:U.size})),raw:{id:Q.id,channel_id:B,guild_id:$,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,W,K)}catch(U){this.logger.error("Error handling Gateway message",{error:String(U),messageId:Q.id})}}async handleGatewayReaction(Q,w,$){if(!this.chat)return;let B=Q.message.guildId||"@me",X=Q.message.channelId,Y=Q.message.channel?.isThread?.(),Z=X,W;if(Y&&Q.message.channel?.parentId)W=X,Z=Q.message.channel.parentId;let K=this.encodeThreadId({guildId:B,channelId:Z,threadId:W}),U=Q.emoji.name||"unknown",G=this.normalizeDiscordEmoji(U),D={adapter:this,threadId:K,messageId:Q.message.id,emoji:G,rawEmoji:Q.emoji.id?`<:${U}:${Q.emoji.id}>`:U,added:$,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(D)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let B=Q.split(":")[2];if(!B)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);let X=w.limit||50,Y=w.direction??"backward",Z=new URLSearchParams;if(Z.set("limit",String(X)),w.cursor)if(Y==="backward")Z.set("before",w.cursor);else Z.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:B,limit:X,direction:Y,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${B}/messages?${Z.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:K.length});let G=[...K].reverse().map((z)=>this.parseDiscordMessage(z,Q)),D;if(K.length===X)if(Y==="backward")D=K.at(-1)?.id;else D=K[0]?.id;return{messages:G,nextCursor:D}}async listThreads(Q,w={}){let $=Q.split(":"),B=$[1],X=$[2];if(!(B&&X))throw new m3("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:B,channelId:X});let W=((await(await this.discordFetch(`/guilds/${B}/threads/active`,"GET")).json()).threads||[]).filter((F)=>F.parent_id===X),K=[];try{K=(await(await this.discordFetch(`/channels/${X}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let U=[...W,...K],G=new Set,D=U.filter((F)=>{if(G.has(F.id))return!1;return G.add(F.id),!0}),z=w.limit||50,V=D.slice(0,z),I=[];for(let F of V){let _=this.encodeThreadId({guildId:B,channelId:X,threadId:F.id});try{let f=(await(await this.discordFetch(`/channels/${F.id}/messages?limit=1&after=0`,"GET")).json())[0];if(f)I.push({id:_,rootMessage:this.parseDiscordMessage(f,_),replyCount:F.total_message_sent??F.message_count,lastReplyAt:F.thread_metadata?.archive_timestamp?new Date(F.thread_metadata.archive_timestamp):void 0})}catch{I.push({id:_,rootMessage:new P9({id:F.id,threadId:_,text:F.name,formatted:this.formatConverter.toAst(F.name),raw:F,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:F.total_message_sent??F.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:I.length}),{threads:I,nextCursor:D.length>z?String(z):void 0}}async fetchChannelInfo(Q){let $=Q.split(":")[2];if(!$)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:$});let X=await(await this.discordFetch(`/channels/${$}`,"GET")).json();return{id:Q,name:X.name,isDM:X.type===TC.DM||X.type===TC.GroupDM,memberCount:X.member_count,metadata:{channelType:X.type,raw:X}}}async postChannelMessage(Q,w){let B=Q.split(":")[2];if(!B)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);let X={},Y=[],Z=[],W=DV0(w);if(W){let z=kBA(W);Y.push(...z.embeds),Z.push(...z.components)}else X.content=this.truncateContent(hC(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)X.embeds=Y;if(Z.length>0)X.components=Z;let K=wBA(w),U=this.tryPostSlashResponse(Q,X,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,Q,X,K);this.logger.debug("Discord API: POST channel message",{channelId:B,contentLength:X.content?.length||0});let D=await(await this.discordFetch(`/channels/${B}/messages`,"POST",X)).json();return{id:D.id,threadId:Q,raw:D}}normalizeDiscordEmoji(Q){let $={"\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 Zj($)}};function _42(A){return new bhw(A??{})}var khw=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 $={threadId:A,token:Phw(),expiresAt:Date.now()+Q};return this.locks.set(A,$),$}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 $=this.cache.get(A);if($)if($.expiresAt!==null&&$.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 $=this.cache.get(A),B;if($&&$.expiresAt!==null&&$.expiresAt<=Date.now())B=[];else if($&&Array.isArray($.value))B=$.value;else B=[];if(B.push(Q),w?.maxLength&&B.length>w.maxLength)B=B.slice(B.length-w.maxLength);this.cache.set(A,{value:B,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let $=this.queues.get(A);if(!$)$=[],this.queues.set(A,$);if($.push(Q),$.length>w)$.splice(0,$.length-w);return $.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 Phw(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function zV0(A){return new khw}b0();var Mhw=H.object({subscribedAt:H.string().datetime(),routingMode:H.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:H.boolean().optional()}),jhw="chat.discord.subscriptions";function PBA(A){return A.scoped({namespace:jhw,schema:Mhw})}function b42(A,Q=zV0()){let w=PBA(A);return new k42(Q,w)}class k42{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 P42(A){let{discord:Q}=A;if(!Q)return new e5A({userName:A.userName,adapters:{},state:zV0()});let w=_42({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new e5A({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:b42(A.runtimeState)})}class MBA{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 B={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,B);else await this.deps.getSubscriptions()?.set(A.id,B);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(($)=>!$.isBot&&!$.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}$A();class jBA{deps;constructor(A){this.deps=A}async build(A,Q,w,$){let B={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return B;if(!($==="anchor"||$==="trusted"))return B;let Y=this.deps.getUploadStore();if(!Y)return B;for(let Z of w.attachments){let W=Z.name;if(!W)continue;let K=uL(W,"upload"),U=YP(K,Z.mimeType),G=Z.size??0,D=VW0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!FW0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let z=await this.readAttachmentData(Z);if(!z)continue;let V=cL({filename:K,mediaType:U,content:z,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let I=await Y.save({filename:V.filename,mediaType:V.mediaType,content:z,metadata:this.buildMetadata(A,Q,w)});B.attachments.push(j42(I.filename,I.mediaType,z,I.ref,V.kind==="text"))}catch(z){this.deps.logger.error("Failed to read chat attachment",{error:z,filename:K}),B.notices.push(`Could not read file upload: ${K}`)}}return B}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let $=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,...$.guildId?{guildId:$.guildId}:{},...$.threadId?{threadId:$.threadId}:{}}}}function M42(A,Q,w,$){return j42(A,Q,w,$,ZP(A,Q))}function j42(A,Q,w,$,B){if(B)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:$};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:$}}function uQ0(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function lV(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 Ohw(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 O42(A,Q){if(A.isDM)return!1;let w=lV(A.id);if(!w.threadId)return!1;let $=Ohw(Q);return $!==void 0&&$!==w.threadId}function JV0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=lV(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some(($)=>typeof $==="string"&&Q.allowedChannels.includes($))}function OBA(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 JV0(A,w)}function fBA(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return JV0(A,w)}function xBA(A,Q){return{channelId:lV(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function sp(A){return A.isDM?"DM":A.channelId}var fhw="https://discord.com/api/v10";async function f42(A){let Q=lV(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let $=A.fetchFn??fetch;try{let B=await $(`${fhw}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!B.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:B.status})}catch(B){A.logger.debug("Failed to clear Discord message components",{error:B,messageId:A.messageId,channelId:w})}}var x42={name:"@brains/chat",version:"0.2.0-alpha.180",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 Rhw=/https?:\/\/\S+/i,vhw=/[\s\S]+/,Chw=1000,hhw=H.looseObject({type:H.literal("card"),children:H.array(H.looseObject({type:H.string()})),imageUrl:H.string().optional(),subtitle:H.string().optional(),title:H.string().optional()}),Ehw=H.object({card:H.custom((A)=>hhw.safeParse(A).success),fallbackText:H.string().optional()});class VV0 extends wq{threadRegistry=new AV0;pendingApprovals;uploadContinuity;promptActions=new f8A(Chw);toolStatusMessenger=new x8A(this.threadRegistry);cardBuilder=new h8A({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new g8A({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new y8A({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await f42({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new MBA({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:O42,logger:this.logger});chatInputBuilder=new jBA({getUploadStore:()=>this.context?.uploads.scoped(uQ0()),getThreadIdParts:lV,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",x42,A,O8A);this.gatewayLoop=new T8A({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new S8A({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(uQ0()),buildApp:(Q)=>P42({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Nt({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 jt({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(uQ0());if(!w)throw Error("Chat upload store unavailable");let $=await w.read(Q);return M42($.record.filename,$.record.mediaType,$.content,$.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=PBA(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 $=this.toDiscordCardOutput(Q);if($){w.post($).catch((B)=>this.logger.error("Failed to send chat message",{error:B,channelId:A}));return}if(typeof Q!=="string")return;for(let B of fQ0(A,Q))w.post(B).catch((X)=>this.logger.error("Failed to send chat message",{error:X,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let $=this.toDiscordCardOutput(Q);if($){let X=await w.post($);return this.threadRegistry.trackMessage(w.id,X),X.id}if(typeof Q!=="string")return;let B;for(let X of fQ0(A,Q))B=await w.post(X),this.threadRegistry.trackMessage(w.id,B);return B?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let $=this.threadRegistry.getMessage(A,Q);if(!$)return!1;try{let B=await $.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,B);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=Ehw.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:$}=Q.data;if($===void 0)return{card:w};return{card:w,fallbackText:$}}formatProgressOutput(A){return C8A(A)}formatCompletionOutput(A){return C8A(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let $={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent($,$.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 w12(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,$,B)=>{await this.handleRoutedMessage(Q,w,B)}),A.onNewMention(async(Q,w,$)=>{let B=this.getPlatformConfig(Q);if(B&&OBA(Q,w,B)&&!Q.isDM&&B.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,$)}),A.onSubscribedMessage(async(Q,w,$)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,$)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(vhw,async(Q,w,$)=>{await this.handleRoutedMessage(Q,w,$)});A.onNewMessage(Rhw,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([QV0,R8A],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(v8A,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(!fBA(w,Q,this.config.adapters.discord))return;let $=this.promptActions.get(A.value);if($?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let B=lV(w.id),X=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:B.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),Z=w.id;await this.runAgentTurn({thread:w,channelId:Z,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let W=await this.context.agent.chat($.prompt,Y,{userPermissionLevel:X,interfaceType:Q,channelId:Z,channelName:sp(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Z,conversationId:Y,response:W,userPermissionLevel:X})}})}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 B=A.thread;if(!fBA(B,Q,this.config.adapters.discord))return;let X=lV(B.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:X.channelId??B.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:B,conversationId:w,approvalId:A.value,confirmed:A.actionId===QV0,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,B,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let $=this.getPlatform(A);if($!=="discord")return;let B=this.getPlatformConfig(A);if(!B)return;if(!OBA(A,Q,B))return;await this.routeToAgent($,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 $=this.formatErrorPayload(w),B=this.toDiscordCardOutput($);if(B){await A.post(B);return}let X=typeof $==="string"?$:"Message failed.";for(let Y of fQ0(Q,X))await A.post(Y)}async routeToAgent(A,Q,w,$){if(!this.context)return;this.threadRegistry.set(Q);let B=this.getConversationId(A,Q.id),X=Q.id,Y=xBA(Q,w),Z=this.context.permissions.getUserLevel(A,w.author.userId,Y),W=await this.chatInputBuilder.build(A,Q,w,Z),K=[...W.attachments];if(await this.attachPriorUploads(B,W,Z),await this.postUploadNotices(Q,W.notices),!W.message&&W.attachments.length===0)return;this.rememberUploadAttachments(B,K),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let U=await this.getPendingApprovalIds(B);if(U.size>0){if(await this.handleConfirmationResponse(W.message,B,Q,U,Z,this.buildUserMessageMetadata(A,Q,w)))return}let G=this.buildCoalescedAgentInput(W.message,$),D=await this.context.agent.chat(G.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:sp(Q),...this.buildUserMessageMetadata(A,Q,w,G.metadata),...W.attachments.length>0?{attachments:W.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:D,userPermissionLevel:Z})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),w=KR(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let $=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),B=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:$,files:Q.files}),X=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((W)=>W.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let Z=X??B;if(Z)for(let W of w.jobIds)this.trackAgentResponseForJob(W,Z,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,$,B,X){if(!Vt(A,$))return!1;let Y=BW0({message:A,approvalIds:$});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:B,...X?{metadata:X}:{}}),!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:sp(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(`
|
|
2399
|
+
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var F42={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},qV0="https://discord.com/api/v10",I42=2000,Nhw=/^[0-9a-f]{64}$/,_hw=/^[0-9a-f]+$/,bhw=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new Lhw;requestContext=new Khw;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new m3("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let $=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!$)throw new m3("discord","publicKey is required. Set DISCORD_PUBLIC_KEY or provide it in config.");let B=Q.applicationId??process.env.DISCORD_APPLICATION_ID;if(!B)throw new m3("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??qV0,this.botToken=w,this.publicKey=$.trim().toLowerCase(),this.applicationId=B,this.mentionRoleIds=Q.mentionRoleIds??(process.env.DISCORD_MENTION_ROLE_IDS?process.env.DISCORD_MENTION_ROLE_IDS.split(",").map((X)=>X.trim()):[]),this.botUserId=B,this.interactionFlags=Q.interactionFlags,this.logger=Q.logger??new KV0("info").child("discord"),this.userName=Q.userName??"bot",!Nhw.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:_hw.test(this.publicKey)})}async initialize(Q){this.chat=Q,this.logger.info("Discord adapter initialized")}async getUser(Q){try{let $=await(await this.discordFetch(`/users/${Q}`,"GET")).json();return{avatarUrl:$.avatar?`https://cdn.discordapp.com/avatars/${$.id}/${$.avatar}.png`:void 0,email:void 0,fullName:$.global_name||$.username,isBot:$.bot??!1,userId:$.id,userName:$.username}}catch{return null}}async handleWebhook(Q,w){let $=await Q.arrayBuffer(),B=new Uint8Array($),X=new TextDecoder().decode(B),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 G=JSON.parse(X);return this.handleForwardedGatewayEvent(G,w)}catch{return new Response("Invalid JSON",{status:400})}}this.logger.info("Discord webhook received",{bodyLength:X.length,bodyBytesLength:B.length,hasSignature:!!Q.headers.get("x-signature-ed25519"),hasTimestamp:!!Q.headers.get("x-signature-timestamp")});let Z=Q.headers.get("x-signature-ed25519"),W=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature(B,Z,W))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let U;try{U=JSON.parse(X)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:U.type,typeIsPing:U.type===rp.Ping,expectedPingType:rp.Ping,id:U.id}),U.type===rp.Ping){let G=JSON.stringify({type:mQ0.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:G,responseType:mQ0.InteractionResponseType.PONG}),new Response(G,{status:200,headers:{"Content-Type":"application/json"}})}if(U.type===rp.MessageComponent)return this.handleComponentInteraction(U,w),this.respondToInteraction({type:F42.DeferredUpdateMessage});if(U.type===rp.ApplicationCommand){let G=this.getApplicationCommandContext(U),D=this.getInteractionFlags(G);return this.handleApplicationCommandInteraction(G,w),this.respondToInteraction({...D===void 0?{}:{data:{flags:D}},type:F42.DeferredChannelMessageWithSource})}return new Response("Unknown interaction type",{status:400})}async verifySignature(Q,w,$){if(!(w&&$))return this.logger.warn("Discord signature verification failed: missing headers",{hasSignature:!!w,hasTimestamp:!!$}),!1;try{this.logger.info("Discord signature verification attempt",{bodyBytesLength:Q.length,signatureLength:w.length,timestampLength:$.length,publicKeyLength:this.publicKey.length,timestamp:$,signaturePrefix:w.slice(0,16),publicKey:this.publicKey});let B=await mQ0.verifyKey(Q,w,$,this.publicKey);if(!B){let X=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:$,bodyLength:Q.length,bodyPrefix:X.slice(0,50)})}return B}catch(B){return this.logger.warn("Discord signature verification failed: exception",{error:B}),!1}}respondToInteraction(Q){return Response.json(Q)}handleComponentInteraction(Q,w){if(!this.chat){this.logger.warn("Chat instance not initialized, ignoring interaction");return}let $=Q.data?.custom_id;if(!$){this.logger.warn("No custom_id in component interaction");return}let B=Q.member?.user||Q.user;if(!B){this.logger.warn("No user in component interaction");return}let X=Q.channel_id,Y=Q.guild_id||"@me",Z=Q.message?.id;if(!(X&&Z)){this.logger.warn("Missing channel_id or message_id in interaction");return}let W=Q.channel,K=W?.type===11||W?.type===12,U=K&&W?.parent_id?W.parent_id:X,G=K?this.encodeThreadId({guildId:Y,channelId:U,threadId:X}):this.encodeThreadId({guildId:Y,channelId:X}),D=Ghw($),z={actionId:D.actionId,value:D.value??D.actionId,user:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:B.bot??!1,isMe:!1},messageId:Z,threadId:G,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:$,messageId:Z,threadId:G}),this.chat.processAction(z,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let $=Q.member?.user||Q.user;if(!$)return this.logger.warn("No user in application command interaction"),null;let B=Q.channel_id;if(!B)return this.logger.warn("Missing channel_id in application command interaction"),null;let X=Q.guild_id||"@me",Y=Q.channel,Z=Y?.type===11||Y?.type===12,W=Z&&Y?.parent_id?Y.parent_id:B,K=Z?this.encodeThreadId({guildId:X,channelId:W,threadId:B}):this.encodeThreadId({guildId:X,channelId:B}),{command:U,text:G}=this.parseSlashCommand(w,Q.data?.options);return{channelId:K,command:U,interaction:Q,text:G,user:$}}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:$,command:B,interaction:X,text:Y,user:Z}=Q;this.logger.debug("Processing Discord slash command",{command:B,text:Y,userId:Z.id,channelId:$}),this.requestContext.run({slashCommand:{channelId:$,interactionToken:X.token,initialResponseSent:!1}},()=>{this.chat?.processSlashCommand({command:B,text:Y,user:{userId:Z.id,userName:Z.username,fullName:Z.global_name||Z.username,isBot:Z.bot??!1,isMe:Z.id===this.applicationId},adapter:this,raw:X,channelId:$},w)})}parseSlashCommand(Q,w){let $=[Q.startsWith("/")?Q:`/${Q}`],B=[],X=(Y)=>{for(let Z of Y){if(Z.value!==void 0){B.push(String(Z.value));continue}if(Z.options&&Z.options.length>0)$.push(Z.name),X(Z.options)}};if(w&&w.length>0)X(w);return{command:$.join(" "),text:B.join(" ").trim()}}async handleGatewayInteraction(Q){if(Q.isChatInputCommand()){let w=this.getApplicationCommandContext(this.normalizeGatewaySlashCommandInteraction(Q)),$=this.getInteractionFlags(w);await Q.deferReply($===void 0?void 0:{flags:$}),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 $=Q.guild_id||"@me",B=Q.channel_id,X,Y=B;if(Q.thread)X=Q.thread.id,Y=Q.thread.parent_id;else if(Q.channel_type===11||Q.channel_type===12)try{let z=await(await this.discordFetch(`/channels/${B}`,"GET")).json();if(z.parent_id)X=B,Y=z.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:B,parentId:z.parent_id})}catch(D){this.logger.error("Failed to fetch thread parent",{error:String(D),channelId:B})}let Z=Q.is_mention||Q.mentions.some((D)=>D.id===this.applicationId),W=this.mentionRoleIds.length>0&&Q.mention_roles?.some((D)=>this.mentionRoleIds.includes(D)),K=Z||W;if(!X&&K)try{let D=await this.createDiscordThread(B,Q.id);X=D.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:B,messageId:Q.id,threadId:D.id})}catch(D){this.logger.error("Failed to create Discord thread for mention",{error:String(D),messageId:Q.id})}let U=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),G=new P9({id:Q.id,threadId:U,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((D)=>({type:this.getAttachmentType(D.content_type),url:D.url,name:D.filename,mimeType:D.content_type,size:D.size})),raw:Q,isMention:K});try{await this.chat.handleIncomingMessage(this,U,G)}catch(D){this.logger.error("Error handling forwarded message",{error:String(D),messageId:Q.id})}}async handleForwardedReaction(Q,w,$){if(!this.chat)return;let B=Q.guild_id||"@me",X=Q.channel_id,Y,Z=X;if(Q.channel_type===TC.GuildPublicThread||Q.channel_type===TC.GuildPrivateThread){let z=this.threadParentCache.get(X);if(z&&z.expiresAt>Date.now())Y=X,Z=z.parentId;else try{let I=await(await this.discordFetch(`/channels/${X}`,"GET")).json();if(I.parent_id)Y=X,Z=I.parent_id,this.threadParentCache.set(X,{parentId:I.parent_id,expiresAt:Date.now()+A.THREAD_PARENT_CACHE_TTL})}catch(V){this.logger.error("Failed to fetch thread parent for reaction",{error:String(V),channelId:X})}}let W=this.encodeThreadId({guildId:B,channelId:Z,threadId:Y}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G=Q.user??Q.member?.user;if(!G){this.logger.warn("Reaction event missing user info",{data:Q});return}let D={adapter:this,threadId:W,messageId:Q.message_id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:w,user:{userId:G.id,userName:G.username,fullName:G.username,isBot:G.bot===!0,isMe:G.id===this.applicationId},raw:Q};this.chat.processReaction(D)}async postMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=Q;if(B)$=B;let Y={},Z=[],W=[],K=DV0(w);if(K){let V=kBA(K);Z.push(...V.embeds),W.push(...V.components)}else Y.content=this.truncateContent(hC(this.formatConverter.renderPostable(w),"discord"));if(Z.length>0)Y.embeds=Z;if(W.length>0)Y.components=W;let U=wBA(w),G=this.tryPostSlashResponse(X,Y,U);if(G)return G;if(U.length>0)return this.postMessageWithFiles($,X,Y,U);this.logger.debug("Discord API: POST message",{channelId:$,contentLength:Y.content?.length||0,embedCount:Z.length,componentCount:W.length});let z=await(await this.discordFetch(`/channels/${$}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:z.id}),{id:z.id,threadId:X,raw:z}}tryPostSlashResponse(Q,w,$){let B=this.requestContext.getStore()?.slashCommand;if(!B||B.channelId!==Q)return;return this.postSlashCommandResponse(B,Q,w,$)}async postSlashCommandResponse(Q,w,$,B){let X=!Q.initialResponseSent;Q.initialResponseSent=!0;let Y=X?`/webhooks/${this.applicationId}/${Q.interactionToken}/messages/@original`:`/webhooks/${this.applicationId}/${Q.interactionToken}?wait=true`,Z=X?"PATCH":"POST";this.logger.debug("Discord interaction webhook: responding to slash command",{threadId:w,isInitialResponse:X,hasFiles:B.length>0});let K=await(B.length>0?await this.discordInteractionFetchWithFiles(Y,Z,$,B):await this.discordInteractionFetch(Y,Z,$)).json();return{id:K.id,threadId:w,raw:K}}async createDiscordThread(Q,w){let $=`Thread ${new Date().toLocaleString()}`;this.logger.debug("Discord API: POST thread",{channelId:Q,messageId:w,threadName:$});try{let X=await(await this.discordFetch(`/channels/${Q}/messages/${w}/threads`,"POST",{name:$,auto_archive_duration:1440})).json();return this.logger.debug("Discord API: POST thread response",{threadId:X.id,threadName:X.name}),X}catch(B){if(B instanceof Hj&&typeof B.message==="string"&&B.message.includes('"code"')&&B.message.includes("160004"))return this.logger.debug("Thread already exists for message, reusing existing thread",{channelId:Q,messageId:w}),{id:w,name:$};throw B}}truncateContent(Q){if(Q.length<=I42)return Q;return`${Q.slice(0,I42-3)}...`}async postMessageWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let W=0;W<B.length;W++){let K=B[W];if(!K)continue;let U=await $BA(K.data,{platform:"discord"});if(!U)continue;let G=new Blob([new Uint8Array(U)],{type:K.mimeType||"application/octet-stream"});X.append(`files[${W}]`,G,K.filename)}let Y=await fetch(`${qV0}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:X});if(!Y.ok){let W=await Y.text();throw new Hj("discord",`Failed to post message: ${Y.status} ${W}`)}let Z=await Y.json();return{id:Z.id,threadId:w,raw:Z}}async discordInteractionFetch(Q,w,$){let B=await fetch(`${qV0}${Q}`,{method:w,headers:$?{"Content-Type":"application/json"}:void 0,body:$?JSON.stringify($):void 0});if(!B.ok){let X=await B.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:B.status,error:X}),new Hj("discord",`Discord interaction API error: ${B.status} ${X}`)}return B}async discordInteractionFetchWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let Z=0;Z<B.length;Z++){let W=B[Z];if(!W)continue;let K=await $BA(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});X.append(`files[${Z}]`,U,W.filename)}let Y=await fetch(`${qV0}${Q}`,{method:w,body:X});if(!Y.ok){let Z=await Y.text();throw this.logger.error("Discord interaction API error",{path:Q,method:w,status:Y.status,error:Z}),new Hj("discord",`Discord interaction API error: ${Y.status} ${Z}`)}return Y}async editMessage(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z={},W=[],K=[],U=DV0($);if(U){let z=kBA(U);W.push(...z.embeds),K.push(...z.components),Z.content=""}else Z.content=this.truncateContent(hC(this.formatConverter.renderPostable($),"discord"));if(W.length>0)Z.embeds=W;if(K.length>0)Z.components=K;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:Z.content?.length||0});let D=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",Z)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:D.id}),{id:D.id,threadId:Q,raw:D}}async deleteMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$;this.logger.debug("Discord API: DELETE message",{channelId:X,messageId:w}),await this.discordFetch(`/channels/${X}/messages/${w}`,"DELETE"),this.logger.debug("Discord API: DELETE message response",{ok:!0})}async addReaction(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z=this.encodeEmoji($);this.logger.debug("Discord API: PUT reaction",{channelId:Y,messageId:w,emoji:Z}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${Z}/@me`,"PUT"),this.logger.debug("Discord API: PUT reaction response",{ok:!0})}async removeReaction(Q,w,$){let{channelId:B,threadId:X}=this.decodeThreadId(Q),Y=X||B,Z=this.encodeEmoji($);this.logger.debug("Discord API: DELETE reaction",{channelId:Y,messageId:w,emoji:Z}),await this.discordFetch(`/channels/${Y}/messages/${w}/reactions/${Z}/@me`,"DELETE"),this.logger.debug("Discord API: DELETE reaction response",{ok:!0})}encodeEmoji(Q){let w=EQ0.toDiscord?EQ0.toDiscord(Q):String(Q);return encodeURIComponent(w)}async startTyping(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$;this.logger.debug("Discord API: POST typing",{channelId:X}),await this.discordFetch(`/channels/${X}/typing`,"POST")}async fetchMessages(Q,w={}){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=B||$,Y=w.limit||50,Z=w.direction??"backward",W=new URLSearchParams;if(W.set("limit",String(Y)),w.cursor)if(Z==="backward")W.set("before",w.cursor);else W.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:X,limit:Y,direction:Z,cursor:w.cursor});let U=await(await this.discordFetch(`/channels/${X}/messages?${W.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:U.length});let D=[...U].reverse().map((V)=>this.parseDiscordMessage(V,Q)),z;if(U.length===Y)if(Z==="backward")z=U.at(-1)?.id;else z=U[0]?.id;return{messages:D,nextCursor:z}}async fetchThread(Q){let{channelId:w,guildId:$}=this.decodeThreadId(Q);this.logger.debug("Discord API: GET channel",{channelId:w});let X=await(await this.discordFetch(`/channels/${w}`,"GET")).json();return{id:Q,channelId:w,channelName:X.name,isDM:X.type===TC.DM||X.type===TC.GroupDM,metadata:{guildId:$,channelType:X.type,raw:X}}}async openDM(Q){this.logger.debug("Discord API: POST DM channel",{userId:Q});let $=await(await this.discordFetch("/users/@me/channels","POST",{recipient_id:Q})).json();return this.logger.debug("Discord API: POST DM channel response",{channelId:$.id}),this.encodeThreadId({guildId:"@me",channelId:$.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 m3("discord",`Invalid Discord thread ID: ${Q}`);return{guildId:w[1],channelId:w[2],threadId:w[3]}}parseMessage(Q){let w=Q,$=w.guild_id||"@me",B=this.encodeThreadId({guildId:$,channelId:w.channel_id});return this.parseDiscordMessage(w,B)}parseDiscordMessage(Q,w){let $=Q.type===J82.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,B=$.author,X=B.bot??!1,Y=B.id===this.botUserId;return new P9({id:$.id,threadId:w,text:this.formatConverter.extractPlainText($.content),formatted:this.formatConverter.toAst($.content),raw:Q,author:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:X,isMe:Y},metadata:{dateSent:new Date($.timestamp),edited:$.edited_timestamp!==null,editedAt:$.edited_timestamp?new Date($.edited_timestamp):void 0},attachments:($.attachments||[]).map((Z)=>({type:this.getAttachmentType(Z.content_type),url:Z.url,name:Z.filename,mimeType:Z.content_type,size:Z.size,width:Z.width??void 0,height:Z.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($){throw new Hj("discord","Failed to download Discord attachment",$ instanceof Error?$:void 0)}if(!w.ok)throw new Hj("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,$){let B=`${this.apiBaseUrl}${Q}`,X={Authorization:`Bot ${this.botToken}`};if($)X["Content-Type"]="application/json";let Y=await fetch(B,{method:w,headers:X,body:$?JSON.stringify($):void 0});if(!Y.ok){let Z=await Y.text();throw this.logger.error("Discord API error",{path:Q,method:w,status:Y.status,error:Z}),new Hj("discord",`Discord API error: ${Y.status} ${Z}`)}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:B?"configured":"not configured"});let X=this.runGatewayListener(w,$,B);return Q.waitUntil(X),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,$){let B=new HX.Client({intents:[HX.GatewayIntentBits.Guilds,HX.GatewayIntentBits.GuildMessages,HX.GatewayIntentBits.MessageContent,HX.GatewayIntentBits.DirectMessages,HX.GatewayIntentBits.GuildMessageReactions,HX.GatewayIntentBits.DirectMessageReactions],partials:[HX.Partials.Channel]}),X=!1;if($)B.on("raw",async(Y)=>{if(X)return;if(!Y.t)return;this.logger.info("Discord Gateway forwarding event",{type:Y.t}),await this.forwardGatewayEvent($,{type:`GATEWAY_${Y.t}`,timestamp:Date.now(),data:Y.d})});else this.setupLegacyGatewayHandlers(B,()=>X);B.on(HX.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:B.user?.username,id:B.user?.id})}),B.on(HX.Events.Error,(Y)=>{this.logger.error("Discord Gateway error",{error:String(Y)})});try{await B.login(this.botToken),await new Promise((Y)=>{let Z=setTimeout(Y,Q);if(w){if(w.aborted){clearTimeout(Z),Y();return}w.addEventListener("abort",()=>{this.logger.info("Discord Gateway listener received abort signal (new listener started)"),clearTimeout(Z),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{X=!0,B.destroy(),this.logger.info("Discord Gateway listener stopped")}}setupLegacyGatewayHandlers(Q,w){Q.on(HX.Events.MessageCreate,async($)=>{if(w()){this.logger.debug("Ignoring message - Gateway is shutting down");return}if($.author.bot){this.logger.debug("Ignoring message from bot",{authorId:$.author.id,authorName:$.author.username,isMe:$.author.id===Q.user?.id});return}let B=$.mentions.has(Q.user?.id??""),X=this.mentionRoleIds.length>0&&$.mentions.roles.some((Z)=>this.mentionRoleIds.includes(Z.id)),Y=B||X;this.logger.info("Discord Gateway message received",{channelId:$.channelId,guildId:$.guildId,authorId:$.author.id,isMentioned:Y,isUserMentioned:B,isRoleMentioned:X,content:$.content.slice(0,100)}),await this.handleGatewayMessage($,Y)}),Q.on(HX.Events.InteractionCreate,async($)=>{if(w()){this.logger.debug("Ignoring interaction - Gateway is shutting down");return}this.logger.info("Discord Gateway interaction received",{id:$.id,type:$.type});try{await this.handleGatewayInteraction($)}catch(B){this.logger.error("Error handling Gateway interaction",{error:String(B),interactionId:$.id})}}),Q.on(HX.Events.MessageReactionAdd,async($,B)=>{if(w()){this.logger.debug("Ignoring reaction - Gateway is shutting down");return}if(B.bot){this.logger.debug("Ignoring reaction from bot",{userId:B.id,isMe:B.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction added",{emoji:$.emoji.name,messageId:$.message.id,channelId:$.message.channelId,userId:B.id}),B.username)await this.handleGatewayReaction($,B,!0)}),Q.on(HX.Events.MessageReactionRemove,async($,B)=>{if(w()){this.logger.debug("Ignoring reaction removal - Gateway is shutting down");return}if(B.bot){this.logger.debug("Ignoring reaction removal from bot",{userId:B.id,isMe:B.id===Q.user?.id});return}if(this.logger.info("Discord Gateway reaction removed",{emoji:$.emoji.name,messageId:$.message.id,channelId:$.message.channelId,userId:B.id}),B.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 $=await fetch(Q,{method:"POST",headers:{"Content-Type":"application/json","x-discord-gateway-token":this.botToken},body:JSON.stringify(w)});if($.ok)this.logger.debug("Gateway event forwarded successfully",{type:w.type});else{let B=await $.text();this.logger.error("Failed to forward Gateway event",{type:w.type,status:$.status,error:B})}}catch($){this.logger.error("Error forwarding Gateway event",{type:w.type,error:String($)})}}async handleGatewayMessage(Q,w){if(!this.chat)return;let $=Q.guildId||"@me",B=Q.channelId,X=Q.channel.isThread(),Y,Z=B;if(X&&"parentId"in Q.channel&&Q.channel.parentId)Y=B,Z=Q.channel.parentId;if(!Y&&w)try{let U=await this.createDiscordThread(B,Q.id);Y=U.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:B,messageId:Q.id,threadId:U.id})}catch(U){this.logger.error("Failed to create Discord thread for mention",{error:String(U),messageId:Q.id})}let W=this.encodeThreadId({guildId:$,channelId:Z,threadId:Y}),K=new P9({id:Q.id,threadId:W,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((U)=>({type:this.getAttachmentType(U.contentType),url:U.url,name:U.name,mimeType:U.contentType??void 0,size:U.size})),raw:{id:Q.id,channel_id:B,guild_id:$,content:Q.content,author:{id:Q.author.id,username:Q.author.username},timestamp:Q.createdAt.toISOString()},isMention:w});try{await this.chat.handleIncomingMessage(this,W,K)}catch(U){this.logger.error("Error handling Gateway message",{error:String(U),messageId:Q.id})}}async handleGatewayReaction(Q,w,$){if(!this.chat)return;let B=Q.message.guildId||"@me",X=Q.message.channelId,Y=Q.message.channel?.isThread?.(),Z=X,W;if(Y&&Q.message.channel?.parentId)W=X,Z=Q.message.channel.parentId;let K=this.encodeThreadId({guildId:B,channelId:Z,threadId:W}),U=Q.emoji.name||"unknown",G=this.normalizeDiscordEmoji(U),D={adapter:this,threadId:K,messageId:Q.message.id,emoji:G,rawEmoji:Q.emoji.id?`<:${U}:${Q.emoji.id}>`:U,added:$,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(D)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let B=Q.split(":")[2];if(!B)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);let X=w.limit||50,Y=w.direction??"backward",Z=new URLSearchParams;if(Z.set("limit",String(X)),w.cursor)if(Y==="backward")Z.set("before",w.cursor);else Z.set("after",w.cursor);this.logger.debug("Discord API: GET channel messages",{channelId:B,limit:X,direction:Y,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${B}/messages?${Z.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:K.length});let G=[...K].reverse().map((z)=>this.parseDiscordMessage(z,Q)),D;if(K.length===X)if(Y==="backward")D=K.at(-1)?.id;else D=K[0]?.id;return{messages:G,nextCursor:D}}async listThreads(Q,w={}){let $=Q.split(":"),B=$[1],X=$[2];if(!(B&&X))throw new m3("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:B,channelId:X});let W=((await(await this.discordFetch(`/guilds/${B}/threads/active`,"GET")).json()).threads||[]).filter((F)=>F.parent_id===X),K=[];try{K=(await(await this.discordFetch(`/channels/${X}/threads/archived/public?limit=${w.limit||50}`,"GET")).json()).threads||[]}catch{this.logger.debug("Could not fetch archived threads (may lack permissions)")}let U=[...W,...K],G=new Set,D=U.filter((F)=>{if(G.has(F.id))return!1;return G.add(F.id),!0}),z=w.limit||50,V=D.slice(0,z),I=[];for(let F of V){let _=this.encodeThreadId({guildId:B,channelId:X,threadId:F.id});try{let f=(await(await this.discordFetch(`/channels/${F.id}/messages?limit=1&after=0`,"GET")).json())[0];if(f)I.push({id:_,rootMessage:this.parseDiscordMessage(f,_),replyCount:F.total_message_sent??F.message_count,lastReplyAt:F.thread_metadata?.archive_timestamp?new Date(F.thread_metadata.archive_timestamp):void 0})}catch{I.push({id:_,rootMessage:new P9({id:F.id,threadId:_,text:F.name,formatted:this.formatConverter.toAst(F.name),raw:F,author:{userId:"unknown",userName:"unknown",fullName:"unknown",isBot:!1,isMe:!1},metadata:{dateSent:new Date,edited:!1},attachments:[]}),replyCount:F.total_message_sent??F.message_count})}}return this.logger.debug("Discord API: listThreads result",{threadCount:I.length}),{threads:I,nextCursor:D.length>z?String(z):void 0}}async fetchChannelInfo(Q){let $=Q.split(":")[2];if(!$)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET channel info",{channelId:$});let X=await(await this.discordFetch(`/channels/${$}`,"GET")).json();return{id:Q,name:X.name,isDM:X.type===TC.DM||X.type===TC.GroupDM,memberCount:X.member_count,metadata:{channelType:X.type,raw:X}}}async postChannelMessage(Q,w){let B=Q.split(":")[2];if(!B)throw new m3("discord",`Invalid Discord channel ID: ${Q}`);let X={},Y=[],Z=[],W=DV0(w);if(W){let z=kBA(W);Y.push(...z.embeds),Z.push(...z.components)}else X.content=this.truncateContent(hC(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)X.embeds=Y;if(Z.length>0)X.components=Z;let K=wBA(w),U=this.tryPostSlashResponse(Q,X,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles(B,Q,X,K);this.logger.debug("Discord API: POST channel message",{channelId:B,contentLength:X.content?.length||0});let D=await(await this.discordFetch(`/channels/${B}/messages`,"POST",X)).json();return{id:D.id,threadId:Q,raw:D}}normalizeDiscordEmoji(Q){let $={"\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 Zj($)}};function _42(A){return new bhw(A??{})}var khw=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 $={threadId:A,token:Phw(),expiresAt:Date.now()+Q};return this.locks.set(A,$),$}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 $=this.cache.get(A);if($)if($.expiresAt!==null&&$.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 $=this.cache.get(A),B;if($&&$.expiresAt!==null&&$.expiresAt<=Date.now())B=[];else if($&&Array.isArray($.value))B=$.value;else B=[];if(B.push(Q),w?.maxLength&&B.length>w.maxLength)B=B.slice(B.length-w.maxLength);this.cache.set(A,{value:B,expiresAt:w?.ttlMs?Date.now()+w.ttlMs:null})}async enqueue(A,Q,w){this.ensureConnected();let $=this.queues.get(A);if(!$)$=[],this.queues.set(A,$);if($.push(Q),$.length>w)$.splice(0,$.length-w);return $.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 Phw(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function zV0(A){return new khw}b0();var Mhw=H.object({subscribedAt:H.string().datetime(),routingMode:H.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:H.boolean().optional()}),jhw="chat.discord.subscriptions";function PBA(A){return A.scoped({namespace:jhw,schema:Mhw})}function b42(A,Q=zV0()){let w=PBA(A);return new k42(Q,w)}class k42{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 P42(A){let{discord:Q}=A;if(!Q)return new e5A({userName:A.userName,adapters:{},state:zV0()});let w=_42({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new e5A({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:b42(A.runtimeState)})}class MBA{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 B={...w,routingMode:"mention-required"};if(!Q.isMention&&!w.mentionRequiredNoticeSent)await this.postMentionRequiredNotice(A,B);else await this.deps.getSubscriptions()?.set(A.id,B);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(($)=>!$.isBot&&!$.isMe).length>1}catch(Q){return this.deps.logger.debug("Failed to inspect Discord thread participants",{error:Q,threadId:A.id}),!1}}}$A();class jBA{deps;constructor(A){this.deps=A}async build(A,Q,w,$){let B={message:w.text.trim(),attachments:[],notices:[]};if(w.attachments.length===0)return B;if(!($==="anchor"||$==="trusted"))return B;let Y=this.deps.getUploadStore();if(!Y)return B;for(let Z of w.attachments){let W=Z.name;if(!W)continue;let K=uL(W,"upload"),U=YP(K,Z.mimeType),G=Z.size??0,D=VW0(K,U);if(!D){B.notices.push(`Unsupported file upload type: ${K}`);continue}if(!FW0(D,G)){B.notices.push(`File upload too large: ${K}`);continue}try{let z=await this.readAttachmentData(Z);if(!z)continue;let V=cL({filename:K,mediaType:U,content:z,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let I=await Y.save({filename:V.filename,mediaType:V.mediaType,content:z,metadata:this.buildMetadata(A,Q,w)});B.attachments.push(j42(I.filename,I.mediaType,z,I.ref,V.kind==="text"))}catch(z){this.deps.logger.error("Failed to read chat attachment",{error:z,filename:K}),B.notices.push(`Could not read file upload: ${K}`)}}return B}async readAttachmentData(A){if(A.fetchData)return A.fetchData();if(!A.url)return;let Q=await fetch(A.url);if(!Q.ok)throw Error(`Attachment download failed with status ${Q.status}`);let w=await Q.arrayBuffer();return Buffer.from(new Uint8Array(w))}buildMetadata(A,Q,w){let $=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,...$.guildId?{guildId:$.guildId}:{},...$.threadId?{threadId:$.threadId}:{}}}}function M42(A,Q,w,$){return j42(A,Q,w,$,ZP(A,Q))}function j42(A,Q,w,$,B){if(B)return{kind:"text",filename:A,mediaType:Q,content:w.toString("utf8").replace(/^\uFEFF/,""),sizeBytes:w.byteLength,source:$};return{kind:"file",filename:A,mediaType:Q,data:w,sizeBytes:w.byteLength,source:$}}function uQ0(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function lV(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 Ohw(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 O42(A,Q){if(A.isDM)return!1;let w=lV(A.id);if(!w.threadId)return!1;let $=Ohw(Q);return $!==void 0&&$!==w.threadId}function JV0(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=lV(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some(($)=>typeof $==="string"&&Q.allowedChannels.includes($))}function OBA(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 JV0(A,w)}function fBA(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return JV0(A,w)}function xBA(A,Q){return{channelId:lV(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function sp(A){return A.isDM?"DM":A.channelId}var fhw="https://discord.com/api/v10";async function f42(A){let Q=lV(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let $=A.fetchFn??fetch;try{let B=await $(`${fhw}/channels/${w}/messages/${A.messageId}`,{method:"PATCH",headers:{Authorization:`Bot ${A.botToken}`,"Content-Type":"application/json"},body:JSON.stringify({components:[]})});if(!B.ok)A.logger.debug("Failed to clear Discord message components",{messageId:A.messageId,channelId:w,status:B.status})}catch(B){A.logger.debug("Failed to clear Discord message components",{error:B,messageId:A.messageId,channelId:w})}}var x42={name:"@brains/chat",version:"0.2.0-alpha.181",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 Rhw=/https?:\/\/\S+/i,vhw=/[\s\S]+/,Chw=1000,hhw=H.looseObject({type:H.literal("card"),children:H.array(H.looseObject({type:H.string()})),imageUrl:H.string().optional(),subtitle:H.string().optional(),title:H.string().optional()}),Ehw=H.object({card:H.custom((A)=>hhw.safeParse(A).success),fallbackText:H.string().optional()});class VV0 extends wq{threadRegistry=new AV0;pendingApprovals;uploadContinuity;promptActions=new f8A(Chw);toolStatusMessenger=new x8A(this.threadRegistry);cardBuilder=new h8A({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new g8A({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new y8A({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await f42({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new MBA({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:O42,logger:this.logger});chatInputBuilder=new jBA({getUploadStore:()=>this.context?.uploads.scoped(uQ0()),getThreadIdParts:lV,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",x42,A,O8A);this.gatewayLoop=new T8A({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new S8A({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(uQ0()),buildApp:(Q)=>P42({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new Nt({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 jt({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(uQ0());if(!w)throw Error("Chat upload store unavailable");let $=await w.read(Q);return M42($.record.filename,$.record.mediaType,$.content,$.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=PBA(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 $=this.toDiscordCardOutput(Q);if($){w.post($).catch((B)=>this.logger.error("Failed to send chat message",{error:B,channelId:A}));return}if(typeof Q!=="string")return;for(let B of fQ0(A,Q))w.post(B).catch((X)=>this.logger.error("Failed to send chat message",{error:X,channelId:A}))}async sendMessageWithId({channelId:A,message:Q}){let w=this.threadRegistry.get(A);if(!w)return;let $=this.toDiscordCardOutput(Q);if($){let X=await w.post($);return this.threadRegistry.trackMessage(w.id,X),X.id}if(typeof Q!=="string")return;let B;for(let X of fQ0(A,Q))B=await w.post(X),this.threadRegistry.trackMessage(w.id,B);return B?.id}async editMessage({channelId:A,messageId:Q,newMessage:w}){let $=this.threadRegistry.getMessage(A,Q);if(!$)return!1;try{let B=await $.edit(this.toDiscordCardOutput(w)??(typeof w==="string"?w:""));if(A)this.threadRegistry.trackMessage(A,B);return!0}catch{return!1}}supportsMessageEditing(){return!0}toDiscordCardOutput(A){let Q=Ehw.safeParse(A);if(!Q.success)return;let{card:w,fallbackText:$}=Q.data;if($===void 0)return{card:w};return{card:w,fallbackText:$}}formatProgressOutput(A){return C8A(A)}formatCompletionOutput(A){return C8A(A)}async handleProgressEvent(A,Q){let w=A.metadata.interfaceType;if(w&&w!==this.id){if(!this.isEnabledPlatform(w))return;let $={...A,metadata:{...A.metadata,interfaceType:this.id}};await super.handleProgressEvent($,$.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 w12(A,Boolean(this.config.adapters.discord))}registerChatHandlers(A){if(A.onDirectMessage(async(Q,w,$,B)=>{await this.handleRoutedMessage(Q,w,B)}),A.onNewMention(async(Q,w,$)=>{let B=this.getPlatformConfig(Q);if(B&&OBA(Q,w,B)&&!Q.isDM&&B.useThreads)await this.subscriptionRouter.subscribeOwnedThread(Q,w);await this.handleRoutedMessage(Q,w,$)}),A.onSubscribedMessage(async(Q,w,$)=>{if(!await this.subscriptionRouter.shouldRouteSubscribedMessage(Q,w))return;await this.handleRoutedMessage(Q,w,$)}),this.config.adapters.discord&&!this.config.adapters.discord.requireMention)A.onNewMessage(vhw,async(Q,w,$)=>{await this.handleRoutedMessage(Q,w,$)});A.onNewMessage(Rhw,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([QV0,R8A],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(v8A,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(!fBA(w,Q,this.config.adapters.discord))return;let $=this.promptActions.get(A.value);if($?.threadId!==w.id){await w.post(this.formatNoticePayload("That suggested action is no longer available.","Action unavailable"));return}this.promptActions.consume(A.value);let B=lV(w.id),X=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:B.channelId??w.channelId,isBot:Boolean(A.user.isBot)}),Y=this.getConversationId(Q,w.id),Z=w.id;await this.runAgentTurn({thread:w,channelId:Z,logLabel:"Error handling chat prompt action",body:async()=>{if(!this.context)return;let W=await this.context.agent.chat($.prompt,Y,{userPermissionLevel:X,interfaceType:Q,channelId:Z,channelName:sp(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Z,conversationId:Y,response:W,userPermissionLevel:X})}})}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 B=A.thread;if(!fBA(B,Q,this.config.adapters.discord))return;let X=lV(B.id),Y=this.context.permissions.getUserLevel(Q,A.user.userId,{channelId:X.channelId??B.channelId,isBot:Boolean(A.user.isBot)});await this.confirmApproval({thread:B,conversationId:w,approvalId:A.value,confirmed:A.actionId===QV0,userPermissionLevel:Y,metadata:this.buildActionEventMetadata(Q,B,A)})}async handleRoutedMessage(A,Q,w){if(!this.context)return;let $=this.getPlatform(A);if($!=="discord")return;let B=this.getPlatformConfig(A);if(!B)return;if(!OBA(A,Q,B))return;await this.routeToAgent($,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 $=this.formatErrorPayload(w),B=this.toDiscordCardOutput($);if(B){await A.post(B);return}let X=typeof $==="string"?$:"Message failed.";for(let Y of fQ0(Q,X))await A.post(Y)}async routeToAgent(A,Q,w,$){if(!this.context)return;this.threadRegistry.set(Q);let B=this.getConversationId(A,Q.id),X=Q.id,Y=xBA(Q,w),Z=this.context.permissions.getUserLevel(A,w.author.userId,Y),W=await this.chatInputBuilder.build(A,Q,w,Z),K=[...W.attachments];if(await this.attachPriorUploads(B,W,Z),await this.postUploadNotices(Q,W.notices),!W.message&&W.attachments.length===0)return;this.rememberUploadAttachments(B,K),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let U=await this.getPendingApprovalIds(B);if(U.size>0){if(await this.handleConfirmationResponse(W.message,B,Q,U,Z,this.buildUserMessageMetadata(A,Q,w)))return}let G=this.buildCoalescedAgentInput(W.message,$),D=await this.context.agent.chat(G.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:sp(Q),...this.buildUserMessageMetadata(A,Q,w,G.metadata),...W.attachments.length>0?{attachments:W.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:D,userPermissionLevel:Z})}})}async renderAgentResponse(A){if(A.confirmation)this.syncPendingConfirmationsFromResponse(A.conversationId,A.response,A.confirmation.approvalId);else this.rememberPendingConfirmationsFromResponse(A.conversationId,A.response);await this.handleAgentResponseToolStatuses(A.response,A.conversationId);let Q=await this.artifactDelivery.resolve(A.response.cards,A.userPermissionLevel),w=KR(A.response,{deniedCardIds:Q.deniedCardIds});if(A.confirmation)await this.approvalCards.resolve(A.conversationId,A.confirmation.approvalId,A.confirmation.confirmed);let $=A.confirmation?this.formatConfirmationResponsePayload(A.response,A.confirmation.confirmed,this.getRemainingApprovalHelp(A.conversationId,A.response),Q.deniedCardIds):this.formatAgentResponseText(w,Q.deniedCardIds),B=await this.sendAgentResponseWithFiles({thread:A.thread,channelId:A.channelId,message:$,files:Q.files}),X=await this.sendArtifactCards(A.thread,w);await this.sendSupplementalCards(A.thread,w);let Y=w.directives.find((W)=>W.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let Z=X??B;if(Z)for(let W of w.jobIds)this.trackAgentResponseForJob(W,Z,A.channelId)}rememberPendingConfirmationsFromResponse(A,Q){this.pendingApprovals.rememberFromResponse(A,Q)}async getPendingApprovalIds(A){return this.pendingApprovals.getApprovalIds(A)}async handleConfirmationResponse(A,Q,w,$,B,X){if(!Vt(A,$))return!1;let Y=BW0({message:A,approvalIds:$});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:B,...X?{metadata:X}:{}}),!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:sp(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(`
|
|
2400
2400
|
|
|
2401
2401
|
`)}formatConfirmationResponsePayload(A,Q,w,$){let B=DW0({response:A,confirmed:Q,remainingApprovalHelp:w,deniedCardIds:$,formatCard:(X)=>this.cardBuilder.formatStructuredCard(X,$),formatPendingConfirmationHelp:vS});return{card:{type:"card",title:UW0(B.variant),children:B.parts.map((X)=>({type:"text",content:X}))},fallbackText:B.parts.join(`
|
|
2402
2402
|
|
|
@@ -2468,7 +2468,7 @@ ${S5A(A)}
|
|
|
2468
2468
|
<p>Once built, this page will be replaced with your actual website.</p>
|
|
2469
2469
|
</div>
|
|
2470
2470
|
</body>
|
|
2471
|
-
</html>`;var DX2={name:"@brains/webserver",version:"0.2.0-alpha.180",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 Kj extends iJ{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",DX2,A,rBA)}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 fV0({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}`,$=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,B=[];if(Q){if(B.push(`Production: ${w}`),A?.previewUrl)B.push(`Preview: ${$}`)}return{status:Q?"healthy":"error",message:Q?B.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?$: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&&!qX2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(zX2(this.config.previewDistDir,"index.html"),oBA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!qX2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(zX2(this.config.productionDistDir,"index.html"),oBA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}g$();$A();b0();MR();var JX2={name:"@brains/web-chat",version:"0.2.0-alpha.180",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2","@tanstack/react-query":"^5.0.0",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",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"};$A();async function VX2(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let $=new URL(A.url),B=$.searchParams.get("id")?.trim();if(!B)return new Response("Missing document id",{status:400});let X=await IX2({entityType:"document",id:B,permissionLevel:w,entityService:Q.entityService});if(!X)return new Response("Document not found",{status:404});if(typeof X.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=yL("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=TL(X.metadata,B,"document",Y.mimeType);return LX2({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function FX2(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let $=new URL(A.url),B=$.searchParams.get("id")?.trim();if(!B)return new Response("Missing image id",{status:400});let X=await IX2({entityType:"image",id:B,permissionLevel:w,entityService:Q.entityService});if(!X)return new Response("Image not found",{status:404});if(typeof X.content!=="string")return new Response("Image content is not an image",{status:415});let Y=yL("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=TL(X.metadata,B,"image",Y.mimeType);return LX2({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function IX2(A){let Q={entityType:A.entityType,id:A.id},w=await SL({entityRef:Q,userLevel:A.permissionLevel,getEntity:($)=>A.entityService.getEntity($),getVisibleEntity:($,B)=>A.entityService.getEntity({...$,visibilityScope:B})});return w.status==="visible"?w.entity:void 0}function LX2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":BP({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}b0();$A();var rQ0="upload",NX2=NS;var xEw={namespace:"upload",refKind:rQ0,routePath:"/api/chat/uploads"};function xV0(){return xEw}$A();_l0();var _X2=zW0;var bX2=JW0;var REw="file",vEw=16384;async function kX2(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>bX2+vEw)return new Response("File upload too large",{status:400});let $;try{$=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let B=$.get(REw);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=cL({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),W=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(W),{status:201})}async function PX2(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 $=await OX2(w,Q.getUploadStore());if($ instanceof Response)return $;let{record:B,content:X}=$,Y=fX2(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",W=new Uint8Array(X).buffer;return new Response(W,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":BP({disposition:Z,filename:B.filename})}})}function MX2(A){let Q=uL(A.filename??_X2),w=hEw(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let $=cL({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!$.ok)return new Response($.message,{status:400});return xX2($,w.buffer)}async function jX2(A,Q){let w=await OX2(A,Q);if(w instanceof Response)return w;let{record:$,content:B}=w,X=fX2($,B);if(X instanceof Response)return X;return xX2(X,B,{kind:rQ0,id:A})}async function OX2(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof nJ)return CEw(w);throw w}}function fX2(A,Q){let w=cL({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function xX2(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 CEw(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 hEw(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let $=A.slice(5,A.indexOf(",")).split(";").some((B)=>B.toLowerCase()==="base64");try{let B=$?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:B,byteLength:B.byteLength}}catch{return null}}var EEw=H.object({type:H.literal("text"),text:H.string()}),gEw=H.object({type:H.literal("file"),mediaType:H.string().optional(),filename:H.string().optional(),url:H.string()}),yEw=H.looseObject({state:H.literal("approval-responded"),approval:H.object({id:H.string(),approved:H.boolean()})}),TEw=H.object({id:H.string().optional(),role:H.string(),parts:H.array(H.unknown()).optional(),content:H.string().optional()}),RX2=H.object({id:H.string().optional(),messages:H.array(TEw).min(1),trigger:H.string().optional()}),SEw=H.object({kind:H.literal(rQ0),id:H.string().regex(NX2)}),mEw=H.object({type:H.literal("data-upload"),data:H.object({ref:SEw})});async function vX2(A,Q){let w=uEw(A);if(!w)return{message:"",attachments:[]};let $=[],B=[];for(let Y of w.parts??[]){let Z=EEw.safeParse(Y);if(Z.success){if(Z.data.text.length>0)$.push(Z.data.text);continue}let W=gEw.safeParse(Y);if(W.success){let U=MX2(W.data);if(U instanceof Response)return U;B.push(U);continue}let K=mEw.safeParse(Y);if(K.success){let U=await jX2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(cEw(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:$.length>0?$.join(`
|
|
2471
|
+
</html>`;var DX2={name:"@brains/webserver",version:"0.2.0-alpha.181",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 Kj extends iJ{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",DX2,A,rBA)}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 fV0({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}`,$=this.previewUrl??A?.previewUrl??`http://localhost:${this.config.previewPort}`,B=[];if(Q){if(B.push(`Production: ${w}`),A?.previewUrl)B.push(`Preview: ${$}`)}return{status:Q?"healthy":"error",message:Q?B.join(", "):"Webserver not running",lastCheck:new Date,details:{preview:!!A?.previewUrl,production:Q,previewUrl:A?.previewUrl?$: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&&!qX2(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(zX2(this.config.previewDistDir,"index.html"),oBA),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!qX2(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(zX2(this.config.productionDistDir,"index.html"),oBA),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}g$();$A();b0();MR();var JX2={name:"@brains/web-chat",version:"0.2.0-alpha.181",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2","@tanstack/react-query":"^5.0.0",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",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"};$A();async function VX2(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let $=new URL(A.url),B=$.searchParams.get("id")?.trim();if(!B)return new Response("Missing document id",{status:400});let X=await IX2({entityType:"document",id:B,permissionLevel:w,entityService:Q.entityService});if(!X)return new Response("Document not found",{status:404});if(typeof X.content!=="string")return new Response("Document content is not a PDF",{status:415});let Y=yL("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=TL(X.metadata,B,"document",Y.mimeType);return LX2({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function FX2(A,Q){let w=await Q.resolvePermissionLevel(A);if(w==="public")return Q.createOperatorLoginRequiredResponse(A);let $=new URL(A.url),B=$.searchParams.get("id")?.trim();if(!B)return new Response("Missing image id",{status:400});let X=await IX2({entityType:"image",id:B,permissionLevel:w,entityService:Q.entityService});if(!X)return new Response("Image not found",{status:404});if(typeof X.content!=="string")return new Response("Image content is not an image",{status:415});let Y=yL("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=TL(X.metadata,B,"image",Y.mimeType);return LX2({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function IX2(A){let Q={entityType:A.entityType,id:A.id},w=await SL({entityRef:Q,userLevel:A.permissionLevel,getEntity:($)=>A.entityService.getEntity($),getVisibleEntity:($,B)=>A.entityService.getEntity({...$,visibilityScope:B})});return w.status==="visible"?w.entity:void 0}function LX2(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":BP({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}b0();$A();var rQ0="upload",NX2=NS;var xEw={namespace:"upload",refKind:rQ0,routePath:"/api/chat/uploads"};function xV0(){return xEw}$A();_l0();var _X2=zW0;var bX2=JW0;var REw="file",vEw=16384;async function kX2(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>bX2+vEw)return new Response("File upload too large",{status:400});let $;try{$=await A.formData()}catch{return new Response("Invalid multipart upload",{status:400})}let B=$.get(REw);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=cL({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),W=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(W),{status:201})}async function PX2(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 $=await OX2(w,Q.getUploadStore());if($ instanceof Response)return $;let{record:B,content:X}=$,Y=fX2(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",W=new Uint8Array(X).buffer;return new Response(W,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":BP({disposition:Z,filename:B.filename})}})}function MX2(A){let Q=uL(A.filename??_X2),w=hEw(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let $=cL({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!$.ok)return new Response($.message,{status:400});return xX2($,w.buffer)}async function jX2(A,Q){let w=await OX2(A,Q);if(w instanceof Response)return w;let{record:$,content:B}=w,X=fX2($,B);if(X instanceof Response)return X;return xX2(X,B,{kind:rQ0,id:A})}async function OX2(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof nJ)return CEw(w);throw w}}function fX2(A,Q){let w=cL({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function xX2(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 CEw(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 hEw(A){let Q=/^data:[^,]*,(.*)$/s.exec(A);if(!Q)return null;let $=A.slice(5,A.indexOf(",")).split(";").some((B)=>B.toLowerCase()==="base64");try{let B=$?Buffer.from(Q[1]??"","base64"):Buffer.from(decodeURIComponent(Q[1]??""),"utf8");return{buffer:B,byteLength:B.byteLength}}catch{return null}}var EEw=H.object({type:H.literal("text"),text:H.string()}),gEw=H.object({type:H.literal("file"),mediaType:H.string().optional(),filename:H.string().optional(),url:H.string()}),yEw=H.looseObject({state:H.literal("approval-responded"),approval:H.object({id:H.string(),approved:H.boolean()})}),TEw=H.object({id:H.string().optional(),role:H.string(),parts:H.array(H.unknown()).optional(),content:H.string().optional()}),RX2=H.object({id:H.string().optional(),messages:H.array(TEw).min(1),trigger:H.string().optional()}),SEw=H.object({kind:H.literal(rQ0),id:H.string().regex(NX2)}),mEw=H.object({type:H.literal("data-upload"),data:H.object({ref:SEw})});async function vX2(A,Q){let w=uEw(A);if(!w)return{message:"",attachments:[]};let $=[],B=[];for(let Y of w.parts??[]){let Z=EEw.safeParse(Y);if(Z.success){if(Z.data.text.length>0)$.push(Z.data.text);continue}let W=gEw.safeParse(Y);if(W.success){let U=MX2(W.data);if(U instanceof Response)return U;B.push(U);continue}let K=mEw.safeParse(Y);if(K.success){let U=await jX2(K.data.data.ref.id,Q.uploadStore);if(U instanceof Response)return U;B.push(U);continue}if(cEw(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:$.length>0?$.join(`
|
|
2472
2472
|
|
|
2473
2473
|
`):w.content??"",attachments:B,...w.id?{messageId:w.id}:{}}}function CX2(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map((w)=>yEw.safeParse(w)).filter((w)=>w.success).map((w)=>w.data.approval)}function uEw(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 cEw(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}$A();var pEw=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function RV0(A){return A.replace(pEw,"").trimEnd()}$A();function hX2(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 sBA(A,Q){let w=Q.directives.flatMap(($)=>{switch($.kind){case"artifact":case"supplemental":return[$.card];case"approvals":return $.cards;default:return[]}});for(let $ of w){let B=_W0($);if(B.kind==="attachment"){A.write({type:"data-attachment",id:B.id,data:B});continue}if(B.kind==="sources"){A.write({type:"data-sources",id:B.id,data:B});continue}if(B.kind==="actions"){A.write({type:"data-actions",id:B.id,data:B});continue}let X=B.toolCallId??B.id,Y=B.input??{};switch(A.write({type:"tool-input-available",toolCallId:X,toolName:B.toolName,input:Y,dynamic:!0,title:B.preview?`${B.summary}
|
|
2474
2474
|
|
|
@@ -5759,7 +5759,7 @@ ${dX2}</style></head><body>${sQ0(A)}<main id="root" data-web-chat-root>Brain Cha
|
|
|
5759
5759
|
`);B=Y.pop()??"";for(let Z of Y){let W=Z.split(`
|
|
5760
5760
|
`).find((I)=>I.startsWith("data: "));if(!W)continue;let K;try{let I=Egw.safeParse(JSON.parse(W.slice(6)));if(!I.success)continue;K=I.data}catch{return w.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let U=K.result;if(!U?.final)continue;w.cancel().catch(()=>{});let G=U.status,D=G?.state??"unknown",V=(G?.message?.parts??[]).filter((I)=>I.kind==="text"&&typeof I.text==="string").map((I)=>I.text).join(`
|
|
5761
5761
|
`)||"No response text";return{success:!0,data:{state:D,response:V}}}X=await NY2(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class aQ0 extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class tQ0 extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function lgw(A,Q,w,$){let B=new AbortController,X;try{return await Promise.race([A(Q,{...w,signal:B.signal}),new Promise((Y,Z)=>{X=setTimeout(()=>{B.abort(),Z(new aQ0($))},$)})])}catch(Y){if(Y instanceof aQ0)throw Y;if(B.signal.aborted)throw new aQ0($);throw Y}finally{if(X)clearTimeout(X)}}async function NY2(A,Q){let w;try{return await Promise.race([A.read(),new Promise(($,B)=>{w=setTimeout(()=>B(new tQ0(Q)),Q)})])}catch($){if($ instanceof tQ0)A.cancel().catch(()=>{});throw $}finally{if(w)clearTimeout(w)}}function dgw(A){if(A instanceof aQ0||A instanceof tQ0)return!1;return A instanceof Error}function Z9A(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof tQ0)return`${A.message}${w}`;let $=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${$}`}async function H9A(A,Q={},w={}){let $=Q.fetch??globalThis.fetch,B={requestTimeoutMs:Q.requestTimeoutMs??ggw,streamIdleTimeoutMs:Q.streamIdleTimeoutMs??ygw,maxNetworkAttempts:Q.maxNetworkAttempts??Tgw},X=ugw(A.agent);if(!X.ok)return{success:!1,error:X.error};let{agentId:Y}=X;if(!Q.entityService)return{success:!1,error:"Agent directory is unavailable. Add the agent first, then try again."};let Z=await Q.entityService.getEntity({entityType:"agent",id:Y,visibilityScope:B7("agent_call is anchor-only and resolves saved remote agents at any visibility")});if(!Z){if(w.requireSaved)return{success:!1,error:`Agent ${Y} is not saved or approved.`,code:"agent_not_saved"};if(!cgw(Y))return{success:!1,error:`Agent ${A.agent} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let G=`https://${Y}`,D=await IY2(G,$);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${Y}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let z=FY2(D.url,Y);if(!z.ok)return{success:!1,error:z.error};let V=await LY2(D.url,A.message,$,Q.requestSigner,B);if("success"in V&&V.success===!0){let I=typeof V.data==="object"&&V.data!==null?V.data:{};return{...V,data:{...I,agentCall:{mode:"one-shot",agent:Y},agentContactCandidate:{source:{kind:"url",url:X.sourceUrl??Y}}}}}return V}if(Z.metadata.status==="archived")return{success:!1,error:`Agent ${Y} is archived and cannot be contacted until it is restored and approved.`,code:"agent_archived"};if(Z.metadata.status!=="approved")return{success:!1,error:`Agent ${Y} is discovered but not approved yet. Approve it first.`,code:"agent_not_approved"};let W=`https://${Y}`,K=await IY2(W,$);if(!K)return{success:!1,error:`Could not fetch Agent Card from ${W}`};let U=FY2(K.url,Y);if(!U.ok)return{success:!1,error:U.error};return LY2(K.url,A.message,$,Q.requestSigner,B)}function bY2(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:Sgw,visibility:"trusted",sideEffects:"external",handler:async(Q)=>{let w=mgw.safeParse(Q);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};return H9A(w.data,A)}}}$A();b0();var igw=H.object({agent:H.string().trim().min(1).max(253),instruction:H.string().trim().min(1).max(2000),selection:H.string().min(1).max(8000)});function kY2(A,Q){A.messaging.subscribe("a2a:call:request",async(w)=>{let $=igw.safeParse(w.payload);if(!$.success)return{success:!1,error:"Invalid A2A call request"};let{agent:B,instruction:X,selection:Y}=$.data,Z=await H9A({agent:B,message:["A CMS author is asking about selected markdown.",`Instruction: ${X}`,"","Selected markdown:",Y].join(`
|
|
5762
|
-
`)},Q,{requireSaved:!0});if("success"in Z&&Z.success===!0)return{success:!0,data:Z.data};return{success:!1,error:"error"in Z?Z.error:"Agent call failed"}}),A.messaging.subscribe("a2a:call:agents",async()=>{if(!A.entityService.hasEntityType("agent"))return{success:!0,data:{agents:[]}};return{success:!0,data:{agents:(await A.entityService.listEntities({entityType:"agent",options:{filter:{visibilityScope:B7("operator CMS lists approved A2A contacts at any visibility")}}})).filter((B)=>B.metadata.status==="approved").map((B)=>{let X=B.metadata.name;return{id:B.id,label:typeof X==="string"&&X.length>0?X:B.id}}).sort((B,X)=>B.label.localeCompare(X.label))}}})}var W9A={name:"@brains/a2a",version:"0.2.0-alpha.180",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 rgw={"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 $l extends iJ{agentCard;taskManager=new Y9A;agentService;jwksResolver=new B9A;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",W9A,A,HY2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,kY2(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(),$=A.tools.listForPermissionLevel("public"),B;if(A.entityService.hasEntityType("skill"))try{let X=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(X.length>0)B=X.map((Y)=>xt.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=WY2({character:Q,profile:w,version:W9A.version,domain:A.domain,organization:this.config.organization,tools:$,skills:B,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),$=new URL(`${w.pathname}${w.search}`,qM(A)),B=await XY2({method:A.method,url:$.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await pX()?.getA2APeerTrust(B.domain);return{permissionLevel:X?.keyFingerprint===B.keyFingerprint?X.grantedLevel:"public",callerDomain:B.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(rgw))Q.set(w,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new tp;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/.well-known/agent-directory.json",async(Q)=>{let w=await KY2(this.getContext().entityService);return this.withCors(Q.json(w))}),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(),$;try{$=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let B;try{B=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let X=DY2.safeParse(B);if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(X.data.method==="message/stream"){let Z=zY2.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let W=JY2(X.data.id,Z.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});if("error"in W)return this.withCors(Q.json(W));let{stream:K}=W;return this.withCors(new Response(K,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await qY2(X.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/.well-known/agent-directory.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=pX();if(!A)return;let Q=A.getIssuer();if(DM(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let $=await A.getA2ASigningKey();await BY2(w,$.privateJwk,$.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[bY2(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")}}}}$A();b0();var PY2={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 MY2={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 jY2={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 OY2={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 fY2={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 xY2={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 RY2={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 vY2={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 CY2={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 Byw=H.object({type:H.string()}).catchall(H.unknown()),Xyw=H.object({lexicon:H.literal(1),id:H.string(),defs:H.object({main:H.object({type:H.literal("record"),key:H.string().min(1),record:H.object({type:H.literal("object"),required:H.array(H.string()).optional(),properties:H.record(H.string(),Byw)})})})});function nq(A){return Xyw.parse(A)}var I$={"ai.rizom.brain.card":nq(PY2),"ai.rizom.brain.deck":nq(MY2),"ai.rizom.brain.link":nq(jY2),"ai.rizom.brain.note":nq(OY2),"ai.rizom.brain.post":nq(fY2),"ai.rizom.brain.project":nq(xY2),"ai.rizom.brain.series":nq(RY2),"ai.rizom.brain.socialPost":nq(vY2),"ai.rizom.brain.topic":nq(CY2)},Yyw="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function $_(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:Yyw}}var hY2={"ai.rizom.brain.card":$_("@brains/atproto"),"ai.rizom.brain.deck":$_("@brains/decks"),"ai.rizom.brain.link":$_("@brains/link"),"ai.rizom.brain.note":$_("@brains/note"),"ai.rizom.brain.post":$_("@brains/blog"),"ai.rizom.brain.project":$_("@brains/portfolio"),"ai.rizom.brain.series":$_("@brains/series"),"ai.rizom.brain.socialPost":$_("@brains/social-media"),"ai.rizom.brain.topic":$_("@brains/topics")};function Gj(){return Object.values(I$)}function yV0(A){if(!(A in I$))return;return I$[A]}function TV0(){return Object.entries(hY2).map(([A,Q])=>({id:A,...Q}))}b0();function SV0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var Zyw=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function Hyw(A){let Q=H.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine(($)=>A.knownValues?.includes($),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine(($)=>Zyw.test($)&&!Number.isNaN(Date.parse($)),{message:"expected datetime"});if(A.format==="uri")w=w.refine(($)=>{try{return new URL($),!0}catch{return!1}},{message:"expected uri"});return w}function EY2(A){switch(A.type){case"string":return Hyw(A);case"integer":return H.number().int();case"boolean":return H.boolean();case"array":{let Q=A.items?EY2(A.items):H.unknown(),w=H.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return Wyw(A);case"blob":return H.custom(SV0,{message:"expected blob"});default:return H.unknown()}}function gY2(A){let Q=new Set(A.required??[]),w={};for(let[$,B]of Object.entries(A.properties??{})){let X=EY2(B);w[$]=Q.has($)?X:X.optional()}return w}function Wyw(A){return H.object(gY2(A)).passthrough()}function K9A(A,Q,w,$=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;w.addIssue({code:H.ZodIssueCode.custom,path:$,message:`unrecognized field(s): ${B.join(", ")}`})}function Kyw(A,Q){if(K9A(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),SV0(A.brain))K9A(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(SV0(A.anchor))K9A(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function rq(A){let Q=H.object({...gY2(A.defs.main.record),$type:H.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(Kyw):Q}var U9A={"ai.rizom.brain.card":rq(I$["ai.rizom.brain.card"]),"ai.rizom.brain.deck":rq(I$["ai.rizom.brain.deck"]),"ai.rizom.brain.link":rq(I$["ai.rizom.brain.link"]),"ai.rizom.brain.note":rq(I$["ai.rizom.brain.note"]),"ai.rizom.brain.post":rq(I$["ai.rizom.brain.post"]),"ai.rizom.brain.project":rq(I$["ai.rizom.brain.project"]),"ai.rizom.brain.series":rq(I$["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":rq(I$["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":rq(I$["ai.rizom.brain.topic"])};function Uyw(A,Q){let w=A;for(let $ of Q){if(typeof $==="symbol")return;if(Array.isArray(w)){w=w[Number($)];continue}if(!SV0(w))return;w=w[String($)]}return w}function Gyw(A,Q,w){let $=w.path.join(".");if($==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&Uyw(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${$}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${$}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${$}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${$}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${$}: ${w.message}`}function B_(A,Q){let w=rq(A).safeParse(Q);if(w.success)return;let $=w.error.issues[0];if(!$)throw w.error;throw Error(Gyw(A,Q,$))}b0();var eQ0="atproto:brain-card-discovered",G9A="atproto:brain-discovered",D9A="atproto:brain-card-refreshed",Dyw=H.custom((A)=>U9A["ai.rizom.brain.card"].safeParse(A).success),q9A=H.object({repoDid:H.string().min(1),uri:H.string().min(1),cid:H.string().min(1),record:Dyw}).strict(),qyw=H.object({agentId:H.string().min(1),name:H.string().min(1),url:H.string().url(),status:H.enum(["discovered","approved","archived"]),repoDid:H.string().min(1).optional(),brainDid:H.string().min(1).optional(),anchorDid:H.string().min(1).optional(),cardUri:H.string().min(1).optional(),cardCid:H.string().min(1).optional()}).strict();class fB{static instance;projections=new Map;static getInstance(){return this.instance??=new fB,this.instance}static createFresh(){return new fB}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 $=this.projections.get(A);if(!$)return;let B=$.lastIndexOf(Q);if(B!==-1)$.splice(B,1);if($.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}`)}}b0();var yY2={name:"@brains/atproto-registry",version:"0.2.0-alpha.180",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 SY2=H.object({enabled:H.boolean().default(!0)}),z9A="/atproto/lexicons",Jyw=H.strictObject({nsid:H.string(),record:H.record(H.string(),H.unknown())});function TY2(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5762
|
+
`)},Q,{requireSaved:!0});if("success"in Z&&Z.success===!0)return{success:!0,data:Z.data};return{success:!1,error:"error"in Z?Z.error:"Agent call failed"}}),A.messaging.subscribe("a2a:call:agents",async()=>{if(!A.entityService.hasEntityType("agent"))return{success:!0,data:{agents:[]}};return{success:!0,data:{agents:(await A.entityService.listEntities({entityType:"agent",options:{filter:{visibilityScope:B7("operator CMS lists approved A2A contacts at any visibility")}}})).filter((B)=>B.metadata.status==="approved").map((B)=>{let X=B.metadata.name;return{id:B.id,label:typeof X==="string"&&X.length>0?X:B.id}}).sort((B,X)=>B.label.localeCompare(X.label))}}})}var W9A={name:"@brains/a2a",version:"0.2.0-alpha.181",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 rgw={"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 $l extends iJ{agentCard;taskManager=new Y9A;agentService;jwksResolver=new B9A;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",W9A,A,HY2)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,kY2(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(),$=A.tools.listForPermissionLevel("public"),B;if(A.entityService.hasEntityType("skill"))try{let X=await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}});if(X.length>0)B=X.map((Y)=>xt.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=WY2({character:Q,profile:w,version:W9A.version,domain:A.domain,organization:this.config.organization,tools:$,skills:B,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),$=new URL(`${w.pathname}${w.search}`,qM(A)),B=await XY2({method:A.method,url:$.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await pX()?.getA2APeerTrust(B.domain);return{permissionLevel:X?.keyFingerprint===B.keyFingerprint?X.grantedLevel:"public",callerDomain:B.domain}}return{permissionLevel:"public",callerDomain:null}}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(rgw))Q.set(w,$);return new Response(A.body,{status:A.status,statusText:A.statusText,headers:Q})}getOrCreateApp(){if(this.app)return this.app;let A=new tp;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/.well-known/agent-directory.json",async(Q)=>{let w=await KY2(this.getContext().entityService);return this.withCors(Q.json(w))}),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(),$;try{$=await this.resolveCaller(Q.req.raw,w)}catch{return this.withCors(Q.json({error:"Invalid HTTP signature"},401))}let B;try{B=JSON.parse(w)}catch{return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32700,message:"Parse error"},id:null}))}let X=DY2.safeParse(B);if(!X.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32600,message:"Invalid request"},id:null}));if(X.data.method==="message/stream"){let Z=zY2.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let W=JY2(X.data.id,Z.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});if("error"in W)return this.withCors(Q.json(W));let{stream:K}=W;return this.withCors(new Response(K,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await qY2(X.data,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});return this.withCors(Q.json(Y))}),this.app=A,A}getWebRoutes(){if(!this.hasWebserver)return[];let A=(Q)=>Promise.resolve(this.getOrCreateApp().fetch(Q));return[{path:"/.well-known/agent-card.json",method:"GET",public:!0,handler:A},{path:"/.well-known/agent-directory.json",method:"GET",public:!0,handler:A},{path:"/a2a",method:"GET",public:!0,handler:A},{path:"/a2a",method:"POST",public:!0,handler:A},{path:"/a2a",method:"OPTIONS",public:!0,handler:A}]}createRequestSigner(){let A=pX();if(!A)return;let Q=A.getIssuer();if(DM(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let $=await A.getA2ASigningKey();await BY2(w,$.privateJwk,$.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[bY2(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")}}}}$A();b0();var PY2={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 MY2={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 jY2={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 OY2={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 fY2={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 xY2={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 RY2={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 vY2={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 CY2={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 Byw=H.object({type:H.string()}).catchall(H.unknown()),Xyw=H.object({lexicon:H.literal(1),id:H.string(),defs:H.object({main:H.object({type:H.literal("record"),key:H.string().min(1),record:H.object({type:H.literal("object"),required:H.array(H.string()).optional(),properties:H.record(H.string(),Byw)})})})});function nq(A){return Xyw.parse(A)}var I$={"ai.rizom.brain.card":nq(PY2),"ai.rizom.brain.deck":nq(MY2),"ai.rizom.brain.link":nq(jY2),"ai.rizom.brain.note":nq(OY2),"ai.rizom.brain.post":nq(fY2),"ai.rizom.brain.project":nq(xY2),"ai.rizom.brain.series":nq(RY2),"ai.rizom.brain.socialPost":nq(vY2),"ai.rizom.brain.topic":nq(CY2)},Yyw="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function $_(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:Yyw}}var hY2={"ai.rizom.brain.card":$_("@brains/atproto"),"ai.rizom.brain.deck":$_("@brains/decks"),"ai.rizom.brain.link":$_("@brains/link"),"ai.rizom.brain.note":$_("@brains/note"),"ai.rizom.brain.post":$_("@brains/blog"),"ai.rizom.brain.project":$_("@brains/portfolio"),"ai.rizom.brain.series":$_("@brains/series"),"ai.rizom.brain.socialPost":$_("@brains/social-media"),"ai.rizom.brain.topic":$_("@brains/topics")};function Gj(){return Object.values(I$)}function yV0(A){if(!(A in I$))return;return I$[A]}function TV0(){return Object.entries(hY2).map(([A,Q])=>({id:A,...Q}))}b0();function SV0(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var Zyw=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function Hyw(A){let Q=H.string(),w=A.maxLength!==void 0?Q.max(A.maxLength):Q;if(A.knownValues)w=w.refine(($)=>A.knownValues?.includes($),{message:`expected one of ${A.knownValues.join(", ")}`});if(A.format==="datetime")w=w.refine(($)=>Zyw.test($)&&!Number.isNaN(Date.parse($)),{message:"expected datetime"});if(A.format==="uri")w=w.refine(($)=>{try{return new URL($),!0}catch{return!1}},{message:"expected uri"});return w}function EY2(A){switch(A.type){case"string":return Hyw(A);case"integer":return H.number().int();case"boolean":return H.boolean();case"array":{let Q=A.items?EY2(A.items):H.unknown(),w=H.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return Wyw(A);case"blob":return H.custom(SV0,{message:"expected blob"});default:return H.unknown()}}function gY2(A){let Q=new Set(A.required??[]),w={};for(let[$,B]of Object.entries(A.properties??{})){let X=EY2(B);w[$]=Q.has($)?X:X.optional()}return w}function Wyw(A){return H.object(gY2(A)).passthrough()}function K9A(A,Q,w,$=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;w.addIssue({code:H.ZodIssueCode.custom,path:$,message:`unrecognized field(s): ${B.join(", ")}`})}function Kyw(A,Q){if(K9A(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),SV0(A.brain))K9A(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(SV0(A.anchor))K9A(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function rq(A){let Q=H.object({...gY2(A.defs.main.record),$type:H.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(Kyw):Q}var U9A={"ai.rizom.brain.card":rq(I$["ai.rizom.brain.card"]),"ai.rizom.brain.deck":rq(I$["ai.rizom.brain.deck"]),"ai.rizom.brain.link":rq(I$["ai.rizom.brain.link"]),"ai.rizom.brain.note":rq(I$["ai.rizom.brain.note"]),"ai.rizom.brain.post":rq(I$["ai.rizom.brain.post"]),"ai.rizom.brain.project":rq(I$["ai.rizom.brain.project"]),"ai.rizom.brain.series":rq(I$["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":rq(I$["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":rq(I$["ai.rizom.brain.topic"])};function Uyw(A,Q){let w=A;for(let $ of Q){if(typeof $==="symbol")return;if(Array.isArray(w)){w=w[Number($)];continue}if(!SV0(w))return;w=w[String($)]}return w}function Gyw(A,Q,w){let $=w.path.join(".");if($==="$type")return`AT Protocol record $type must match lexicon id: ${String(Q.$type)} !== ${A.id}`;if(w.code==="invalid_type"&&Uyw(Q,w.path)===void 0)return`Missing required AT Protocol record field: ${$}`;if(w.code==="invalid_type")return`Invalid AT Protocol record field ${$}: expected ${w.expected}`;if(w.code==="too_big")return`Invalid AT Protocol record field ${$}: exceeds maxLength ${w.maximum}`;if(w.code==="custom")return`Invalid AT Protocol record field ${$}: ${w.message}`;if(w.code==="unrecognized_keys")return`Unrecognized AT Protocol record field(s): ${w.keys.join(", ")}`;return`Invalid AT Protocol record field ${$}: ${w.message}`}function B_(A,Q){let w=rq(A).safeParse(Q);if(w.success)return;let $=w.error.issues[0];if(!$)throw w.error;throw Error(Gyw(A,Q,$))}b0();var eQ0="atproto:brain-card-discovered",G9A="atproto:brain-discovered",D9A="atproto:brain-card-refreshed",Dyw=H.custom((A)=>U9A["ai.rizom.brain.card"].safeParse(A).success),q9A=H.object({repoDid:H.string().min(1),uri:H.string().min(1),cid:H.string().min(1),record:Dyw}).strict(),qyw=H.object({agentId:H.string().min(1),name:H.string().min(1),url:H.string().url(),status:H.enum(["discovered","approved","archived"]),repoDid:H.string().min(1).optional(),brainDid:H.string().min(1).optional(),anchorDid:H.string().min(1).optional(),cardUri:H.string().min(1).optional(),cardCid:H.string().min(1).optional()}).strict();class fB{static instance;projections=new Map;static getInstance(){return this.instance??=new fB,this.instance}static createFresh(){return new fB}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 $=this.projections.get(A);if(!$)return;let B=$.lastIndexOf(Q);if(B!==-1)$.splice(B,1);if($.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}`)}}b0();var yY2={name:"@brains/atproto-registry",version:"0.2.0-alpha.181",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 SY2=H.object({enabled:H.boolean().default(!0)}),z9A="/atproto/lexicons",Jyw=H.strictObject({nsid:H.string(),record:H.record(H.string(),H.unknown())});function TY2(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5763
5763
|
`,{headers:{"Content-Type":"application/json"}})}class J9A extends Rw{constructor(A={}){super("atproto-registry",yY2,A,SY2)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${z9A}/index.json`,method:"GET",public:!0,handler:()=>TY2(this.getIndex())},...Gj().map((A)=>({path:`${z9A}/${A.id}.json`,method:"GET",public:!0,handler:()=>TY2(A)}))]}getIndex(){return{lexicons:TV0().map((A)=>({...A,path:`${z9A}/${A.id}.json`}))}}getLexicon(A){return yV0(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:H.string().describe("Canonical lexicon NSID"),record:H.record(H.string(),H.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=Jyw.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 B_(w,Q.data.record),{success:!0,data:{valid:!0}}}catch($){return{success:!0,data:{valid:!1,error:$ instanceof Error?$.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:Gj().length,nsids:Gj().map((A)=>A.id),metadata:TV0()}})}}}function Aw0(A={}){return new J9A(A)}$A();class V9A{logger;handleImport;handleDelete;deleteOnFileRemoval;fileOperations;constructor(A,Q,w,$,B=!0){if(this.logger=A,this.fileOperations=$,this.deleteOnFileRemoval=B,w)this.handleImport=async(X)=>{let Y=await w({type:"directory-import",data:{paths:[X]}});this.logger.debug("Queued import job for file change",{jobId:Y,path:X})},this.handleDelete=async(X)=>{if(!this.deleteOnFileRemoval){this.logger.warn("File deleted but deleteOnFileRemoval is disabled",{path:X});return}try{let{entityType:Y,id:Z}=this.fileOperations.parseEntityFromPath(X),W=await w({type:"directory-delete",data:{entityId:Z,entityType:Y,filePath:X}});this.logger.info("Queued delete job for removed file",{jobId:W,path:X,entityId:Z,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:X,error:Y})}};else this.handleImport=async(X)=>{await Q([X])},this.handleDelete=async(X)=>{this.logger.warn("File deleted but no job queue available",{path:X})}}async handleFileChange(A,Q){this.logger.debug("Processing file change",{event:A,path:Q});try{switch(A){case"add":case"change":await this.handleImport(Q);break;case"delete":case"unlink":await this.handleDelete(Q);break;default:this.logger.debug("Unhandled file event",{event:A,path:Q})}}catch(w){this.logger.error("Failed to handle file change",{event:A,path:Q,error:w})}}}import{EventEmitter as iyw}from"events";import{stat as nyw,Stats as iT8}from"fs";import{readdir as ryw,stat as oyw}from"fs/promises";import*as d6 from"path";import{lstat as mY2,readdir as Vyw,realpath as Fyw,stat as Iyw}from"fs/promises";import{join as Lyw,relative as Nyw,resolve as uY2,sep as _yw}from"path";import{Readable as byw}from"stream";var NU={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},F9A={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:NU.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(F9A);var dY2="READDIRP_RECURSIVE_ERROR",kyw=new Set(["ENOENT","EPERM","EACCES","ELOOP",dY2]),cY2=[NU.DIR_TYPE,NU.EVERYTHING_TYPE,NU.FILE_DIR_TYPE,NU.FILE_TYPE],Pyw=new Set([NU.DIR_TYPE,NU.EVERYTHING_TYPE,NU.FILE_DIR_TYPE]),Myw=new Set([NU.EVERYTHING_TYPE,NU.FILE_DIR_TYPE,NU.FILE_TYPE]),jyw=(A)=>kyw.has(A.code),Oyw=process.platform==="win32",pY2=(A)=>!0,lY2=(A)=>{if(A===void 0)return pY2;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(($)=>w.basename===$)}return pY2};class I9A extends byw{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={...F9A,...A},{root:w,type:$}=Q;this._fileFilter=lY2(Q.fileFilter),this._directoryFilter=lY2(Q.directoryFilter);let B=Q.lstat?mY2:Iyw;if(Oyw)this._stat=(X)=>B(X,{bigint:!0});else this._stat=B;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:F9A.depth,this._wantsDir=$?Pyw.has($):!1,this._wantsFile=$?Myw.has($):!1,this._wantsEverything=$===NU.EVERYTHING_TYPE,this._root=uY2(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:$,depth:B}=Q,X=w.splice(0,A).map((Z)=>this._formatEntry(Z,$)),Y=await Promise.all(X);for(let Z of Y){if(!Z)continue;if(this.destroyed)return;let W=await this._getEntryType(Z);if(W==="directory"&&this._directoryFilter(Z)){if(B<=this._maxDepth)this.parents.push(this._exploreDir(Z.fullPath,B+1));if(this._wantsDir)this.push(Z),A--}else if((W==="file"||this._includeAsFile(Z))&&this._fileFilter(Z)){if(this._wantsFile)this.push(Z),A--}}}else{let $=this.parents.pop();if(!$){this.push(null);break}if(this.parent=await $,this.destroyed)return}}}catch(Q){this.destroy(Q)}finally{this.reading=!1}}async _exploreDir(A,Q){let w;try{w=await Vyw(A,this._rdOptions)}catch($){this._onError($)}return{files:w,depth:Q,path:A}}async _formatEntry(A,Q){let w,$=this._isDirent?A.name:A;try{let B=uY2(Lyw(Q,$));w={path:Nyw(this._root,B),fullPath:B,basename:$},w[this._statsProp]=this._isDirent?A:await this._stat(B)}catch(B){this._onError(B);return}return w}_onError(A){if(jyw(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 $=await Fyw(w),B=await mY2($);if(B.isFile())return"file";if(B.isDirectory()){let X=$.length;if(w.startsWith($)&&w.substr(X,1)===_yw){let Y=Error(`Circular symlink detected: "${w}" points to "${$}"`);return Y.code=dY2,this._onError(Y)}return"directory"}}catch($){return this._onError($),""}}}_includeAsFile(A){let Q=A&&A[this._statsProp];return Q&&this._wantsEverything&&!Q.isDirectory()}}function iY2(A,Q={}){let w=Q.entryType||Q.type;if(w==="both")w=NU.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&&!cY2.includes(w))throw Error(`readdirp: Invalid type passed. Use one of ${cY2.join(", ")}`);return Q.root=A,new I9A(Q)}import{watch as fyw,unwatchFile as nY2,watchFile as xyw}from"fs";import{realpath as L9A,lstat as Ryw,open as vyw,stat as oY2}from"fs/promises";import{type as Cyw}from"os";import*as wB from"path";var hyw="data",b9A="end",sY2="close",pV0=()=>{};var lV0=process.platform,k9A=lV0==="win32",Eyw=lV0==="darwin",gyw=lV0==="linux",yyw=lV0==="freebsd",aY2=Cyw()==="OS400",j5={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},oq=j5,Tyw="watch",Syw={lstat:Ryw,stat:oY2},lC="listeners",mV0="errHandlers",Bl="rawEmitters",myw=[lC,mV0,Bl],uyw=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"]),cyw=(A)=>uyw.has(wB.extname(A).slice(1).toLowerCase()),_9A=(A,Q)=>{if(A instanceof Set)A.forEach(Q);else Q(A)},Qw0=(A,Q,w)=>{let $=A[Q];if(!($ instanceof Set))A[Q]=$=new Set([$]);$.add(w)},pyw=(A)=>(Q)=>{let w=A[Q];if(w instanceof Set)w.clear();else delete A[Q]},ww0=(A,Q,w)=>{let $=A[Q];if($ instanceof Set)$.delete(w);else if($===w)delete A[Q]},tY2=(A)=>A instanceof Set?A.size===0:!A,uV0=new Map;function rY2(A,Q,w,$,B){let X=(Y,Z)=>{if(w(A),B(Y,Z,{watchedPath:A}),Z&&A!==Z)cV0(wB.resolve(A,Z),lC,wB.join(A,Z))};try{return fyw(A,{persistent:Q.persistent},X)}catch(Y){$(Y);return}}var cV0=(A,Q,w,$,B)=>{let X=uV0.get(A);if(!X)return;_9A(X[Q],(Y)=>{Y(w,$,B)})},lyw=(A,Q,w,$)=>{let{listener:B,errHandler:X,rawEmitter:Y}=$,Z=uV0.get(Q),W;if(!w.persistent){if(W=rY2(A,w,B,X,Y),!W)return;return W.close.bind(W)}if(Z)Qw0(Z,lC,B),Qw0(Z,mV0,X),Qw0(Z,Bl,Y);else{if(W=rY2(A,w,cV0.bind(null,Q,lC),X,cV0.bind(null,Q,Bl)),!W)return;W.on(oq.ERROR,async(K)=>{let U=cV0.bind(null,Q,mV0);if(Z)Z.watcherUnusable=!0;if(k9A&&K.code==="EPERM")try{await(await vyw(A,"r")).close(),U(K)}catch(G){}else U(K)}),Z={listeners:B,errHandlers:X,rawEmitters:Y,watcher:W},uV0.set(Q,Z)}return()=>{if(ww0(Z,lC,B),ww0(Z,mV0,X),ww0(Z,Bl,Y),tY2(Z.listeners))Z.watcher.close(),uV0.delete(Q),myw.forEach(pyw(Z)),Z.watcher=void 0,Object.freeze(Z)}},N9A=new Map,dyw=(A,Q,w,$)=>{let{listener:B,rawEmitter:X}=$,Y=N9A.get(Q),Z=Y&&Y.options;if(Z&&(Z.persistent<w.persistent||Z.interval>w.interval))nY2(Q),Y=void 0;if(Y)Qw0(Y,lC,B),Qw0(Y,Bl,X);else Y={listeners:B,rawEmitters:X,options:w,watcher:xyw(Q,w,(W,K)=>{_9A(Y.rawEmitters,(G)=>{G(oq.CHANGE,Q,{curr:W,prev:K})});let U=W.mtimeMs;if(W.size!==K.size||U>K.mtimeMs||U===0)_9A(Y.listeners,(G)=>G(A,W))})},N9A.set(Q,Y);return()=>{if(ww0(Y,lC,B),ww0(Y,Bl,X),tY2(Y.listeners))N9A.delete(Q),nY2(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class P9A{fsw;_boundHandleError;constructor(A){this.fsw=A,this._boundHandleError=(Q)=>A._handleError(Q)}_watchWithNodeFs(A,Q){let w=this.fsw.options,$=wB.dirname(A),B=wB.basename(A);this.fsw._getWatchedDir($).add(B);let Y=wB.resolve(A),Z={persistent:w.persistent};if(!Q)Q=pV0;let W;if(w.usePolling){let K=w.interval!==w.binaryInterval;Z.interval=K&&cyw(B)?w.binaryInterval:w.interval,W=dyw(A,Y,Z,{listener:Q,rawEmitter:this.fsw._emitRaw})}else W=lyw(A,Y,Z,{listener:Q,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return W}_handleFile(A,Q,w){if(this.fsw.closed)return;let $=wB.dirname(A),B=wB.basename(A),X=this.fsw._getWatchedDir($),Y=Q;if(X.has(B))return;let Z=async(K,U)=>{if(!this.fsw._throttle(Tyw,A,5))return;if(!U||U.mtimeMs===0)try{let G=await oY2(A);if(this.fsw.closed)return;let{atimeMs:D,mtimeMs:z}=G;if(!D||D<=z||z!==Y.mtimeMs)this.fsw._emit(oq.CHANGE,A,G);if((Eyw||gyw||yyw)&&Y.ino!==G.ino){this.fsw._closeFile(K),Y=G;let V=this._watchWithNodeFs(A,Z);if(V)this.fsw._addPathCloser(K,V)}else Y=G}catch(G){this.fsw._remove($,B)}else if(X.has(B)){let{atimeMs:G,mtimeMs:D}=U;if(!G||G<=D||D!==Y.mtimeMs)this.fsw._emit(oq.CHANGE,A,U);Y=U}},W=this._watchWithNodeFs(A,Z);if(!(w&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(oq.ADD,A,0))return;this.fsw._emit(oq.ADD,A,Q)}return W}async _handleSymlink(A,Q,w,$){if(this.fsw.closed)return;let B=A.fullPath,X=this.fsw._getWatchedDir(Q);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let Y;try{Y=await L9A(w)}catch(Z){return this.fsw._emitReady(),!0}if(this.fsw.closed)return;if(X.has($)){if(this.fsw._symlinkPaths.get(B)!==Y)this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(oq.CHANGE,w,A.stats)}else X.add($),this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(oq.ADD,w,A.stats);return this.fsw._emitReady(),!0}if(this.fsw._symlinkPaths.has(B))return!0;this.fsw._symlinkPaths.set(B,!0)}_handleRead(A,Q,w,$,B,X,Y){A=wB.join(A,"");let Z=$?`${A}:${$}`:A;if(Y=this.fsw._throttle("readdir",Z,1000),!Y)return;let W=this.fsw._getWatchedDir(w.path),K=new Set,U=this.fsw._readdirp(A,{fileFilter:(G)=>w.filterPath(G),directoryFilter:(G)=>w.filterDir(G)});if(!U)return;return U.on(hyw,async(G)=>{if(this.fsw.closed){U=void 0;return}let D=G.path,z=wB.join(A,D);if(K.add(D),G.stats.isSymbolicLink()&&await this._handleSymlink(G,A,z,D))return;if(this.fsw.closed){U=void 0;return}if(D===$||!$&&!W.has(D))this.fsw._incrReadyCount(),z=wB.join(B,wB.relative(B,z)),this._addToNodeFs(z,Q,w,X+1)}).on(oq.ERROR,this._boundHandleError),new Promise((G,D)=>{if(!U)return D();U.once(b9A,()=>{if(this.fsw.closed){U=void 0;return}let z=Y?Y.clear():!1;if(G(void 0),W.getChildren().filter((V)=>{return V!==A&&!K.has(V)}).forEach((V)=>{this.fsw._remove(A,V)}),U=void 0,z)this._handleRead(A,!1,w,$,B,X,Y)})})}async _handleDir(A,Q,w,$,B,X,Y){let Z=this.fsw._getWatchedDir(wB.dirname(A)),W=Z.has(wB.basename(A));if(!(w&&this.fsw.options.ignoreInitial)&&!B&&!W)this.fsw._emit(oq.ADD_DIR,A,Q);Z.add(wB.basename(A)),this.fsw._getWatchedDir(A);let K,U,G=this.fsw.options.depth;if((G==null||$<=G)&&!this.fsw._symlinkPaths.has(Y)){if(!B){if(await this._handleRead(A,w,X,B,A,$,K),this.fsw.closed)return}U=this._watchWithNodeFs(A,(D,z)=>{if(z&&z.mtimeMs===0)return;this._handleRead(D,!1,X,B,A,$,K)})}return U}async _addToNodeFs(A,Q,w,$,B){let X=this.fsw._emitReady;if(this.fsw._isIgnored(A)||this.fsw.closed)return X(),!1;let Y=this.fsw._getWatchHelpers(A);if(w)Y.filterPath=(Z)=>w.filterPath(Z),Y.filterDir=(Z)=>w.filterDir(Z);try{let Z=await Syw[Y.statMethod](Y.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(Y.watchPath,Z))return X(),!1;let W=this.fsw.options.followSymlinks,K;if(Z.isDirectory()){let U=wB.resolve(A),G=W?await L9A(A):A;if(this.fsw.closed)return;if(K=await this._handleDir(Y.watchPath,Z,Q,$,B,Y,G),this.fsw.closed)return;if(U!==G&&G!==void 0)this.fsw._symlinkPaths.set(U,G)}else if(Z.isSymbolicLink()){let U=W?await L9A(A):A;if(this.fsw.closed)return;let G=wB.dirname(Y.watchPath);if(this.fsw._getWatchedDir(G).add(Y.watchPath),this.fsw._emit(oq.ADD,Y.watchPath,Z),K=await this._handleDir(G,Z,Q,$,A,Y,U),this.fsw.closed)return;if(U!==void 0)this.fsw._symlinkPaths.set(wB.resolve(A),U)}else K=this._handleFile(Y.watchPath,Z,Q);if(X(),K)this.fsw._addPathCloser(A,K);return!1}catch(Z){if(this.fsw._handleError(Z))return X(),A}}}/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */var M9A="/",syw="//",$Z2=".",ayw="..",tyw="string",eyw=/\\/g,BZ2=/\/\//g,ATw=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,QTw=/^\.[/\\]/;function dV0(A){return Array.isArray(A)?A:[A]}var j9A=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function wTw(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=d6.relative(A.path,Q);if(!w)return!1;return!w.startsWith("..")&&!d6.isAbsolute(w)}return!1};return()=>!1}function $Tw(A){if(typeof A!=="string")throw Error("string expected");A=d6.normalize(A),A=A.replace(/\\/g,"/");let Q=!1;if(A.startsWith("//"))Q=!0;if(A=A.replace(BZ2,"/"),Q)A="/"+A;return A}function eY2(A,Q,w){let $=$Tw(Q);for(let B=0;B<A.length;B++){let X=A[B];if(X($,w))return!0}return!1}function BTw(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let $=dV0(A).map((B)=>wTw(B));if(Q==null)return(B,X)=>{return eY2($,B,X)};return eY2($,Q)}var AZ2=(A)=>{let Q=dV0(A).flat();if(!Q.every((w)=>typeof w===tyw))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(XZ2)},QZ2=(A)=>{let Q=A.replace(eyw,M9A),w=!1;if(Q.startsWith(syw))w=!0;if(Q=Q.replace(BZ2,M9A),w)Q=M9A+Q;return Q},XZ2=(A)=>QZ2(d6.normalize(QZ2(A))),wZ2=(A="")=>(Q)=>{if(typeof Q==="string")return XZ2(d6.isAbsolute(Q)?Q:d6.join(A,Q));else return Q},XTw=(A,Q)=>{if(d6.isAbsolute(A))return A;return d6.join(Q,A)},YTw=Object.freeze(new Set);class YZ2{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!==$Z2&&A!==ayw)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 ryw(w)}catch($){if(this._removeWatcher)this._removeWatcher(d6.dirname(w),d6.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=pV0,this.items=YTw,Object.freeze(this)}}var ZTw="stat",HTw="lstat";class ZZ2{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,w){this.fsw=w;let $=A;this.path=A=A.replace(QTw,""),this.watchPath=$,this.fullWatchPath=d6.resolve($),this.dirParts=[],this.dirParts.forEach((B)=>{if(B.length>1)B.pop()}),this.followSymlinks=Q,this.statMethod=Q?ZTw:HTw}entryPath(A){return d6.join(this.watchPath,d6.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 O9A extends iyw{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},$={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...A,ignored:A.ignored?dV0(A.ignored):dV0([]),awaitWriteFinish:Q===!0?w:typeof Q==="object"?{...w,...Q}:!1};if(aY2)$.usePolling=!0;if($.atomic===void 0)$.atomic=!$.usePolling;let B=process.env.CHOKIDAR_USEPOLLING;if(B!==void 0){let Z=B.toLowerCase();if(Z==="false"||Z==="0")$.usePolling=!1;else if(Z==="true"||Z==="1")$.usePolling=!0;else $.usePolling=!!Z}let X=process.env.CHOKIDAR_INTERVAL;if(X)$.interval=Number.parseInt(X,10);let Y=0;this._emitReady=()=>{if(Y++,Y>=this._readyCount)this._emitReady=pV0,this._readyEmitted=!0,process.nextTick(()=>this.emit(j5.READY))},this._emitRaw=(...Z)=>this.emit(j5.RAW,...Z),this._boundRemove=this._remove.bind(this),this.options=$,this._nodeFsHandler=new P9A(this),Object.freeze($)}_addIgnoredPath(A){if(j9A(A)){for(let Q of this._ignoredPaths)if(j9A(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(j9A(Q)&&Q.path===A)this._ignoredPaths.delete(Q)}}add(A,Q,w){let{cwd:$}=this.options;this.closed=!1,this._closePromise=void 0;let B=AZ2(A);if($)B=B.map((X)=>{return XTw(X,$)});if(B.forEach((X)=>{this._removeIgnoredPath(X)}),this._userIgnored=void 0,!this._readyCount)this._readyCount=0;return this._readyCount+=B.length,Promise.all(B.map(async(X)=>{let Y=await this._nodeFsHandler._addToNodeFs(X,!w,void 0,0,Q);if(Y)this._emitReady();return Y})).then((X)=>{if(this.closed)return;X.forEach((Y)=>{if(Y)this.add(d6.dirname(Y),d6.basename(Q||Y))})}),this}unwatch(A){if(this.closed)return this;let Q=AZ2(A),{cwd:w}=this.options;return Q.forEach(($)=>{if(!d6.isAbsolute($)&&!this._closers.has($)){if(w)$=d6.join(w,$);$=d6.resolve($)}if(this._closePath($),this._addIgnoredPath($),this._watched.has($))this._addIgnoredPath({path:$,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 $=w();if($ instanceof Promise)A.push($)})),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 B=(this.options.cwd?d6.relative(this.options.cwd,w):w)||$Z2;A[B]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==j5.ERROR)this.emit(j5.ALL,A,...Q)}async _emit(A,Q,w){if(this.closed)return;let $=this.options;if(k9A)Q=d6.normalize(Q);if($.cwd)Q=d6.relative($.cwd,Q);let B=[Q];if(w!=null)B.push(w);let X=$.awaitWriteFinish,Y;if(X&&(Y=this._pendingWrites.get(Q)))return Y.lastChange=new Date,this;if($.atomic){if(A===j5.UNLINK)return this._pendingUnlinks.set(Q,[A,...B]),setTimeout(()=>{this._pendingUnlinks.forEach((Z,W)=>{this.emit(...Z),this.emit(j5.ALL,...Z),this._pendingUnlinks.delete(W)})},typeof $.atomic==="number"?$.atomic:100),this;if(A===j5.ADD&&this._pendingUnlinks.has(Q))A=j5.CHANGE,this._pendingUnlinks.delete(Q)}if(X&&(A===j5.ADD||A===j5.CHANGE)&&this._readyEmitted){let Z=(W,K)=>{if(W)A=j5.ERROR,B[0]=W,this.emitWithAll(A,B);else if(K){if(B.length>1)B[1]=K;else B.push(K);this.emitWithAll(A,B)}};return this._awaitWriteFinish(Q,X.stabilityThreshold,A,Z),this}if(A===j5.CHANGE){if(!this._throttle(j5.CHANGE,Q,50))return this}if($.alwaysStat&&w===void 0&&(A===j5.ADD||A===j5.ADD_DIR||A===j5.CHANGE)){let Z=$.cwd?d6.join($.cwd,Q):Q,W;try{W=await oyw(Z)}catch(K){}if(!W||this.closed)return;B.push(W)}return this.emitWithAll(A,B),this}_handleError(A){let Q=A&&A.code;if(A&&Q!=="ENOENT"&&Q!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||Q!=="EPERM"&&Q!=="EACCES"))this.emit(j5.ERROR,A);return A||this.closed}_throttle(A,Q,w){if(!this._throttled.has(A))this._throttled.set(A,new Map);let $=this._throttled.get(A);if(!$)throw Error("invalid throttle");let B=$.get(Q);if(B)return B.count++,!1;let X,Y=()=>{let W=$.get(Q),K=W?W.count:0;if($.delete(Q),clearTimeout(X),W)clearTimeout(W.timeoutObject);return K};X=setTimeout(Y,w);let Z={timeoutObject:X,clear:Y,count:0};return $.set(Q,Z),Z}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(A,Q,w,$){let B=this.options.awaitWriteFinish;if(typeof B!=="object")return;let X=B.pollInterval,Y,Z=A;if(this.options.cwd&&!d6.isAbsolute(A))Z=d6.join(this.options.cwd,A);let W=new Date,K=this._pendingWrites;function U(G){nyw(Z,(D,z)=>{if(D||!K.has(A)){if(D&&D.code!=="ENOENT")$(D);return}let V=Number(new Date);if(G&&z.size!==G.size)K.get(A).lastChange=V;let I=K.get(A);if(V-I.lastChange>=Q)K.delete(A),$(void 0,z);else Y=setTimeout(U,X,z)})}if(!K.has(A))K.set(A,{lastChange:W,cancelWait:()=>{return K.delete(A),clearTimeout(Y),w}}),Y=setTimeout(U,X)}_isIgnored(A,Q){if(this.options.atomic&&ATw.test(A))return!0;if(!this._userIgnored){let{cwd:w}=this.options,B=(this.options.ignored||[]).map(wZ2(w)),Y=[...[...this._ignoredPaths].map(wZ2(w)),...B];this._userIgnored=BTw(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new ZZ2(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=d6.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new YZ2(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 $=d6.join(A,Q),B=d6.resolve($);if(w=w!=null?w:this._watched.has($)||this._watched.has(B),!this._throttle("remove",$,100))return;if(!w&&this._watched.size===1)this.add(A,Q,!0);this._getWatchedDir($).getChildren().forEach((G)=>this._remove($,G));let Z=this._getWatchedDir(A),W=Z.has(Q);if(Z.remove(Q),this._symlinkPaths.has(B))this._symlinkPaths.delete(B);let K=$;if(this.options.cwd)K=d6.relative(this.options.cwd,$);if(this.options.awaitWriteFinish&&this._pendingWrites.has(K)){if(this._pendingWrites.get(K).cancelWait()===j5.ADD)return}this._watched.delete($),this._watched.delete(B);let U=w?j5.UNLINK_DIR:j5.UNLINK;if(W&&!this._isIgnored($))this._emit(U,$);this._closePath($)}_closePath(A){this._closeFile(A);let Q=d6.dirname(A);this._getWatchedDir(Q).remove(d6.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:j5.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},$=iY2(A,w);return this._streams.add($),$.once(sY2,()=>{$=void 0}),$.once(b9A,()=>{if($)this._streams.delete($),$=void 0}),$}}function WTw(A,Q={}){let w=new O9A(Q);return w.add(A),w}var HZ2={watch:WTw,FSWatcher:O9A};import{extname as KTw}from"path";var iV0=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function dC(A){let Q=KTw(A).toLowerCase();return iV0.includes(Q)}function WZ2(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 f9A(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as UTw,relative as GTw,sep as KZ2,join as DTw}from"path";function c3(A,Q){return UTw(Q)?Q:DTw(A,Q)}function Xl(A,Q){let w=c3(A,Q),$=GTw(A,w);return KZ2==="/"?$:$.split(KZ2).join("/")}function qTw(A,Q){if(!Xl(Q,A).startsWith("image/"))return!1;return dC(A)}function zTw(A,Q){if(Xl(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return qTw(A,Q)}class x9A{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=HZ2.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(!zTw(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=Xl(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 $=c3(this.syncPath,Q);try{if(this.onFileChange)await this.onFileChange(w,$)}catch(B){this.logger.error("Error processing file change",{path:Q,event:w,error:B})}}}isWatching(){return!!this.watcher}getPendingChangesCount(){return this.pendingChanges.size}}async function UZ2(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return JTw(Q)}function GZ2(A){if(A)A.stop();return}function DZ2(A,Q){if(A)A.setCallback(Q)}async function JTw(A){let{logger:Q,syncPath:w,watchInterval:$,importEntities:B,jobQueueCallback:X,fileOperations:Y,deleteOnFileRemoval:Z}=A,W=new V9A(Q,B,X,Y,Z),K=new x9A({syncPath:w,watchInterval:$,logger:Q,onFileChange:async(U,G)=>{await W.handleFileChange(U,G)}});return await K.start(),K}async function qZ2(A){let Q=Date.now();A.logger.debug("Starting sync (import only)");let w=await A.importEntities(),$=await A.removeOrphanedEntities(),B=Date.now()-Q;return A.markSynced(new Date),A.logger.debug("Sync completed",{duration:B,imported:w.imported,orphansDeleted:$.deleted}),{export:{exported:0,failed:0,errors:[]},import:w,duration:B}}$A();class R9A{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 $=w.length;if(this.deleteOnFileRemoval)Q.push({type:"directory-cleanup",data:{}});let B=A.length;return this.logger.debug("Prepared batch operations",{exportOperationsCount:0,importOperationsCount:$,totalFiles:B}),{operations:Q,exportOperationsCount:0,importOperationsCount:$,totalFiles:B}}async queueSyncBatch(A,Q,w,$){let B=this.prepareBatchOperations(w);if(B.operations.length===0)return this.logger.debug("No sync operations needed",{source:Q}),null;return{batchId:await A.jobs.enqueueBatch(B.operations,{source:Q,rootJobId:$?.rootJobId??kY(),metadata:{progressToken:$?.progressToken,operationType:"file_operations",operationTarget:this.syncPath,pluginId:$?.pluginId??"directory-sync",interfaceType:$?.interfaceType,channelId:$?.channelId}}),operationCount:B.operations.length,exportOperationsCount:B.exportOperationsCount,importOperationsCount:B.importOperationsCount,totalFiles:B.totalFiles}}createImportOperations(A){if(A.length===0)return[];let Q=50,w=[];for(let $=0;$<A.length;$+=Q){let B=A.slice($,$+Q);w.push({type:"directory-import",data:{batchIndex:Math.floor($/Q),paths:B,batchSize:B.length}})}return w}}class v9A{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new R9A({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 $=await this.fileOperations.getAllSyncFiles();return await this.batchOperationsManager.queueSyncBatch(A,Q,$,w)}finally{this.syncInProgress=!1}}}class C9A{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 _Tw,dirname as bTw,extname as kTw}from"path";import{extname as VTw}from"path";var nV0=[".pdf"],zZ2=".meta.json";function iC(A){let Q=VTw(A).toLowerCase();return nV0.includes(Q)}function JZ2(A){return A.toLowerCase().endsWith(zZ2)}function h9A(A){return`${A}${zZ2}`}function VZ2(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as FTw,join as rV0}from"path";function oV0(A,Q){let $=Xl(A,Q).split("/"),B,X;if($.length===1)B="note",X=$;else if($.length>1&&$[0])B=$[0],X=$.slice(1);else B="note",X=$;let Y;if(X.length>1){let Z=X[X.length-1];if(Z)X[X.length-1]=FZ2(Z);Y=X.join(":")}else Y=FZ2(X[0]??"");return{entityType:B,id:Y}}function IZ2(A,Q,w,$=".md"){let B=Q.split(":").filter((K)=>K.length>0),X=w==="note";if(B.length===1)return X?rV0(A,`${B[0]}${$}`):rV0(A,w,`${B[0]}${$}`);let Y=B;if(B[0]===w)Y=B.slice(1);let Z=Y[Y.length-1],W=Y.slice(0,-1);if(X)return rV0(A,...W,`${Z}${$}`);return rV0(A,w,...W,`${Z}${$}`)}function LZ2(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return f9A(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?f9A(w[1]):".md"}function FZ2(A){let Q=FTw(A).toLowerCase();return Q===".md"||iV0.includes(Q)||nV0.includes(Q)?A.slice(0,-Q.length):A}b0();wH();import{mkdir as PTw,readFile as Yl,writeFile as g9A,stat as MTw,utimes as jTw}from"fs/promises";import{join as sV0}from"path";import{mkdir as NZ2,readdir as LTw,stat as NTw}from"fs/promises";import{access as ITw}from"fs/promises";async function O9(A){try{return await ITw(A),!0}catch{return!1}}async function E9A(A,Q){return PZ2(A,Q,{includeDocuments:!1,includeImages:!1})}async function _Z2(A,Q){return PZ2(A,Q,{includeDocuments:!0,includeImages:!0})}async function bZ2(A,Q){if(!await O9(A))await NZ2(A,{recursive:!0});for(let w of Q)if(w!=="note")await NZ2(sV0(A,w),{recursive:!0})}async function kZ2(A,Q){let w=[],$={totalFiles:0,byEntityType:{}};if(!await O9(A))return{files:w,stats:$};let B=await E9A(A,Q);for(let X of B)try{let Y=sV0(A,X),Z=await NTw(Y),{entityType:W}=oV0(A,X);w.push({path:X,entityType:W,modified:Z.mtime}),$.totalFiles++,$.byEntityType[W]=($.byEntityType[W]??0)+1}catch{continue}return{files:w,stats:$}}async function PZ2(A,Q,w){let $=[];if(!await O9(A))return $;let B=async(X,Y="",Z=!1,W=!1)=>{let K=await LTw(X,{withFileTypes:!0});for(let U of K){let G=Y?sV0(Y,U.name):U.name;if(U.isFile()&&!U.name.endsWith(".invalid")&&!JZ2(U.name)){if(U.name.endsWith(".md"))$.push(G);else if(w.includeImages&&Z&&dC(U.name))$.push(G);else if(w.includeDocuments&&W&&iC(U.name))$.push(G)}else if(U.isDirectory()&&!U.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(U.name))continue;let D=sV0(X,U.name),z=U.name==="image"&&Y==="",V=U.name==="document"&&Y==="";await B(D,G,Z||z,W||V)}}};return await B(A),$}var OTw=H.record(H.string(),H.unknown());class y9A{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return oV0(this.syncPath,A)}async readEntity(A){let Q=c3(this.syncPath,A),w=await MTw(Q),{entityType:$,id:B}=this.parseEntityFromPath(A),X=w.birthtime.getTime()>0?w.birthtime:w.mtime,Y=w.mtime,Z,W;if(dC(A)||iC(A)){let G=(await Yl(Q)).toString("base64"),D=kTw(A);if(Z=`data:${iC(A)?VZ2(D):WZ2(D)};base64,${G}`,iC(A))W=await this.readDocumentSidecar(Q,A)}else Z=await Yl(Q,"utf-8");let K={entityType:$,id:B,content:Z,created:X,updated:Y};if(W)K.metadata=W;return K}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:_Tw(Q)},$=h9A(A);if(!await O9($))return w;try{let B=await Yl($,"utf-8"),X=OTw.safeParse(JSON.parse(B));return{...w,...X.success?X.data:{}}}catch{return w}}async writeEntity(A){let Q=this.getEntityFilePath(A),w=A.entityType==="image",$=A.entityType==="document";if(w||$){let X=w?/^data:image\/[a-z+]+;base64,(.+)$/i:/^data:application\/pdf;base64,(.+)$/i,Y=A.content.match(X),Z=Y?.[1]?Buffer.from(Y[1],"base64"):Buffer.from(A.content,"base64"),W=!1;if(await O9(Q)){let K=await Yl(Q),U=mw(K.toString("base64")),G=mw(Z.toString("base64"));if(U===G)W=!0}if(!W)await this.ensureEntityDirectory(A,Q),await g9A(Q,Z);if($)await this.writeDocumentSidecar(A,Q);if(W)return}else{let X=this.entityService.serializeEntity(A);if(await O9(Q)){let Y=await Yl(Q,"utf-8"),Z=mw(Y),W=mw(X);if(Z===W)return}await this.ensureEntityDirectory(A,Q),await g9A(Q,X,"utf-8")}let B=new Date(A.updated);await jTw(Q,B,B)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await PTw(bTw(Q),{recursive:!0})}async writeDocumentSidecar(A,Q){let w=A.metadata,$={};for(let[Y,Z]of Object.entries(w)){if(Y==="mimeType")continue;if(Z===void 0)continue;$[Y]=Z}let B=h9A(Q),X=`${JSON.stringify($,null,2)}
|
|
5764
5764
|
`;if(await O9(B)){if(await Yl(B,"utf-8")===X)return}await this.ensureEntityDirectory(A,B),await g9A(B,X,"utf-8")}getFilePath(A,Q,w=".md"){return IZ2(this.syncPath,A,Q,w)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,LZ2(A))}async getAllMarkdownFiles(){return E9A(this.syncPath,this.entityService)}async getAllSyncFiles(){return _Z2(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await bZ2(this.syncPath,A)}shouldUpdateEntity(A,Q){let w=mw(Q.content);return A.contentHash!==w}async gatherFileStatus(){return kZ2(this.syncPath,this.entityService)}async syncDirectoryExists(){return O9(this.syncPath)}async fileExists(A){return O9(A)}}rY();b0();Q4();R2();rY();async function aV0(A,Q,w,$){let{sourceUrl:B}=A,X=await Q.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}});if(X[0])return $.debug("Reusing existing image entity",{sourceUrl:B,imageId:X[0].id}),X[0].id;let Y=await w(B),{base64:Z}=IP(Y),W=ER(Z),K=LP(Z);if(!W||!K)throw Error("Could not detect image format or dimensions");let U=await Q.createEntity({entity:{id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:W,width:K.width,height:K.height,sourceUrl:B}}});return $.debug("Created image entity from URL",{sourceUrl:B,imageId:U.entityId}),U.entityId}var MZ2=H.object({title:H.string(),slug:H.string().optional(),coverImageUrl:H.url(),coverImageId:H.string().optional(),coverImageAlt:H.string().optional()});class T9A{entityService;fetcher;logger;constructor(A,Q,w=z3){this.entityService=A,this.fetcher=w,this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=M$(A)}catch{return null}let{frontmatter:w}=Q,$=MZ2.safeParse(w);if(!$.success)return null;if($.data.coverImageId)return null;let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=$.data;if(!hR(Y))return null;return{sourceUrl:Y,postTitle:B,postSlug:X??F1(B),customAlt:Z}}async convert(A){let Q;try{Q=M$(A)}catch(K){return this.logger.debug("Parse failed",{error:K}),{content:A,converted:!1}}let{frontmatter:w}=Q,$=MZ2.safeParse(w);if(!$.success)return{content:A,converted:!1};if($.data.coverImageId)return{content:A,converted:!1};let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=$.data;if(!hR(Y))return{content:A,converted:!1};let W={postTitle:B,postSlug:X??F1(B),sourceUrl:Y,customAlt:Z};try{let K=await this.createImageEntity(W),U={...w};return delete U.coverImageUrl,delete U.coverImageAlt,U.coverImageId=K,{content:wR(U,Q.content),converted:!0,imageId:K}}catch(K){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:lA(K)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:w,sourceUrl:$,customAlt:B}=A,X=`Cover image for ${Q}`;return aV0({id:`${w}-cover`,title:X,alt:B??X,sourceUrl:$},this.entityService,this.fetcher,this.logger)}}rY();class $w0{entityService;fetcher;logger;constructor(A,Q,w=z3){this.entityService=A,this.fetcher=w,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let w=[],$=rr0(A);for(let B of $){if(!hR(B.url))continue;if(B.url.startsWith("entity://"))continue;let X=this.reconstructMarkdown(B);w.push({sourceUrl:B.url,alt:B.alt,originalMarkdown:X,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 $=A,B=0,X=0;for(let Y of w)try{let Z=await this.createImageEntity(Y,X++),W=``;$=$.replace(Y.originalMarkdown,W),B++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:Z})}catch(Z){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:lA(Z)})}return{content:$,converted:B>0,convertedCount:B}}async createImageEntity(A,Q){let{sourceUrl:w,alt:$,postSlug:B}=A;return aV0({id:`${B}-inline-${Q}`,title:$||`Inline image ${Q+1} for ${B}`,alt:$||"",sourceUrl:w},this.entityService,this.fetcher,this.logger)}}class S9A{logger;entityService;fileOperations;constructor(A,Q,w){this.logger=A,this.entityService=Q,this.fileOperations=w}async importEntitiesWithProgress(A,Q,w,$){this.logger.debug("Importing entities with progress reporting");let B={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},X=A??await this.fileOperations.getAllSyncFiles(),Y=X.length;await Q.report({progress:0,message:`Starting import of ${Y} files`});for(let Z=0;Z<Y;Z+=w){let W=X.slice(Z,Z+w),K=await $(W);B.imported+=K.imported,B.skipped+=K.skipped,B.failed+=K.failed,B.quarantined+=K.quarantined,B.errors.push(...K.errors),B.quarantinedFiles.push(...K.quarantinedFiles),B.jobIds.push(...K.jobIds);let U=Math.min(Z+w,Y),G=Math.round(U/Y*40);await Q.report({progress:G,message:`Imported ${U}/${Y} files`})}return B}async exportEntitiesWithProgress(A,Q,w,$){this.logger.debug("Exporting entities with progress reporting");let B=A??this.entityService.getEntityTypes();await Q.report({progress:50,message:`Starting export of ${B.length} entity types`});let X=await $(A);return await Q.report({progress:100,message:`Exported ${X.exported} entities`}),this.logger.debug("Export completed",X),X}}$A();import{rename as fTw,appendFile as xTw,readFile as RTw,writeFile as vTw,access as CTw}from"fs/promises";import{join as jZ2}from"path";class m9A{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return iH0(A)}async quarantineInvalidFile(A,Q,w,$){let B=$(A),X=`${B}.invalid`;try{await fTw(B,X),w.quarantined++,w.quarantinedFiles.push(A);let Y=jZ2(this.syncPath,".import-errors.log"),Z=new Date().toISOString(),W=lA(Q),K=`${Z} - ${A}: ${W}
|
|
5765
5765
|
\u2192 ${A}.invalid
|
|
@@ -5788,7 +5788,7 @@ ${dX2}</style></head><body>${sQ0(A)}<main id="root" data-web-chat-root>Brain Cha
|
|
|
5788
5788
|
*...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
|
|
5789
5789
|
## Getting Started
|
|
5790
5790
|
`),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(`
|
|
5791
|
-
`)}}$A();class _F0 extends p6{directorySync;constructor(A,Q,w){super(A,{schema:c7A,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let $=Date.now();try{let B=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:B.exported,failed:B.failed,duration:Date.now()-$}),B}catch(B){throw this.logger.error("Directory export job failed",{jobId:Q,error:B}),B}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}$A();class bF0 extends p6{directorySync;constructor(A,Q,w){super(A,{schema:u7A,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let $=Date.now();try{let B=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:B.imported,skipped:B.skipped,failed:B.failed,quarantined:B.quarantined,duration:Date.now()-$}),B}catch(B){throw this.logger.error("Directory import job failed",{jobId:Q,error:B}),B}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}$A();class kF0 extends p6{directorySync;context;constructor(A,Q,w){super(A,{schema:S7A,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let $=Date.now(),B=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:B});let X={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if(B!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),X=await this.importWithProgress(A.paths,w),B==="import")await this.waitForImportJobs(X.jobIds,w),await w.report({progress:100,message:`Import complete: ${X.imported} imported`});else await w.report({progress:50,message:`Imported ${X.imported} entities`}),await this.waitForImportJobs(X.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if(B!=="import"){let W=B==="export"?10:60;await w.report({progress:W,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:B==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${X.imported} imported, ${Y.exported} exported`})}let Z=Date.now()-$;return this.logger.info("Directory sync job completed",{jobId:Q,duration:Z,imported:X.imported,exported:Y.exported}),{import:X,export:Y,duration:Z}}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,$=300000,B=500,X=Date.now(),Y=async()=>{let W=(await Promise.all(A.map((U)=>w.getAsyncJobStatus(U)))).filter((U)=>U&&(U.status==="completed"||U.status==="failed")).length;if(W===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-X>$){this.logger.warn(`Timeout waiting for import jobs (${W}/${A.length} completed)`);return}let K=Math.round(W/A.length*100);return await Q.report({progress:50+Math.round(K*0.05),message:`Processing ${W}/${A.length} entities`}),await new Promise((U)=>setTimeout(U,B)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}$A();class PF0 extends p6{context;directorySync;gitSync;constructor(A,Q,w,$){super(A,{schema:m7A,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=$}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let $=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(!$)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: ${$.importOperationsCount} import jobs for ${$.totalFiles} files`}),acw($)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function acw(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}$A();class MF0 extends p6{context;constructor(A,Q,w){super(A,{schema:LF0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let $=LF0.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}),await w.report({progress:0,total:1,message:`Deleting ${$.entityType}:${$.entityId}`});try{let B=await this.context.entityService.deleteEntity({entityType:$.entityType,id:$.entityId});if(B)this.logger.info("Successfully deleted entity for removed file",{entityId:$.entityId,entityType:$.entityType});else this.logger.warn("Entity not found in database",{entityId:$.entityId,entityType:$.entityType});return await w.report({progress:1,total:1,message:`Deleted ${$.entityType}:${$.entityId}`}),{deleted:B,entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}}catch(B){throw this.logger.error("Failed to delete entity",{entityId:$.entityId,entityType:$.entityType,error:B}),B}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}$A();b0();var tcw=H.object({});class jF0 extends p6{directorySync;constructor(A,Q){super(A,{schema:tcw,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let $=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${$.deleted} orphans removed`}),$}}$A();rY();Q4();g$();b0();rY();import{readFile as ecw,writeFile as Apw}from"fs/promises";var Qpw=p7A,wpw=H.record(H.string(),H.unknown());class OF0 extends p6{context;fetcher;constructor(A,Q,w=z3){super(Q,{schema:Qpw,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:$,sourceUrl:B,postTitle:X,postSlug:Y,customAlt:Z}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:$,sourceUrl:B,postSlug:Y});try{await this.reportProgress(w,{progress:kw.INIT,message:`Reading file: ${$}`});let W;try{W=await ecw($,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:$,error:lA(F)}),J5.failure(F)}let K;try{K=M$(W)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:$,error:lA(F)}),J5.failure(F)}let U=wpw.safeParse(K.frontmatter),G=U.success?U.data:{};if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:kw.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),z;if(D[0])z=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:z}),await this.reportProgress(w,{progress:kw.EXTRACT,message:`Reusing existing image: ${z}`});else{await this.reportProgress(w,{progress:kw.PROCESS,message:`Fetching image from ${B}`});let F;try{F=await this.fetcher(B)}catch(v){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:lA(v)}),J5.failure(v)}await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let{base64:_}=IP(F),k=ER(_),b=LP(_);if(!k||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),J5.failure(Error("Could not detect image format or dimensions"));z=`${Y}-cover`;let f=`Cover image for ${X}`,R=Z??f;await this.context.entityService.createEntity({entity:{id:z,entityType:"image",content:F,metadata:{title:f,alt:R,format:k,width:b.width,height:b.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:z,sourceUrl:B}),await this.reportProgress(w,{progress:kw.EXTRACT,message:`Created image: ${z}`})}await this.reportProgress(w,{progress:kw.SAVE,message:"Updating file"});let V={...G};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=z;let I=wR(V,K.content);try{await Apw($,I,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:$,error:lA(F)}),J5.failure(F)}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:z,sourceUrl:B}),{success:!0,imageId:z}}catch(W){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:lA(W)}),J5.failure(W)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}$A();rY();g$();import{readFile as $pw,writeFile as Bpw}from"fs/promises";class fF0 extends p6{converter;constructor(A,Q,w=z3){super(Q,{schema:l7A,jobTypeName:"inline-image-convert"});this.converter=new $w0(A.entityService,Q,w)}async process(A,Q,w){let{filePath:$,postSlug:B}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:$,postSlug:B});try{await this.reportProgress(w,{progress:kw.INIT,message:`Reading file: ${$}`});let X;try{X=await $pw($,"utf-8")}catch(W){let K=lA(W);return this.logger.error("Failed to read file",{filePath:$,error:K}),{success:!1,error:K}}await this.reportProgress(w,{progress:kw.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(X,B);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:$,count:Y.length}),await this.reportProgress(w,{progress:kw.PROCESS,message:`Converting ${Y.length} images`});let Z=await this.converter.convert(X,B);if(!Z.converted)return this.logger.debug("No images were converted",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:kw.SAVE,message:"Writing updated file"});try{await Bpw($,Z.content,"utf-8")}catch(W){let K=lA(W);return this.logger.error("Failed to write file",{filePath:$,error:K}),{success:!1,error:K}}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=lA(X);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:$,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function UU2(A,Q,w){let $=(B)=>w.child(B);A.jobs.registerHandler("directory-sync",new kF0($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new _F0($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new bF0($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new MF0($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new jF0($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new OF0(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new fF0(A,$("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}$A();b0();import{unlink as Xpw,access as Ypw}from"fs/promises";var Zpw=H.record(H.string(),H.unknown());function GU2(A,Q,w,$){let{subscribe:B}=A.messaging,{entityService:X}=A;B("entity:created",async(Y)=>{let{entity:Z}=Y.payload;try{await Q.fileOps.writeEntity(Z),w.debug("Auto-exported created entity",{id:Z.id,entityType:Z.entityType})}catch(W){w.error("Auto-export FAILED for created entity",{id:Z.id,entityType:Z.entityType,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),B("entity:updated",async(Y)=>{let{entityType:Z,entityId:W}=Y.payload;try{let K=await X.getEntity({entityType:Z,id:W});if(!K)return w.debug("Entity not found in DB, skipping export",{entityType:Z,entityId:W}),{success:!1};await Q.fileOps.writeEntity(K),w.debug("Auto-exported updated entity",{id:K.id,entityType:K.entityType})}catch(K){w.error("Auto-export FAILED for updated entity",{entityType:Z,entityId:W,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0})}return{success:!0}}),B("entity:deleted",async(Y)=>{let{entityId:Z,entityType:W}=Y.payload,K=Q.fileOps.getFilePath(Z,W);if(await Ypw(K).then(()=>!0,()=>!1))await Xpw(K),w.debug("Auto-deleted entity file",{id:Z,entityType:W,path:K});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:$})}function DU2(A,Q,w){Q.setJobQueueCallback(async($)=>{let B=[{type:$.type,data:Zpw.parse($.data)}];return A.jobs.enqueueBatch(B,{priority:5,source:"directory-sync-watcher",rootJobId:kY(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}$A();import{readdir as JU2,mkdir as Wpw,copyFile as Kpw}from"fs/promises";import{join as zU2,resolve as d7A}from"path";import{join as Hpw}from"path";async function qU2(A){if(!await O9(Hpw(A,".git")))return!1;try{return await sq(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function Upw(A,Q){if(!await O9(A))return!0;if((await JU2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await qU2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function VU2(A,Q){let w=await JU2(A,{withFileTypes:!0});for(let $ of w){let B=zU2(A,$.name),X=zU2(Q,$.name);if($.isDirectory()){if(!await O9(X))await Wpw(X,{recursive:!0});await VU2(B,X)}else await Kpw(B,X)}}async function FU2(A,Q,w){let $=d7A(process.cwd(),A);w=w?d7A(w):d7A(process.cwd(),"seed-content");let B=await Upw($,Q);if(B&&await O9(w))Q.debug("Copying seed content to brain-data directory"),await VU2(w,$),Q.debug("Seed content copied successfully");else if(B)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function IU2(A,Q,w,$,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if(w.seedContent){let W=w.syncPath??A.dataDir;await FU2(W,$,w.seedContentPath)}try{if(B){$.debug("Git enabled \u2014 pulling before import");let K=await B.pull();if(K.files.length>0)$.info("Pulled changes from remote",{filesChanged:K.files.length})}$.debug("Starting initial sync");let W=await Z.sync();$.debug("Initial sync completed",{imported:W.import.imported,failed:W.import.failed,duration:W.duration}),await A.messaging.send({type:YR.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(W){$.error("Initial sync failed",W),await A.messaging.send({type:YR.initialSyncCompleted,payload:{success:!1,error:lA(W)},...{broadcast:!0}})}};A.messaging.subscribe(YR.pluginsRegistered,async()=>{return $.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class i7A{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 n7A{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 LU2(A,Q,w,$){let B=new n7A(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(Z){$.error("Git auto-commit failed",{error:Z})}})},w),X=["entity:created","entity:updated","entity:deleted"],Y=[];for(let Z of X){let W=A.subscribe(Z,async()=>{return B.trigger(),{success:!0}});Y.push(W)}return()=>{B.dispose();for(let Z of Y)Z()}}function NU2(A,Q,w,$,B){if($<=0)return()=>{};let X=$*60*1000,Y=!1,Z=async()=>{if(Y)return;Y=!0;try{let{files:K,result:U}=await A.withLock(async()=>{let G=await A.pull();if(G.files.length===0)return{files:[],result:null};let D=await Q.queueSyncBatch(w,"periodic-sync");return{files:G.files,result:D}});if(K.length>0)B.info("Periodic sync: pulled changes",{filesChanged:K.length});if(U)B.debug("Periodic sync: queued imports",{importOperations:U.importOperationsCount,totalFiles:U.totalFiles})}catch(K){B.error("Periodic git sync failed",{error:K})}finally{Y=!1}},W=setInterval(()=>{Z()},X);return B.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(W)}}import{spawnSync as bU2}from"child_process";import{cpSync as Gpw,existsSync as _U2,mkdirSync as Dpw,mkdtempSync as qpw,rmSync as zpw}from"fs";import{tmpdir as Jpw}from"os";import{fileURLToPath as Vpw}from"url";import{join as Fpw,resolve as Ipw}from"path";function zj(A,Q){let w=bU2("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let $=w.stderr.toString().trim(),B=w.stdout.toString().trim();throw Error($||B||`git ${Q.join(" ")} failed`)}}function Lpw(A){return A.startsWith("file://")}function Npw(A){return Vpw(A)}function _pw(A,Q){return bU2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function kU2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!Lpw(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=Npw(A.gitUrl),$=Ipw(A.seedContentPath);if(!_U2($))throw Error(`Seed content path not found: ${$}`);if(!_U2(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),Dpw(w,{recursive:!0}),zj(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(_pw(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:$,branch:Q});let B=qpw(Fpw(Jpw(),"directory-sync-seed-"));try{zj(B,["init",`--initial-branch=${Q}`]),zj(B,["config","user.name",A.authorName??"Brain"]),zj(B,["config","user.email",A.authorEmail??"brain@localhost"]),Gpw($,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),zj(B,["add","."]),zj(B,["commit","-m","seed content remote"]),zj(B,["remote","add","origin",A.gitUrl]),zj(B,["push","-u","origin",Q])}finally{zpw(B,{recursive:!0,force:!0})}}function PU2(A,Q,w,$,B,X){let{subscribe:Y}=A.messaging;Y("entity:export:request",async(Z)=>{try{return{success:!0,data:await Q().exportEntities(Z.payload.entityTypes)}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Export failed"}}}),Y("entity:import:request",async(Z)=>{try{let W=Q(),K=Z.payload.paths,U=await W.importEntities(K);if(K&&K.length>0)await W.removeOrphanedEntities();return{success:!0,data:U}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let W=await Q().getStatus();return{success:!0,data:{syncPath:W.syncPath,isInitialized:W.exists,watchEnabled:W.watching,lastSync:W.lastSync?.toISOString()??null,totalFiles:W.stats.totalFiles,byEntityType:W.stats.byEntityType,git:await bpw(X?.(),$)}}}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Status check failed"}}}),Y("sync:configure:request",async(Z)=>{try{return await w({syncPath:Z.payload.syncPath}),{success:!0,data:{syncPath:Z.payload.syncPath,configured:!0}}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Configuration failed"}}}),Y("git-sync:get-repo-info",async()=>{if(!B?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:B.repo,branch:B.branch??"main"}}}),$.debug("Registered message handlers")}async function bpw(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}}$A();b0();$A();b0();function MU2(A,Q){return j$(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",H.object({entityType:H.string().describe("Entity type (e.g. post, note, link)"),id:H.string().describe("Entity ID"),sha:H.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:H.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let $=`${w.entityType}/${w.id}.md`;try{if(w.sha){let X=await Q.show(w.sha,$);return Z7({sha:w.sha,entityType:w.entityType,id:w.id,content:X},`Content at ${w.sha.slice(0,7)}`)}let B=await Q.log($,w.limit);if(B.length===0)return Z7({commits:[]},`No history found for ${w.entityType}/${w.id}`);return Z7({commits:B,entityType:w.entityType,id:w.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return TX(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function jU2(A,Q,w,$){let B=[j$(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.",H.object({}),async(X,Y)=>{try{let Z=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,W={interfaceType:Y.interfaceType,channelId:Y.channelId};if($){let U=await Q.jobs.enqueue({type:"sync-request",data:{source:Z,interfaceType:W.interfaceType,channelId:W.channelId},toolContext:Y});return Z7({jobId:U,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let K=await A.queueSyncBatch(Q,Z,W);if(!K)return Z7({gitPulled:!1},"No files to sync");return Z7({batchId:K.batchId,importOperations:K.importOperationsCount,totalFiles:K.totalFiles,gitPulled:!1},`Sync started: ${K.importOperationsCount} import jobs queued for ${K.totalFiles} files`)}catch(Z){return TX(Z instanceof Error?Z.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),j$(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.",H.object({}),async()=>{try{let X=await A.getStatus(),Y={syncPath:X.syncPath,lastSync:X.lastSync?.toISOString(),watching:X.watching};if($){let Z=await $.getStatus();Y.git={isRepo:Z.isRepo,branch:Z.branch,hasChanges:Z.hasChanges,ahead:Z.ahead,behind:Z.behind,remote:Z.remote}}return Z7(Y)}catch(X){return TX(X instanceof Error?X.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if($)B.push(MU2(w,$));return B}var OU2={name:"@brains/directory-sync",version:"0.2.0-alpha.180",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 r7A extends Rw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",OU2,A,Jw0)}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:Vw0,basePrompt:"",formatter:new NF0,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new Bw0({syncPath:$,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:$})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let B=this.requireDirectorySync();if(GU2(A,B,this.logger,this.config.entityTypes),this.config.autoSync)DU2(A,B,this.config.syncPath??A.dataDir);let X=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!X)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(X&&this.config.git){await kU2({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 T7A({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 PF0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(LU2(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(NU2(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)IU2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);PU2(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return jU2(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 Bw0({...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){UU2(A,this.requireDirectorySync(),this.logger)}}function sC(A={}){return new r7A(A)}b0();var xF0="email:send",fU2=H.strictObject({to:H.string().email(),subject:H.string().min(1),text:H.string().min(1),html:H.string().min(1).optional(),sensitivity:H.enum(["normal","secret"]).default("normal")});$A();b0();var xU2={name:"@brains/email-resend",version:"0.2.0-alpha.180",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 Mpw=H.object({apiKey:H.string().min(1).optional(),from:H.string().min(1).optional()}),jpw=H.looseObject({id:H.string().optional()});class RU2 extends Rw{fetchImpl;constructor(A={},Q={}){super("email-resend",xU2,A,Mpw);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(xF0,async(w)=>{let $=fU2.parse(w.payload);try{return{success:!0,data:await this.sendWithResend($)}}catch(B){if($.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:$.to,subject:$.subject,error:B instanceof Error?B.message:String(B)});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 $=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(!$.ok)throw Error("Resend email request failed");let B=jpw.parse(await $.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function RF0(A={}){return new RU2(A)}$A();import{render as VM2}from"preact-render-to-string";import{h as vh}from"preact";function vU2(A){var Q,w,$="";if(typeof A=="string"||typeof A=="number")$+=A;else if(typeof A=="object")if(Array.isArray(A)){var B=A.length;for(Q=0;Q<B;Q++)A[Q]&&(w=vU2(A[Q]))&&($&&($+=" "),$+=w)}else for(w in A)A[w]&&($&&($+=" "),$+=w);return $}function Vl(){for(var A,Q,w=0,$="",B=arguments.length;w<B;w++)(A=arguments[w])&&(Q=vU2(A))&&($&&($+=" "),$+=Q);return $}var Opw=(A,Q)=>{let w=Array(A.length+Q.length);for(let $=0;$<A.length;$++)w[$]=A[$];for(let $=0;$<Q.length;$++)w[A.length+$]=Q[$];return w},fpw=(A,Q)=>({classGroupId:A,validator:Q}),mU2=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var CU2=[];var xpw=(A)=>{let Q=vpw(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:$}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return Rpw(Y);let Z=Y.split("-"),W=Z[0]===""&&Z.length>1?1:0;return uU2(Z,W,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let W=$[Y],K=w[Y];if(W){if(K)return Opw(K,W);return W}return K||CU2}return w[Y]||CU2}}},uU2=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let B=A[Q],X=w.nextPart.get(B);if(X){let K=uU2(A,Q+1,X);if(K)return K}let Y=w.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),W=Y.length;for(let K=0;K<W;K++){let U=Y[K];if(U.validator(Z))return U.classGroupId}return},Rpw=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),$=Q.slice(0,w);return $?"arbitrary.."+$:void 0})(),vpw=(A)=>{let{theme:Q,classGroups:w}=A;return Cpw(w,Q)},Cpw=(A,Q)=>{let w=mU2();for(let $ in A){let B=A[$];a7A(B,w,$,Q)}return w},a7A=(A,Q,w,$)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];hpw(Y,Q,w,$)}},hpw=(A,Q,w,$)=>{if(typeof A==="string"){Epw(A,Q,w);return}if(typeof A==="function"){gpw(A,Q,w,$);return}ypw(A,Q,w,$)},Epw=(A,Q,w)=>{let $=A===""?Q:cU2(Q,A);$.classGroupId=w},gpw=(A,Q,w,$)=>{if(Tpw(A)){a7A(A($),Q,w,$);return}if(Q.validators===null)Q.validators=[];Q.validators.push(fpw(w,A))},ypw=(A,Q,w,$)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,W]=B[Y];a7A(W,cU2(Q,Z),w,$)}},cU2=(A,Q)=>{let w=A,$=Q.split("-"),B=$.length;for(let X=0;X<B;X++){let Y=$[X],Z=w.nextPart.get(Y);if(!Z)Z=mU2(),w.nextPart.set(Y,Z);w=Z}return w},Tpw=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,Spw=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),$=Object.create(null),B=(X,Y)=>{if(w[X]=Y,Q++,Q>A)Q=0,$=w,w=Object.create(null)};return{get(X){let Y=w[X];if(Y!==void 0)return Y;if((Y=$[X])!==void 0)return B(X,Y),Y},set(X,Y){if(X in w)w[X]=Y;else B(X,Y)}}};var mpw=[],hU2=(A,Q,w,$,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:$,isExternal:B}),upw=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,$=(B)=>{let X=[],Y=0,Z=0,W=0,K,U=B.length;for(let I=0;I<U;I++){let F=B[I];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(W,I)),W=I+1;continue}if(F==="/"){K=I;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")Z--}let G=X.length===0?B:B.slice(W),D=G,z=!1;if(G.endsWith("!"))D=G.slice(0,-1),z=!0;else if(G.startsWith("!"))D=G.slice(1),z=!0;let V=K&&K>W?K-W:void 0;return hU2(X,z,D,V)};if(Q){let B=Q+":",X=$;$=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):hU2(mpw,!1,Y,void 0,!0)}if(w){let B=$;$=(X)=>w({className:X,parseClassName:B})}return $},cpw=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,$)=>{Q.set(w,1e6+$)}),(w)=>{let $=[],B=[];for(let X=0;X<w.length;X++){let Y=w[X],Z=Y[0]==="[",W=Q.has(Y);if(Z||W){if(B.length>0)B.sort(),$.push(...B),B=[];$.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),$.push(...B);return $}},ppw=(A)=>({cache:Spw(A.cacheSize),parseClassName:upw(A),sortModifiers:cpw(A),postfixLookupClassGroupIds:lpw(A),...xpw(A)}),lpw=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let $=0;$<w.length;$++)Q[w[$]]=!0;return Q},dpw=/\s+/,ipw=(A,Q)=>{let{parseClassName:w,getClassGroupId:$,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],W=A.trim().split(dpw),K="";for(let U=W.length-1;U>=0;U-=1){let G=W[U],{isExternal:D,modifiers:z,hasImportantModifier:V,baseClassName:I,maybePostfixModifierPosition:F}=w(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!F,k;if(_){let M=I.substring(0,F);k=$(M);let y=k&&Y[k]?$(I):void 0;if(y&&y!==k)k=y,_=!1}else k=$(I);if(!k){if(!_){K=G+(K.length>0?" "+K:K);continue}if(k=$(I),!k){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=z.length===0?"":z.length===1?z[0]:X(z).join(":"),f=V?b+"!":b,R=f+k;if(Z.indexOf(R)>-1)continue;Z.push(R);let v=B(k,_);for(let M=0;M<v.length;++M){let y=v[M];Z.push(f+y)}K=G+(K.length>0?" "+K:K)}return K},npw=(...A)=>{let Q=0,w,$,B="";while(Q<A.length)if(w=A[Q++]){if($=pU2(w))B&&(B+=" "),B+=$}return B},pU2=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let $=0;$<A.length;$++)if(A[$]){if(Q=pU2(A[$]))w&&(w+=" "),w+=Q}return w},EU2=(A,...Q)=>{let w,$,B,X,Y=(W)=>{let K=Q.reduce((U,G)=>G(U),A());return w=ppw(K),$=w.cache.get,B=w.cache.set,X=Z,Z(W)},Z=(W)=>{let K=$(W);if(K)return K;let U=ipw(W,w);return B(W,U),U};return X=Y,(...W)=>X(npw(...W))},rpw=[],F4=(A)=>{let Q=(w)=>w[A]||rpw;return Q.isThemeGetter=!0,Q},lU2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,dU2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,opw=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,spw=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,apw=/\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$/,tpw=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,epw=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,Alw=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,Jj=(A)=>opw.test(A),_6=(A)=>!!A&&!Number.isNaN(Number(A)),nV=(A)=>!!A&&Number.isInteger(Number(A)),o7A=(A)=>A.endsWith("%")&&_6(A.slice(0,-1)),Y_=(A)=>spw.test(A),iU2=()=>!0,Qlw=(A)=>apw.test(A)&&!tpw.test(A),t7A=()=>!1,wlw=(A)=>epw.test(A),$lw=(A)=>Alw.test(A),Blw=(A)=>!S2(A)&&!p2(A),Xlw=(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)),Ylw=(A)=>Vj(A,oU2,t7A),S2=(A)=>lU2.test(A),aC=(A)=>Vj(A,sU2,Qlw),gU2=(A)=>Vj(A,qlw,_6),Zlw=(A)=>Vj(A,tU2,iU2),Hlw=(A)=>Vj(A,aU2,t7A),yU2=(A)=>Vj(A,nU2,t7A),Wlw=(A)=>Vj(A,rU2,$lw),vF0=(A)=>Vj(A,eU2,wlw),p2=(A)=>dU2.test(A),Fw0=(A)=>tC(A,sU2),Klw=(A)=>tC(A,aU2),TU2=(A)=>tC(A,nU2),Ulw=(A)=>tC(A,oU2),Glw=(A)=>tC(A,rU2),CF0=(A)=>tC(A,eU2,!0),Dlw=(A)=>tC(A,tU2,!0),Vj=(A,Q,w)=>{let $=lU2.exec(A);if($){if($[1])return Q($[1]);return w($[2])}return!1},tC=(A,Q,w=!1)=>{let $=dU2.exec(A);if($){if($[1])return Q($[1]);return w}return!1},nU2=(A)=>A==="position"||A==="percentage",rU2=(A)=>A==="image"||A==="url",oU2=(A)=>A==="length"||A==="size"||A==="bg-size",sU2=(A)=>A==="length",qlw=(A)=>A==="number",aU2=(A)=>A==="family-name",tU2=(A)=>A==="number"||A==="weight",eU2=(A)=>A==="shadow";var SU2=()=>{let A=F4("color"),Q=F4("font"),w=F4("text"),$=F4("font-weight"),B=F4("tracking"),X=F4("leading"),Y=F4("breakpoint"),Z=F4("container"),W=F4("spacing"),K=F4("radius"),U=F4("shadow"),G=F4("inset-shadow"),D=F4("text-shadow"),z=F4("drop-shadow"),V=F4("blur"),I=F4("perspective"),F=F4("aspect"),_=F4("ease"),k=F4("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],f=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...f(),p2,S2],v=()=>["auto","hidden","clip","visible","scroll"],M=()=>["auto","contain","none"],y=()=>[p2,S2,W],S=()=>[Jj,"full","auto",...y()],l=()=>[nV,"none","subgrid",p2,S2],o=()=>["auto",{span:["full",nV,p2,S2]},nV,p2,S2],Z0=()=>[nV,"auto",p2,S2],d=()=>["auto","min","max","fr",p2,S2],j=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],E=()=>["start","end","center","stretch","center-safe","end-safe"],g=()=>["auto",...y()],n=()=>[Jj,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...y()],r=()=>[Jj,"screen","full","dvw","lvw","svw","min","max","fit",...y()],G0=()=>[Jj,"screen","full","lh","dvh","lvh","svh","min","max","fit",...y()],p=()=>[A,p2,S2],H0=()=>[...f(),TU2,yU2,{position:[p2,S2]}],V0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],Q0=()=>["auto","cover","contain",Ulw,Ylw,{size:[p2,S2]}],C0=()=>[o7A,Fw0,aC],m0=()=>["","none","full",K,p2,S2],I0=()=>["",_6,Fw0,aC],L0=()=>["solid","dashed","dotted","double"],j0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],E0=()=>[_6,o7A,TU2,yU2],P0=()=>["","none",V,p2,S2],M0=()=>["none",_6,p2,S2],O0=()=>["none",_6,p2,S2],f0=()=>[_6,p2,S2],S0=()=>[Jj,"full",...y()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Y_],breakpoint:[Y_],color:[iU2],container:[Y_],"drop-shadow":[Y_],ease:["in","out","in-out"],font:[Blw],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Y_],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Y_],shadow:[Y_],spacing:["px",_6],text:[Y_],"text-shadow":[Y_],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",Jj,S2,p2,F]}],container:["container"],"container-type":[{"@container":["","normal","size",p2,S2]}],"container-named":[Xlw],columns:[{columns:[_6,S2,p2,Z]}],"break-after":[{"break-after":b()}],"break-before":[{"break-before":b()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:R()}],overflow:[{overflow:v()}],"overflow-x":[{"overflow-x":v()}],"overflow-y":[{"overflow-y":v()}],overscroll:[{overscroll:M()}],"overscroll-x":[{"overscroll-x":M()}],"overscroll-y":[{"overscroll-y":M()}],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:[nV,"auto",p2,S2]}],basis:[{basis:[Jj,"full","auto",Z,...y()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[_6,Jj,"auto","initial","none",S2]}],grow:[{grow:["",_6,p2,S2]}],shrink:[{shrink:["",_6,p2,S2]}],order:[{order:[nV,"first","last","none",p2,S2]}],"grid-cols":[{"grid-cols":l()}],"col-start-end":[{col:o()}],"col-start":[{"col-start":Z0()}],"col-end":[{"col-end":Z0()}],"grid-rows":[{"grid-rows":l()}],"row-start-end":[{row:o()}],"row-start":[{"row-start":Z0()}],"row-end":[{"row-end":Z0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":d()}],"auto-rows":[{"auto-rows":d()}],gap:[{gap:y()}],"gap-x":[{"gap-x":y()}],"gap-y":[{"gap-y":y()}],"justify-content":[{justify:[...j(),"normal"]}],"justify-items":[{"justify-items":[...E(),"normal"]}],"justify-self":[{"justify-self":["auto",...E()]}],"align-content":[{content:["normal",...j()]}],"align-items":[{items:[...E(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...E(),{baseline:["","last"]}]}],"place-content":[{"place-content":j()}],"place-items":[{"place-items":[...E(),"baseline"]}],"place-self":[{"place-self":["auto",...E()]}],p:[{p:y()}],px:[{px:y()}],py:[{py:y()}],ps:[{ps:y()}],pe:[{pe:y()}],pbs:[{pbs:y()}],pbe:[{pbe:y()}],pt:[{pt:y()}],pr:[{pr:y()}],pb:[{pb:y()}],pl:[{pl:y()}],m:[{m:g()}],mx:[{mx:g()}],my:[{my:g()}],ms:[{ms:g()}],me:[{me:g()}],mbs:[{mbs:g()}],mbe:[{mbe:g()}],mt:[{mt:g()}],mr:[{mr:g()}],mb:[{mb:g()}],ml:[{ml:g()}],"space-x":[{"space-x":y()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":y()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...r()]}],"min-inline-size":[{"min-inline":["auto",...r()]}],"max-inline-size":[{"max-inline":["none",...r()]}],"block-size":[{block:["auto",...G0()]}],"min-block-size":[{"min-block":["auto",...G0()]}],"max-block-size":[{"max-block":["none",...G0()]}],w:[{w:[Z,"screen",...n()]}],"min-w":[{"min-w":[Z,"screen","none",...n()]}],"max-w":[{"max-w":[Z,"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,Fw0,aC]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[$,Dlw,Zlw]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",o7A,S2]}],"font-family":[{font:[Klw,Hlw,Q]}],"font-features":[{"font-features":[S2]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[B,p2,S2]}],"line-clamp":[{"line-clamp":[_6,"none",p2,gU2]}],leading:[{leading:[X,...y()]}],"list-image":[{"list-image":["none",p2,S2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",p2,S2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:p()}],"text-color":[{text:p()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...L0(),"wavy"]}],"text-decoration-thickness":[{decoration:[_6,"from-font","auto",p2,aC]}],"text-decoration-color":[{decoration:p()}],"underline-offset":[{"underline-offset":[_6,"auto",p2,S2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:y()}],"tab-size":[{tab:[nV,p2,S2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",p2,S2]}],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,S2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:H0()}],"bg-repeat":[{bg:V0()}],"bg-size":[{bg:Q0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},nV,p2,S2],radial:["",p2,S2],conic:[nV,p2,S2]},Glw,Wlw]}],"bg-color":[{bg:p()}],"gradient-from-pos":[{from:C0()}],"gradient-via-pos":[{via:C0()}],"gradient-to-pos":[{to:C0()}],"gradient-from":[{from:p()}],"gradient-via":[{via:p()}],"gradient-to":[{to:p()}],rounded:[{rounded:m0()}],"rounded-s":[{"rounded-s":m0()}],"rounded-e":[{"rounded-e":m0()}],"rounded-t":[{"rounded-t":m0()}],"rounded-r":[{"rounded-r":m0()}],"rounded-b":[{"rounded-b":m0()}],"rounded-l":[{"rounded-l":m0()}],"rounded-ss":[{"rounded-ss":m0()}],"rounded-se":[{"rounded-se":m0()}],"rounded-ee":[{"rounded-ee":m0()}],"rounded-es":[{"rounded-es":m0()}],"rounded-tl":[{"rounded-tl":m0()}],"rounded-tr":[{"rounded-tr":m0()}],"rounded-br":[{"rounded-br":m0()}],"rounded-bl":[{"rounded-bl":m0()}],"border-w":[{border:I0()}],"border-w-x":[{"border-x":I0()}],"border-w-y":[{"border-y":I0()}],"border-w-s":[{"border-s":I0()}],"border-w-e":[{"border-e":I0()}],"border-w-bs":[{"border-bs":I0()}],"border-w-be":[{"border-be":I0()}],"border-w-t":[{"border-t":I0()}],"border-w-r":[{"border-r":I0()}],"border-w-b":[{"border-b":I0()}],"border-w-l":[{"border-l":I0()}],"divide-x":[{"divide-x":I0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":I0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...L0(),"hidden","none"]}],"divide-style":[{divide:[...L0(),"hidden","none"]}],"border-color":[{border:p()}],"border-color-x":[{"border-x":p()}],"border-color-y":[{"border-y":p()}],"border-color-s":[{"border-s":p()}],"border-color-e":[{"border-e":p()}],"border-color-bs":[{"border-bs":p()}],"border-color-be":[{"border-be":p()}],"border-color-t":[{"border-t":p()}],"border-color-r":[{"border-r":p()}],"border-color-b":[{"border-b":p()}],"border-color-l":[{"border-l":p()}],"divide-color":[{divide:p()}],"outline-style":[{outline:[...L0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[_6,p2,S2]}],"outline-w":[{outline:["",_6,Fw0,aC]}],"outline-color":[{outline:p()}],shadow:[{shadow:["","none",U,CF0,vF0]}],"shadow-color":[{shadow:p()}],"inset-shadow":[{"inset-shadow":["none",G,CF0,vF0]}],"inset-shadow-color":[{"inset-shadow":p()}],"ring-w":[{ring:I0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:p()}],"ring-offset-w":[{"ring-offset":[_6,aC]}],"ring-offset-color":[{"ring-offset":p()}],"inset-ring-w":[{"inset-ring":I0()}],"inset-ring-color":[{"inset-ring":p()}],"text-shadow":[{"text-shadow":["none",D,CF0,vF0]}],"text-shadow-color":[{"text-shadow":p()}],opacity:[{opacity:[_6,p2,S2]}],"mix-blend":[{"mix-blend":[...j0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":j0()}],"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":[_6]}],"mask-image-linear-from-pos":[{"mask-linear-from":E0()}],"mask-image-linear-to-pos":[{"mask-linear-to":E0()}],"mask-image-linear-from-color":[{"mask-linear-from":p()}],"mask-image-linear-to-color":[{"mask-linear-to":p()}],"mask-image-t-from-pos":[{"mask-t-from":E0()}],"mask-image-t-to-pos":[{"mask-t-to":E0()}],"mask-image-t-from-color":[{"mask-t-from":p()}],"mask-image-t-to-color":[{"mask-t-to":p()}],"mask-image-r-from-pos":[{"mask-r-from":E0()}],"mask-image-r-to-pos":[{"mask-r-to":E0()}],"mask-image-r-from-color":[{"mask-r-from":p()}],"mask-image-r-to-color":[{"mask-r-to":p()}],"mask-image-b-from-pos":[{"mask-b-from":E0()}],"mask-image-b-to-pos":[{"mask-b-to":E0()}],"mask-image-b-from-color":[{"mask-b-from":p()}],"mask-image-b-to-color":[{"mask-b-to":p()}],"mask-image-l-from-pos":[{"mask-l-from":E0()}],"mask-image-l-to-pos":[{"mask-l-to":E0()}],"mask-image-l-from-color":[{"mask-l-from":p()}],"mask-image-l-to-color":[{"mask-l-to":p()}],"mask-image-x-from-pos":[{"mask-x-from":E0()}],"mask-image-x-to-pos":[{"mask-x-to":E0()}],"mask-image-x-from-color":[{"mask-x-from":p()}],"mask-image-x-to-color":[{"mask-x-to":p()}],"mask-image-y-from-pos":[{"mask-y-from":E0()}],"mask-image-y-to-pos":[{"mask-y-to":E0()}],"mask-image-y-from-color":[{"mask-y-from":p()}],"mask-image-y-to-color":[{"mask-y-to":p()}],"mask-image-radial":[{"mask-radial":[p2,S2]}],"mask-image-radial-from-pos":[{"mask-radial-from":E0()}],"mask-image-radial-to-pos":[{"mask-radial-to":E0()}],"mask-image-radial-from-color":[{"mask-radial-from":p()}],"mask-image-radial-to-color":[{"mask-radial-to":p()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":f()}],"mask-image-conic-pos":[{"mask-conic":[_6]}],"mask-image-conic-from-pos":[{"mask-conic-from":E0()}],"mask-image-conic-to-pos":[{"mask-conic-to":E0()}],"mask-image-conic-from-color":[{"mask-conic-from":p()}],"mask-image-conic-to-color":[{"mask-conic-to":p()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:H0()}],"mask-repeat":[{mask:V0()}],"mask-size":[{mask:Q0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",p2,S2]}],filter:[{filter:["","none",p2,S2]}],blur:[{blur:P0()}],brightness:[{brightness:[_6,p2,S2]}],contrast:[{contrast:[_6,p2,S2]}],"drop-shadow":[{"drop-shadow":["","none",z,CF0,vF0]}],"drop-shadow-color":[{"drop-shadow":p()}],grayscale:[{grayscale:["",_6,p2,S2]}],"hue-rotate":[{"hue-rotate":[_6,p2,S2]}],invert:[{invert:["",_6,p2,S2]}],saturate:[{saturate:[_6,p2,S2]}],sepia:[{sepia:["",_6,p2,S2]}],"backdrop-filter":[{"backdrop-filter":["","none",p2,S2]}],"backdrop-blur":[{"backdrop-blur":P0()}],"backdrop-brightness":[{"backdrop-brightness":[_6,p2,S2]}],"backdrop-contrast":[{"backdrop-contrast":[_6,p2,S2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",_6,p2,S2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[_6,p2,S2]}],"backdrop-invert":[{"backdrop-invert":["",_6,p2,S2]}],"backdrop-opacity":[{"backdrop-opacity":[_6,p2,S2]}],"backdrop-saturate":[{"backdrop-saturate":[_6,p2,S2]}],"backdrop-sepia":[{"backdrop-sepia":["",_6,p2,S2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":y()}],"border-spacing-x":[{"border-spacing-x":y()}],"border-spacing-y":[{"border-spacing-y":y()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",p2,S2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[_6,"initial",p2,S2]}],ease:[{ease:["linear","initial",_,p2,S2]}],delay:[{delay:[_6,p2,S2]}],animate:[{animate:["none",k,p2,S2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[I,p2,S2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:M0()}],"rotate-x":[{"rotate-x":M0()}],"rotate-y":[{"rotate-y":M0()}],"rotate-z":[{"rotate-z":M0()}],scale:[{scale:O0()}],"scale-x":[{"scale-x":O0()}],"scale-y":[{"scale-y":O0()}],"scale-z":[{"scale-z":O0()}],"scale-3d":["scale-3d"],skew:[{skew:f0()}],"skew-x":[{"skew-x":f0()}],"skew-y":[{"skew-y":f0()}],transform:[{transform:[p2,S2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:S0()}],"translate-x":[{"translate-x":S0()}],"translate-y":[{"translate-y":S0()}],"translate-z":[{"translate-z":S0()}],"translate-none":["translate-none"],zoom:[{zoom:[nV,p2,S2]}],accent:[{accent:p()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:p()}],"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,S2]}],"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":p()}],"scrollbar-track-color":[{"scrollbar-track":p()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":y()}],"scroll-mx":[{"scroll-mx":y()}],"scroll-my":[{"scroll-my":y()}],"scroll-ms":[{"scroll-ms":y()}],"scroll-me":[{"scroll-me":y()}],"scroll-mbs":[{"scroll-mbs":y()}],"scroll-mbe":[{"scroll-mbe":y()}],"scroll-mt":[{"scroll-mt":y()}],"scroll-mr":[{"scroll-mr":y()}],"scroll-mb":[{"scroll-mb":y()}],"scroll-ml":[{"scroll-ml":y()}],"scroll-p":[{"scroll-p":y()}],"scroll-px":[{"scroll-px":y()}],"scroll-py":[{"scroll-py":y()}],"scroll-ps":[{"scroll-ps":y()}],"scroll-pe":[{"scroll-pe":y()}],"scroll-pbs":[{"scroll-pbs":y()}],"scroll-pbe":[{"scroll-pbe":y()}],"scroll-pt":[{"scroll-pt":y()}],"scroll-pr":[{"scroll-pr":y()}],"scroll-pb":[{"scroll-pb":y()}],"scroll-pl":[{"scroll-pl":y()}],"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,S2]}],fill:[{fill:["none",...p()]}],"stroke-w":[{stroke:[_6,Fw0,aC,gU2]}],stroke:[{stroke:["none",...p()]}],"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"]}},zlw=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:$,extend:B={},override:X={}})=>{return Fl(A,"cacheSize",Q),Fl(A,"prefix",w),Fl(A,"experimentalParseClassName",$),hF0(A.theme,X.theme),hF0(A.classGroups,X.classGroups),hF0(A.conflictingClassGroups,X.conflictingClassGroups),hF0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),Fl(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),Fl(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),EF0(A.theme,B.theme),EF0(A.classGroups,B.classGroups),EF0(A.conflictingClassGroups,B.conflictingClassGroups),EF0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),s7A(A,B,"postfixLookupClassGroups"),s7A(A,B,"orderSensitiveModifiers"),A},Fl=(A,Q,w)=>{if(w!==void 0)A[Q]=w},hF0=(A,Q)=>{if(Q)for(let w in Q)Fl(A,w,Q[w])},EF0=(A,Q)=>{if(Q)for(let w in Q)s7A(A,Q,w)},s7A=(A,Q,w)=>{let $=Q[w];if($!==void 0)A[w]=A[w]?A[w].concat($):$},gF0=(A,...Q)=>typeof A==="function"?EU2(SU2,A,...Q):EU2(()=>zlw(SU2(),A),...Q);var Jlw=gF0({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 l2(...A){return Jlw(Vl(A))}var AG2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,QG2=Vl,f8=(A,Q)=>(w)=>{var $;if((Q===null||Q===void 0?void 0:Q.variants)==null)return QG2(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:B,defaultVariants:X}=Q,Y=Object.keys(B).map((K)=>{let U=w===null||w===void 0?void 0:w[K],G=X===null||X===void 0?void 0:X[K];if(U===null)return null;let D=AG2(U)||AG2(G);return B[K][D]}),Z=w&&Object.entries(w).reduce((K,U)=>{let[G,D]=U;if(D===void 0)return K;return K[G]=D,K},{}),W=Q===null||Q===void 0?void 0:($=Q.compoundVariants)===null||$===void 0?void 0:$.reduce((K,U)=>{let{class:G,className:D,...z}=U;return Object.entries(z).every((V)=>{let[I,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[I]):{...X,...Z}[I]===F})?[...K,G,D]:K},[]);return QG2(A,Y,W,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as e7A}from"preact/jsx-dev-runtime";var wG2=f8("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 A4A({variant:A,title:Q,children:w,className:$}){return e7A("div",{className:l2(wG2({variant:A}),$),role:"alert",children:[Q&&e7A("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),e7A("div",{className:l2(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 Vlw}from"preact/jsx-dev-runtime";var $G2=f8("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 eC({variant:A,size:Q,className:w,children:$,ssrOnClick:B,type:X="button",...Y}){return Vlw("button",{type:X,className:l2($G2({variant:A,size:Q}),w),...Y,...B&&{onclick:B},children:$},void 0,!1,void 0,this)}import{jsxDEV as Flw}from"preact/jsx-dev-runtime";var BG2=f8("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 I4({href:A,children:Q,variant:w,size:$,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return Flw("a",{href:A,className:l2(BG2({variant:w,size:$}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as yF0}from"preact/jsx-dev-runtime";var XG2=f8("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"}}),Ilw={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Il({variant:A,size:Q,className:w}){let $=Ilw[Q??"md"];return yF0("button",{onclick:"toggleTheme()",type:"button",className:l2(XG2({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:yF0("svg",{className:l2($,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[yF0("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),yF0("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 Q4A}from"preact/jsx-dev-runtime";var YG2=f8("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function TF0({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:$,children:B}){if(A.length===0&&!B)return null;let X=[...A].sort((Y,Z)=>Y.priority-Z.priority);return Q4A("ul",{className:l2(YG2({orientation:$}),Q),children:[X.map((Y)=>Q4A("li",{children:Q4A("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),B]},void 0,!0,void 0,this)}import{jsxDEV as cd8}from"preact/jsx-dev-runtime";import{jsxDEV as dd8}from"preact/jsx-dev-runtime";import{createContext as Llw,h as Nlw}from"preact";import{useContext as _lw}from"preact/hooks";var w4A=Llw(null);function Ll({headCollector:A,children:Q}){return Nlw(w4A.Provider,{value:A},Q)}function ZG2(){return _lw(w4A)}function Nw(A){let Q=ZG2();if(Q)Q.setHeadProps(A);return null}import{createContext as esw,h as Aaw}from"preact";import{useContext as Qaw}from"preact/hooks";Xa0();var Vz2=V1(Jz2(),1),asw=new CG0({gfm:!0,breaks:!0}),tsw={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 jXA(A,Q){let{imageRenderer:w}=Q??{},B=(w?new CG0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return w(X,Y,Z)??!1}}}):asw).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5791
|
+
`)}}$A();class _F0 extends p6{directorySync;constructor(A,Q,w){super(A,{schema:c7A,jobTypeName:"directory-export"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory export job",{jobId:Q,data:A});let $=Date.now();try{let B=await this.directorySync.exportEntitiesWithProgress(A.entityTypes,w,A.batchSize??100);return this.logger.debug("Directory export job completed",{jobId:Q,exported:B.exported,failed:B.failed,duration:Date.now()-$}),B}catch(B){throw this.logger.error("Directory export job failed",{jobId:Q,error:B}),B}}summarizeDataForLog(A){return{entityTypes:A.entityTypes??"all",batchSize:A.batchSize}}}$A();class bF0 extends p6{directorySync;constructor(A,Q,w){super(A,{schema:u7A,jobTypeName:"directory-import"});this.directorySync=w}async process(A,Q,w){this.logger.debug("Processing directory import job",{jobId:Q,data:A});let $=Date.now();try{let B=await this.directorySync.importEntitiesWithProgress(A.paths,w,A.batchSize??100);return this.logger.debug("Directory import job completed",{jobId:Q,imported:B.imported,skipped:B.skipped,failed:B.failed,quarantined:B.quarantined,duration:Date.now()-$}),B}catch(B){throw this.logger.error("Directory import job failed",{jobId:Q,error:B}),B}}summarizeDataForLog(A){return{pathCount:A.paths?.length??"all",batchSize:A.batchSize}}}$A();class kF0 extends p6{directorySync;context;constructor(A,Q,w){super(A,{schema:S7A,jobTypeName:"directory-sync"});this.context=Q,this.directorySync=w}async process(A,Q,w){let $=Date.now(),B=A.syncDirection??"both";this.logger.info("Starting directory sync job",{jobId:Q,operation:A.operation,syncDirection:B});let X={imported:0,skipped:0,failed:0,quarantined:0,quarantinedFiles:[],errors:[],jobIds:[]},Y={exported:0,failed:0,errors:[]};if(B!=="export")if(await w.report({progress:10,message:"Scanning directory for changes"}),X=await this.importWithProgress(A.paths,w),B==="import")await this.waitForImportJobs(X.jobIds,w),await w.report({progress:100,message:`Import complete: ${X.imported} imported`});else await w.report({progress:50,message:`Imported ${X.imported} entities`}),await this.waitForImportJobs(X.jobIds,w),await w.report({progress:56,message:"Processing complete, starting export"});if(B!=="import"){let W=B==="export"?10:60;await w.report({progress:W,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message:B==="export"?`Export complete: ${Y.exported} exported`:`Sync complete: ${X.imported} imported, ${Y.exported} exported`})}let Z=Date.now()-$;return this.logger.info("Directory sync job completed",{jobId:Q,duration:Z,imported:X.imported,exported:Y.exported}),{import:X,export:Y,duration:Z}}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,$=300000,B=500,X=Date.now(),Y=async()=>{let W=(await Promise.all(A.map((U)=>w.getAsyncJobStatus(U)))).filter((U)=>U&&(U.status==="completed"||U.status==="failed")).length;if(W===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-X>$){this.logger.warn(`Timeout waiting for import jobs (${W}/${A.length} completed)`);return}let K=Math.round(W/A.length*100);return await Q.report({progress:50+Math.round(K*0.05),message:`Processing ${W}/${A.length} entities`}),await new Promise((U)=>setTimeout(U,B)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}$A();class PF0 extends p6{context;directorySync;gitSync;constructor(A,Q,w,$){super(A,{schema:m7A,jobTypeName:"sync-request"});this.context=Q,this.directorySync=w,this.gitSync=$}async process(A,Q,w){await w.report({progress:5,message:"Pulling latest content from git"});let $=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(!$)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: ${$.importOperationsCount} import jobs for ${$.totalFiles} files`}),acw($)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function acw(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}$A();class MF0 extends p6{context;constructor(A,Q,w){super(A,{schema:LF0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let $=LF0.parse(A);this.logger.info("Processing entity deletion for removed file",{entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}),await w.report({progress:0,total:1,message:`Deleting ${$.entityType}:${$.entityId}`});try{let B=await this.context.entityService.deleteEntity({entityType:$.entityType,id:$.entityId});if(B)this.logger.info("Successfully deleted entity for removed file",{entityId:$.entityId,entityType:$.entityType});else this.logger.warn("Entity not found in database",{entityId:$.entityId,entityType:$.entityType});return await w.report({progress:1,total:1,message:`Deleted ${$.entityType}:${$.entityId}`}),{deleted:B,entityId:$.entityId,entityType:$.entityType,filePath:$.filePath}}catch(B){throw this.logger.error("Failed to delete entity",{entityId:$.entityId,entityType:$.entityType,error:B}),B}}summarizeDataForLog(A){return{entityId:A.entityId,entityType:A.entityType,filePath:A.filePath}}}$A();b0();var tcw=H.object({});class jF0 extends p6{directorySync;constructor(A,Q){super(A,{schema:tcw,jobTypeName:"directory-cleanup"});this.directorySync=Q}async process(A,Q,w){await w.report({progress:0,message:"Removing orphaned entities"});let $=await this.directorySync.removeOrphanedEntities();return await w.report({progress:100,message:`Cleanup complete: ${$.deleted} orphans removed`}),$}}$A();rY();Q4();g$();b0();rY();import{readFile as ecw,writeFile as Apw}from"fs/promises";var Qpw=p7A,wpw=H.record(H.string(),H.unknown());class OF0 extends p6{context;fetcher;constructor(A,Q,w=z3){super(Q,{schema:Qpw,jobTypeName:"cover-image-convert"});this.context=A,this.fetcher=w}async process(A,Q,w){let{filePath:$,sourceUrl:B,postTitle:X,postSlug:Y,customAlt:Z}=A;this.logger.debug("Starting image conversion job",{jobId:Q,filePath:$,sourceUrl:B,postSlug:Y});try{await this.reportProgress(w,{progress:kw.INIT,message:`Reading file: ${$}`});let W;try{W=await ecw($,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:$,error:lA(F)}),J5.failure(F)}let K;try{K=M$(W)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:$,error:lA(F)}),J5.failure(F)}let U=wpw.safeParse(K.frontmatter),G=U.success?U.data:{};if(G.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:kw.FETCH,message:"Checking for existing image"});let D=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),z;if(D[0])z=D[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:z}),await this.reportProgress(w,{progress:kw.EXTRACT,message:`Reusing existing image: ${z}`});else{await this.reportProgress(w,{progress:kw.PROCESS,message:`Fetching image from ${B}`});let F;try{F=await this.fetcher(B)}catch(v){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:lA(v)}),J5.failure(v)}await this.reportProgress(w,{progress:kw.GENERATE,message:"Creating image entity"});let{base64:_}=IP(F),k=ER(_),b=LP(_);if(!k||!b)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),J5.failure(Error("Could not detect image format or dimensions"));z=`${Y}-cover`;let f=`Cover image for ${X}`,R=Z??f;await this.context.entityService.createEntity({entity:{id:z,entityType:"image",content:F,metadata:{title:f,alt:R,format:k,width:b.width,height:b.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:z,sourceUrl:B}),await this.reportProgress(w,{progress:kw.EXTRACT,message:`Created image: ${z}`})}await this.reportProgress(w,{progress:kw.SAVE,message:"Updating file"});let V={...G};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=z;let I=wR(V,K.content);try{await Apw($,I,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:$,error:lA(F)}),J5.failure(F)}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:z,sourceUrl:B}),{success:!0,imageId:z}}catch(W){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:lA(W)}),J5.failure(W)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}$A();rY();g$();import{readFile as $pw,writeFile as Bpw}from"fs/promises";class fF0 extends p6{converter;constructor(A,Q,w=z3){super(Q,{schema:l7A,jobTypeName:"inline-image-convert"});this.converter=new $w0(A.entityService,Q,w)}async process(A,Q,w){let{filePath:$,postSlug:B}=A;this.logger.debug("Starting inline image conversion job",{jobId:Q,filePath:$,postSlug:B});try{await this.reportProgress(w,{progress:kw.INIT,message:`Reading file: ${$}`});let X;try{X=await $pw($,"utf-8")}catch(W){let K=lA(W);return this.logger.error("Failed to read file",{filePath:$,error:K}),{success:!1,error:K}}await this.reportProgress(w,{progress:kw.FETCH,message:"Detecting inline images"});let Y=this.converter.detectInlineImages(X,B);if(Y.length===0)return this.logger.debug("No inline images to convert",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"No images to convert"}),{success:!0,skipped:!0,convertedCount:0};this.logger.debug("Found inline images to convert",{filePath:$,count:Y.length}),await this.reportProgress(w,{progress:kw.PROCESS,message:`Converting ${Y.length} images`});let Z=await this.converter.convert(X,B);if(!Z.converted)return this.logger.debug("No images were converted",{filePath:$}),await this.reportProgress(w,{progress:kw.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:kw.SAVE,message:"Writing updated file"});try{await Bpw($,Z.content,"utf-8")}catch(W){let K=lA(W);return this.logger.error("Failed to write file",{filePath:$,error:K}),{success:!1,error:K}}return await this.reportProgress(w,{progress:kw.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=lA(X);return this.logger.error("Inline image conversion job failed",{jobId:Q,filePath:$,error:Y}),{success:!1,error:Y}}}summarizeDataForLog(A){return{filePath:A.filePath,postSlug:A.postSlug}}}function UU2(A,Q,w){let $=(B)=>w.child(B);A.jobs.registerHandler("directory-sync",new kF0($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new _F0($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new bF0($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new MF0($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new jF0($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new OF0(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new fF0(A,$("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}$A();b0();import{unlink as Xpw,access as Ypw}from"fs/promises";var Zpw=H.record(H.string(),H.unknown());function GU2(A,Q,w,$){let{subscribe:B}=A.messaging,{entityService:X}=A;B("entity:created",async(Y)=>{let{entity:Z}=Y.payload;try{await Q.fileOps.writeEntity(Z),w.debug("Auto-exported created entity",{id:Z.id,entityType:Z.entityType})}catch(W){w.error("Auto-export FAILED for created entity",{id:Z.id,entityType:Z.entityType,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),B("entity:updated",async(Y)=>{let{entityType:Z,entityId:W}=Y.payload;try{let K=await X.getEntity({entityType:Z,id:W});if(!K)return w.debug("Entity not found in DB, skipping export",{entityType:Z,entityId:W}),{success:!1};await Q.fileOps.writeEntity(K),w.debug("Auto-exported updated entity",{id:K.id,entityType:K.entityType})}catch(K){w.error("Auto-export FAILED for updated entity",{entityType:Z,entityId:W,error:K instanceof Error?K.message:String(K),stack:K instanceof Error?K.stack:void 0})}return{success:!0}}),B("entity:deleted",async(Y)=>{let{entityId:Z,entityType:W}=Y.payload,K=Q.fileOps.getFilePath(Z,W);if(await Ypw(K).then(()=>!0,()=>!1))await Xpw(K),w.debug("Auto-deleted entity file",{id:Z,entityType:W,path:K});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:$})}function DU2(A,Q,w){Q.setJobQueueCallback(async($)=>{let B=[{type:$.type,data:Zpw.parse($.data)}];return A.jobs.enqueueBatch(B,{priority:5,source:"directory-sync-watcher",rootJobId:kY(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}$A();import{readdir as JU2,mkdir as Wpw,copyFile as Kpw}from"fs/promises";import{join as zU2,resolve as d7A}from"path";import{join as Hpw}from"path";async function qU2(A){if(!await O9(Hpw(A,".git")))return!1;try{return await sq(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function Upw(A,Q){if(!await O9(A))return!0;if((await JU2(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await qU2(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function VU2(A,Q){let w=await JU2(A,{withFileTypes:!0});for(let $ of w){let B=zU2(A,$.name),X=zU2(Q,$.name);if($.isDirectory()){if(!await O9(X))await Wpw(X,{recursive:!0});await VU2(B,X)}else await Kpw(B,X)}}async function FU2(A,Q,w){let $=d7A(process.cwd(),A);w=w?d7A(w):d7A(process.cwd(),"seed-content");let B=await Upw($,Q);if(B&&await O9(w))Q.debug("Copying seed content to brain-data directory"),await VU2(w,$),Q.debug("Seed content copied successfully");else if(B)Q.debug("No seed content directory found, starting with empty brain-data");else Q.debug("brain-data directory not empty, skipping seed content")}function IU2(A,Q,w,$,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if(w.seedContent){let W=w.syncPath??A.dataDir;await FU2(W,$,w.seedContentPath)}try{if(B){$.debug("Git enabled \u2014 pulling before import");let K=await B.pull();if(K.files.length>0)$.info("Pulled changes from remote",{filesChanged:K.files.length})}$.debug("Starting initial sync");let W=await Z.sync();$.debug("Initial sync completed",{imported:W.import.imported,failed:W.import.failed,duration:W.duration}),await A.messaging.send({type:YR.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(W){$.error("Initial sync failed",W),await A.messaging.send({type:YR.initialSyncCompleted,payload:{success:!1,error:lA(W)},...{broadcast:!0}})}};A.messaging.subscribe(YR.pluginsRegistered,async()=>{return $.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class i7A{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 n7A{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 LU2(A,Q,w,$){let B=new n7A(()=>{Q.withLock(async()=>{try{await Q.commit(),await Q.push()}catch(Z){$.error("Git auto-commit failed",{error:Z})}})},w),X=["entity:created","entity:updated","entity:deleted"],Y=[];for(let Z of X){let W=A.subscribe(Z,async()=>{return B.trigger(),{success:!0}});Y.push(W)}return()=>{B.dispose();for(let Z of Y)Z()}}function NU2(A,Q,w,$,B){if($<=0)return()=>{};let X=$*60*1000,Y=!1,Z=async()=>{if(Y)return;Y=!0;try{let{files:K,result:U}=await A.withLock(async()=>{let G=await A.pull();if(G.files.length===0)return{files:[],result:null};let D=await Q.queueSyncBatch(w,"periodic-sync");return{files:G.files,result:D}});if(K.length>0)B.info("Periodic sync: pulled changes",{filesChanged:K.length});if(U)B.debug("Periodic sync: queued imports",{importOperations:U.importOperationsCount,totalFiles:U.totalFiles})}catch(K){B.error("Periodic git sync failed",{error:K})}finally{Y=!1}},W=setInterval(()=>{Z()},X);return B.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(W)}}import{spawnSync as bU2}from"child_process";import{cpSync as Gpw,existsSync as _U2,mkdirSync as Dpw,mkdtempSync as qpw,rmSync as zpw}from"fs";import{tmpdir as Jpw}from"os";import{fileURLToPath as Vpw}from"url";import{join as Fpw,resolve as Ipw}from"path";function zj(A,Q){let w=bU2("git",Q,{cwd:A,stdio:"pipe"});if(w.status!==0){let $=w.stderr.toString().trim(),B=w.stdout.toString().trim();throw Error($||B||`git ${Q.join(" ")} failed`)}}function Lpw(A){return A.startsWith("file://")}function Npw(A){return Vpw(A)}function _pw(A,Q){return bU2("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function kU2(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!Lpw(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=Npw(A.gitUrl),$=Ipw(A.seedContentPath);if(!_U2($))throw Error(`Seed content path not found: ${$}`);if(!_U2(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),Dpw(w,{recursive:!0}),zj(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(_pw(w,Q)){A.logger.debug("Content remote already initialized",{remotePath:w,branch:Q});return}A.logger.debug("Seeding local content remote",{remotePath:w,seedPath:$,branch:Q});let B=qpw(Fpw(Jpw(),"directory-sync-seed-"));try{zj(B,["init",`--initial-branch=${Q}`]),zj(B,["config","user.name",A.authorName??"Brain"]),zj(B,["config","user.email",A.authorEmail??"brain@localhost"]),Gpw($,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),zj(B,["add","."]),zj(B,["commit","-m","seed content remote"]),zj(B,["remote","add","origin",A.gitUrl]),zj(B,["push","-u","origin",Q])}finally{zpw(B,{recursive:!0,force:!0})}}function PU2(A,Q,w,$,B,X){let{subscribe:Y}=A.messaging;Y("entity:export:request",async(Z)=>{try{return{success:!0,data:await Q().exportEntities(Z.payload.entityTypes)}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Export failed"}}}),Y("entity:import:request",async(Z)=>{try{let W=Q(),K=Z.payload.paths,U=await W.importEntities(K);if(K&&K.length>0)await W.removeOrphanedEntities();return{success:!0,data:U}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let W=await Q().getStatus();return{success:!0,data:{syncPath:W.syncPath,isInitialized:W.exists,watchEnabled:W.watching,lastSync:W.lastSync?.toISOString()??null,totalFiles:W.stats.totalFiles,byEntityType:W.stats.byEntityType,git:await bpw(X?.(),$)}}}catch(Z){return{success:!1,error:Z instanceof Error?Z.message:"Status check failed"}}}),Y("sync:configure:request",async(Z)=>{try{return await w({syncPath:Z.payload.syncPath}),{success:!0,data:{syncPath:Z.payload.syncPath,configured:!0}}}catch(W){return{success:!1,error:W instanceof Error?W.message:"Configuration failed"}}}),Y("git-sync:get-repo-info",async()=>{if(!B?.repo)return{success:!1,error:"Git not configured"};return{success:!0,data:{repo:B.repo,branch:B.branch??"main"}}}),$.debug("Registered message handlers")}async function bpw(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}}$A();b0();$A();b0();function MU2(A,Q){return j$(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",H.object({entityType:H.string().describe("Entity type (e.g. post, note, link)"),id:H.string().describe("Entity ID"),sha:H.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:H.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let $=`${w.entityType}/${w.id}.md`;try{if(w.sha){let X=await Q.show(w.sha,$);return Z7({sha:w.sha,entityType:w.entityType,id:w.id,content:X},`Content at ${w.sha.slice(0,7)}`)}let B=await Q.log($,w.limit);if(B.length===0)return Z7({commits:[]},`No history found for ${w.entityType}/${w.id}`);return Z7({commits:B,entityType:w.entityType,id:w.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return TX(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function jU2(A,Q,w,$){let B=[j$(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.",H.object({}),async(X,Y)=>{try{let Z=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,W={interfaceType:Y.interfaceType,channelId:Y.channelId};if($){let U=await Q.jobs.enqueue({type:"sync-request",data:{source:Z,interfaceType:W.interfaceType,channelId:W.channelId},toolContext:Y});return Z7({jobId:U,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let K=await A.queueSyncBatch(Q,Z,W);if(!K)return Z7({gitPulled:!1},"No files to sync");return Z7({batchId:K.batchId,importOperations:K.importOperationsCount,totalFiles:K.totalFiles,gitPulled:!1},`Sync started: ${K.importOperationsCount} import jobs queued for ${K.totalFiles} files`)}catch(Z){return TX(Z instanceof Error?Z.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),j$(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.",H.object({}),async()=>{try{let X=await A.getStatus(),Y={syncPath:X.syncPath,lastSync:X.lastSync?.toISOString(),watching:X.watching};if($){let Z=await $.getStatus();Y.git={isRepo:Z.isRepo,branch:Z.branch,hasChanges:Z.hasChanges,ahead:Z.ahead,behind:Z.behind,remote:Z.remote}}return Z7(Y)}catch(X){return TX(X instanceof Error?X.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if($)B.push(MU2(w,$));return B}var OU2={name:"@brains/directory-sync",version:"0.2.0-alpha.181",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 r7A extends Rw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",OU2,A,Jw0)}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:Vw0,basePrompt:"",formatter:new NF0,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new Bw0({syncPath:$,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:$})}catch(Y){throw this.logger.error("Failed to initialize directory",Y),Y}await this.registerJobHandlers(A);let B=this.requireDirectorySync();if(GU2(A,B,this.logger,this.config.entityTypes),this.config.autoSync)DU2(A,B,this.config.syncPath??A.dataDir);let X=this.config.git!==void 0&&(this.config.git.repo!==void 0||this.config.git.gitUrl!==void 0);if(this.config.git&&!X)this.logger.debug("Git block present but no repo/gitUrl configured \u2014 git sync disabled");if(X&&this.config.git){await kU2({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 T7A({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 PF0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(LU2(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(NU2(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)IU2(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);PU2(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return jU2(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 Bw0({...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){UU2(A,this.requireDirectorySync(),this.logger)}}function sC(A={}){return new r7A(A)}b0();var xF0="email:send",fU2=H.strictObject({to:H.string().email(),subject:H.string().min(1),text:H.string().min(1),html:H.string().min(1).optional(),sensitivity:H.enum(["normal","secret"]).default("normal")});$A();b0();var xU2={name:"@brains/email-resend",version:"0.2.0-alpha.181",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 Mpw=H.object({apiKey:H.string().min(1).optional(),from:H.string().min(1).optional()}),jpw=H.looseObject({id:H.string().optional()});class RU2 extends Rw{fetchImpl;constructor(A={},Q={}){super("email-resend",xU2,A,Mpw);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(xF0,async(w)=>{let $=fU2.parse(w.payload);try{return{success:!0,data:await this.sendWithResend($)}}catch(B){if($.sensitivity==="secret")Q.warn("Email delivery failed for a secret message");else Q.warn("Email delivery failed",{to:$.to,subject:$.subject,error:B instanceof Error?B.message:String(B)});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 $=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(!$.ok)throw Error("Resend email request failed");let B=jpw.parse(await $.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function RF0(A={}){return new RU2(A)}$A();import{render as VM2}from"preact-render-to-string";import{h as vh}from"preact";function vU2(A){var Q,w,$="";if(typeof A=="string"||typeof A=="number")$+=A;else if(typeof A=="object")if(Array.isArray(A)){var B=A.length;for(Q=0;Q<B;Q++)A[Q]&&(w=vU2(A[Q]))&&($&&($+=" "),$+=w)}else for(w in A)A[w]&&($&&($+=" "),$+=w);return $}function Vl(){for(var A,Q,w=0,$="",B=arguments.length;w<B;w++)(A=arguments[w])&&(Q=vU2(A))&&($&&($+=" "),$+=Q);return $}var Opw=(A,Q)=>{let w=Array(A.length+Q.length);for(let $=0;$<A.length;$++)w[$]=A[$];for(let $=0;$<Q.length;$++)w[A.length+$]=Q[$];return w},fpw=(A,Q)=>({classGroupId:A,validator:Q}),mU2=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var CU2=[];var xpw=(A)=>{let Q=vpw(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:$}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return Rpw(Y);let Z=Y.split("-"),W=Z[0]===""&&Z.length>1?1:0;return uU2(Z,W,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let W=$[Y],K=w[Y];if(W){if(K)return Opw(K,W);return W}return K||CU2}return w[Y]||CU2}}},uU2=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let B=A[Q],X=w.nextPart.get(B);if(X){let K=uU2(A,Q+1,X);if(K)return K}let Y=w.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),W=Y.length;for(let K=0;K<W;K++){let U=Y[K];if(U.validator(Z))return U.classGroupId}return},Rpw=(A)=>A.slice(1,-1).indexOf(":")===-1?void 0:(()=>{let Q=A.slice(1,-1),w=Q.indexOf(":"),$=Q.slice(0,w);return $?"arbitrary.."+$:void 0})(),vpw=(A)=>{let{theme:Q,classGroups:w}=A;return Cpw(w,Q)},Cpw=(A,Q)=>{let w=mU2();for(let $ in A){let B=A[$];a7A(B,w,$,Q)}return w},a7A=(A,Q,w,$)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];hpw(Y,Q,w,$)}},hpw=(A,Q,w,$)=>{if(typeof A==="string"){Epw(A,Q,w);return}if(typeof A==="function"){gpw(A,Q,w,$);return}ypw(A,Q,w,$)},Epw=(A,Q,w)=>{let $=A===""?Q:cU2(Q,A);$.classGroupId=w},gpw=(A,Q,w,$)=>{if(Tpw(A)){a7A(A($),Q,w,$);return}if(Q.validators===null)Q.validators=[];Q.validators.push(fpw(w,A))},ypw=(A,Q,w,$)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,W]=B[Y];a7A(W,cU2(Q,Z),w,$)}},cU2=(A,Q)=>{let w=A,$=Q.split("-"),B=$.length;for(let X=0;X<B;X++){let Y=$[X],Z=w.nextPart.get(Y);if(!Z)Z=mU2(),w.nextPart.set(Y,Z);w=Z}return w},Tpw=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,Spw=(A)=>{if(A<1)return{get:()=>{return},set:()=>{}};let Q=0,w=Object.create(null),$=Object.create(null),B=(X,Y)=>{if(w[X]=Y,Q++,Q>A)Q=0,$=w,w=Object.create(null)};return{get(X){let Y=w[X];if(Y!==void 0)return Y;if((Y=$[X])!==void 0)return B(X,Y),Y},set(X,Y){if(X in w)w[X]=Y;else B(X,Y)}}};var mpw=[],hU2=(A,Q,w,$,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:$,isExternal:B}),upw=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,$=(B)=>{let X=[],Y=0,Z=0,W=0,K,U=B.length;for(let I=0;I<U;I++){let F=B[I];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(W,I)),W=I+1;continue}if(F==="/"){K=I;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")Z--}let G=X.length===0?B:B.slice(W),D=G,z=!1;if(G.endsWith("!"))D=G.slice(0,-1),z=!0;else if(G.startsWith("!"))D=G.slice(1),z=!0;let V=K&&K>W?K-W:void 0;return hU2(X,z,D,V)};if(Q){let B=Q+":",X=$;$=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):hU2(mpw,!1,Y,void 0,!0)}if(w){let B=$;$=(X)=>w({className:X,parseClassName:B})}return $},cpw=(A)=>{let Q=new Map;return A.orderSensitiveModifiers.forEach((w,$)=>{Q.set(w,1e6+$)}),(w)=>{let $=[],B=[];for(let X=0;X<w.length;X++){let Y=w[X],Z=Y[0]==="[",W=Q.has(Y);if(Z||W){if(B.length>0)B.sort(),$.push(...B),B=[];$.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),$.push(...B);return $}},ppw=(A)=>({cache:Spw(A.cacheSize),parseClassName:upw(A),sortModifiers:cpw(A),postfixLookupClassGroupIds:lpw(A),...xpw(A)}),lpw=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let $=0;$<w.length;$++)Q[w[$]]=!0;return Q},dpw=/\s+/,ipw=(A,Q)=>{let{parseClassName:w,getClassGroupId:$,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],W=A.trim().split(dpw),K="";for(let U=W.length-1;U>=0;U-=1){let G=W[U],{isExternal:D,modifiers:z,hasImportantModifier:V,baseClassName:I,maybePostfixModifierPosition:F}=w(G);if(D){K=G+(K.length>0?" "+K:K);continue}let _=!!F,k;if(_){let M=I.substring(0,F);k=$(M);let y=k&&Y[k]?$(I):void 0;if(y&&y!==k)k=y,_=!1}else k=$(I);if(!k){if(!_){K=G+(K.length>0?" "+K:K);continue}if(k=$(I),!k){K=G+(K.length>0?" "+K:K);continue}_=!1}let b=z.length===0?"":z.length===1?z[0]:X(z).join(":"),f=V?b+"!":b,R=f+k;if(Z.indexOf(R)>-1)continue;Z.push(R);let v=B(k,_);for(let M=0;M<v.length;++M){let y=v[M];Z.push(f+y)}K=G+(K.length>0?" "+K:K)}return K},npw=(...A)=>{let Q=0,w,$,B="";while(Q<A.length)if(w=A[Q++]){if($=pU2(w))B&&(B+=" "),B+=$}return B},pU2=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let $=0;$<A.length;$++)if(A[$]){if(Q=pU2(A[$]))w&&(w+=" "),w+=Q}return w},EU2=(A,...Q)=>{let w,$,B,X,Y=(W)=>{let K=Q.reduce((U,G)=>G(U),A());return w=ppw(K),$=w.cache.get,B=w.cache.set,X=Z,Z(W)},Z=(W)=>{let K=$(W);if(K)return K;let U=ipw(W,w);return B(W,U),U};return X=Y,(...W)=>X(npw(...W))},rpw=[],F4=(A)=>{let Q=(w)=>w[A]||rpw;return Q.isThemeGetter=!0,Q},lU2=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,dU2=/^\((?:(\w[\w-]*):)?(.+)\)$/i,opw=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,spw=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,apw=/\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$/,tpw=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,epw=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,Alw=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,Jj=(A)=>opw.test(A),_6=(A)=>!!A&&!Number.isNaN(Number(A)),nV=(A)=>!!A&&Number.isInteger(Number(A)),o7A=(A)=>A.endsWith("%")&&_6(A.slice(0,-1)),Y_=(A)=>spw.test(A),iU2=()=>!0,Qlw=(A)=>apw.test(A)&&!tpw.test(A),t7A=()=>!1,wlw=(A)=>epw.test(A),$lw=(A)=>Alw.test(A),Blw=(A)=>!S2(A)&&!p2(A),Xlw=(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)),Ylw=(A)=>Vj(A,oU2,t7A),S2=(A)=>lU2.test(A),aC=(A)=>Vj(A,sU2,Qlw),gU2=(A)=>Vj(A,qlw,_6),Zlw=(A)=>Vj(A,tU2,iU2),Hlw=(A)=>Vj(A,aU2,t7A),yU2=(A)=>Vj(A,nU2,t7A),Wlw=(A)=>Vj(A,rU2,$lw),vF0=(A)=>Vj(A,eU2,wlw),p2=(A)=>dU2.test(A),Fw0=(A)=>tC(A,sU2),Klw=(A)=>tC(A,aU2),TU2=(A)=>tC(A,nU2),Ulw=(A)=>tC(A,oU2),Glw=(A)=>tC(A,rU2),CF0=(A)=>tC(A,eU2,!0),Dlw=(A)=>tC(A,tU2,!0),Vj=(A,Q,w)=>{let $=lU2.exec(A);if($){if($[1])return Q($[1]);return w($[2])}return!1},tC=(A,Q,w=!1)=>{let $=dU2.exec(A);if($){if($[1])return Q($[1]);return w}return!1},nU2=(A)=>A==="position"||A==="percentage",rU2=(A)=>A==="image"||A==="url",oU2=(A)=>A==="length"||A==="size"||A==="bg-size",sU2=(A)=>A==="length",qlw=(A)=>A==="number",aU2=(A)=>A==="family-name",tU2=(A)=>A==="number"||A==="weight",eU2=(A)=>A==="shadow";var SU2=()=>{let A=F4("color"),Q=F4("font"),w=F4("text"),$=F4("font-weight"),B=F4("tracking"),X=F4("leading"),Y=F4("breakpoint"),Z=F4("container"),W=F4("spacing"),K=F4("radius"),U=F4("shadow"),G=F4("inset-shadow"),D=F4("text-shadow"),z=F4("drop-shadow"),V=F4("blur"),I=F4("perspective"),F=F4("aspect"),_=F4("ease"),k=F4("animate"),b=()=>["auto","avoid","all","avoid-page","page","left","right","column"],f=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...f(),p2,S2],v=()=>["auto","hidden","clip","visible","scroll"],M=()=>["auto","contain","none"],y=()=>[p2,S2,W],S=()=>[Jj,"full","auto",...y()],l=()=>[nV,"none","subgrid",p2,S2],o=()=>["auto",{span:["full",nV,p2,S2]},nV,p2,S2],Z0=()=>[nV,"auto",p2,S2],d=()=>["auto","min","max","fr",p2,S2],j=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],E=()=>["start","end","center","stretch","center-safe","end-safe"],g=()=>["auto",...y()],n=()=>[Jj,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...y()],r=()=>[Jj,"screen","full","dvw","lvw","svw","min","max","fit",...y()],G0=()=>[Jj,"screen","full","lh","dvh","lvh","svh","min","max","fit",...y()],p=()=>[A,p2,S2],H0=()=>[...f(),TU2,yU2,{position:[p2,S2]}],V0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],Q0=()=>["auto","cover","contain",Ulw,Ylw,{size:[p2,S2]}],C0=()=>[o7A,Fw0,aC],m0=()=>["","none","full",K,p2,S2],I0=()=>["",_6,Fw0,aC],L0=()=>["solid","dashed","dotted","double"],j0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],E0=()=>[_6,o7A,TU2,yU2],P0=()=>["","none",V,p2,S2],M0=()=>["none",_6,p2,S2],O0=()=>["none",_6,p2,S2],f0=()=>[_6,p2,S2],S0=()=>[Jj,"full",...y()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[Y_],breakpoint:[Y_],color:[iU2],container:[Y_],"drop-shadow":[Y_],ease:["in","out","in-out"],font:[Blw],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[Y_],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[Y_],shadow:[Y_],spacing:["px",_6],text:[Y_],"text-shadow":[Y_],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",Jj,S2,p2,F]}],container:["container"],"container-type":[{"@container":["","normal","size",p2,S2]}],"container-named":[Xlw],columns:[{columns:[_6,S2,p2,Z]}],"break-after":[{"break-after":b()}],"break-before":[{"break-before":b()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:R()}],overflow:[{overflow:v()}],"overflow-x":[{"overflow-x":v()}],"overflow-y":[{"overflow-y":v()}],overscroll:[{overscroll:M()}],"overscroll-x":[{"overscroll-x":M()}],"overscroll-y":[{"overscroll-y":M()}],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:[nV,"auto",p2,S2]}],basis:[{basis:[Jj,"full","auto",Z,...y()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[_6,Jj,"auto","initial","none",S2]}],grow:[{grow:["",_6,p2,S2]}],shrink:[{shrink:["",_6,p2,S2]}],order:[{order:[nV,"first","last","none",p2,S2]}],"grid-cols":[{"grid-cols":l()}],"col-start-end":[{col:o()}],"col-start":[{"col-start":Z0()}],"col-end":[{"col-end":Z0()}],"grid-rows":[{"grid-rows":l()}],"row-start-end":[{row:o()}],"row-start":[{"row-start":Z0()}],"row-end":[{"row-end":Z0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":d()}],"auto-rows":[{"auto-rows":d()}],gap:[{gap:y()}],"gap-x":[{"gap-x":y()}],"gap-y":[{"gap-y":y()}],"justify-content":[{justify:[...j(),"normal"]}],"justify-items":[{"justify-items":[...E(),"normal"]}],"justify-self":[{"justify-self":["auto",...E()]}],"align-content":[{content:["normal",...j()]}],"align-items":[{items:[...E(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...E(),{baseline:["","last"]}]}],"place-content":[{"place-content":j()}],"place-items":[{"place-items":[...E(),"baseline"]}],"place-self":[{"place-self":["auto",...E()]}],p:[{p:y()}],px:[{px:y()}],py:[{py:y()}],ps:[{ps:y()}],pe:[{pe:y()}],pbs:[{pbs:y()}],pbe:[{pbe:y()}],pt:[{pt:y()}],pr:[{pr:y()}],pb:[{pb:y()}],pl:[{pl:y()}],m:[{m:g()}],mx:[{mx:g()}],my:[{my:g()}],ms:[{ms:g()}],me:[{me:g()}],mbs:[{mbs:g()}],mbe:[{mbe:g()}],mt:[{mt:g()}],mr:[{mr:g()}],mb:[{mb:g()}],ml:[{ml:g()}],"space-x":[{"space-x":y()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":y()}],"space-y-reverse":["space-y-reverse"],size:[{size:n()}],"inline-size":[{inline:["auto",...r()]}],"min-inline-size":[{"min-inline":["auto",...r()]}],"max-inline-size":[{"max-inline":["none",...r()]}],"block-size":[{block:["auto",...G0()]}],"min-block-size":[{"min-block":["auto",...G0()]}],"max-block-size":[{"max-block":["none",...G0()]}],w:[{w:[Z,"screen",...n()]}],"min-w":[{"min-w":[Z,"screen","none",...n()]}],"max-w":[{"max-w":[Z,"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,Fw0,aC]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[$,Dlw,Zlw]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",o7A,S2]}],"font-family":[{font:[Klw,Hlw,Q]}],"font-features":[{"font-features":[S2]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[B,p2,S2]}],"line-clamp":[{"line-clamp":[_6,"none",p2,gU2]}],leading:[{leading:[X,...y()]}],"list-image":[{"list-image":["none",p2,S2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",p2,S2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:p()}],"text-color":[{text:p()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...L0(),"wavy"]}],"text-decoration-thickness":[{decoration:[_6,"from-font","auto",p2,aC]}],"text-decoration-color":[{decoration:p()}],"underline-offset":[{"underline-offset":[_6,"auto",p2,S2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:y()}],"tab-size":[{tab:[nV,p2,S2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",p2,S2]}],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,S2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:H0()}],"bg-repeat":[{bg:V0()}],"bg-size":[{bg:Q0()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},nV,p2,S2],radial:["",p2,S2],conic:[nV,p2,S2]},Glw,Wlw]}],"bg-color":[{bg:p()}],"gradient-from-pos":[{from:C0()}],"gradient-via-pos":[{via:C0()}],"gradient-to-pos":[{to:C0()}],"gradient-from":[{from:p()}],"gradient-via":[{via:p()}],"gradient-to":[{to:p()}],rounded:[{rounded:m0()}],"rounded-s":[{"rounded-s":m0()}],"rounded-e":[{"rounded-e":m0()}],"rounded-t":[{"rounded-t":m0()}],"rounded-r":[{"rounded-r":m0()}],"rounded-b":[{"rounded-b":m0()}],"rounded-l":[{"rounded-l":m0()}],"rounded-ss":[{"rounded-ss":m0()}],"rounded-se":[{"rounded-se":m0()}],"rounded-ee":[{"rounded-ee":m0()}],"rounded-es":[{"rounded-es":m0()}],"rounded-tl":[{"rounded-tl":m0()}],"rounded-tr":[{"rounded-tr":m0()}],"rounded-br":[{"rounded-br":m0()}],"rounded-bl":[{"rounded-bl":m0()}],"border-w":[{border:I0()}],"border-w-x":[{"border-x":I0()}],"border-w-y":[{"border-y":I0()}],"border-w-s":[{"border-s":I0()}],"border-w-e":[{"border-e":I0()}],"border-w-bs":[{"border-bs":I0()}],"border-w-be":[{"border-be":I0()}],"border-w-t":[{"border-t":I0()}],"border-w-r":[{"border-r":I0()}],"border-w-b":[{"border-b":I0()}],"border-w-l":[{"border-l":I0()}],"divide-x":[{"divide-x":I0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":I0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...L0(),"hidden","none"]}],"divide-style":[{divide:[...L0(),"hidden","none"]}],"border-color":[{border:p()}],"border-color-x":[{"border-x":p()}],"border-color-y":[{"border-y":p()}],"border-color-s":[{"border-s":p()}],"border-color-e":[{"border-e":p()}],"border-color-bs":[{"border-bs":p()}],"border-color-be":[{"border-be":p()}],"border-color-t":[{"border-t":p()}],"border-color-r":[{"border-r":p()}],"border-color-b":[{"border-b":p()}],"border-color-l":[{"border-l":p()}],"divide-color":[{divide:p()}],"outline-style":[{outline:[...L0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[_6,p2,S2]}],"outline-w":[{outline:["",_6,Fw0,aC]}],"outline-color":[{outline:p()}],shadow:[{shadow:["","none",U,CF0,vF0]}],"shadow-color":[{shadow:p()}],"inset-shadow":[{"inset-shadow":["none",G,CF0,vF0]}],"inset-shadow-color":[{"inset-shadow":p()}],"ring-w":[{ring:I0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:p()}],"ring-offset-w":[{"ring-offset":[_6,aC]}],"ring-offset-color":[{"ring-offset":p()}],"inset-ring-w":[{"inset-ring":I0()}],"inset-ring-color":[{"inset-ring":p()}],"text-shadow":[{"text-shadow":["none",D,CF0,vF0]}],"text-shadow-color":[{"text-shadow":p()}],opacity:[{opacity:[_6,p2,S2]}],"mix-blend":[{"mix-blend":[...j0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":j0()}],"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":[_6]}],"mask-image-linear-from-pos":[{"mask-linear-from":E0()}],"mask-image-linear-to-pos":[{"mask-linear-to":E0()}],"mask-image-linear-from-color":[{"mask-linear-from":p()}],"mask-image-linear-to-color":[{"mask-linear-to":p()}],"mask-image-t-from-pos":[{"mask-t-from":E0()}],"mask-image-t-to-pos":[{"mask-t-to":E0()}],"mask-image-t-from-color":[{"mask-t-from":p()}],"mask-image-t-to-color":[{"mask-t-to":p()}],"mask-image-r-from-pos":[{"mask-r-from":E0()}],"mask-image-r-to-pos":[{"mask-r-to":E0()}],"mask-image-r-from-color":[{"mask-r-from":p()}],"mask-image-r-to-color":[{"mask-r-to":p()}],"mask-image-b-from-pos":[{"mask-b-from":E0()}],"mask-image-b-to-pos":[{"mask-b-to":E0()}],"mask-image-b-from-color":[{"mask-b-from":p()}],"mask-image-b-to-color":[{"mask-b-to":p()}],"mask-image-l-from-pos":[{"mask-l-from":E0()}],"mask-image-l-to-pos":[{"mask-l-to":E0()}],"mask-image-l-from-color":[{"mask-l-from":p()}],"mask-image-l-to-color":[{"mask-l-to":p()}],"mask-image-x-from-pos":[{"mask-x-from":E0()}],"mask-image-x-to-pos":[{"mask-x-to":E0()}],"mask-image-x-from-color":[{"mask-x-from":p()}],"mask-image-x-to-color":[{"mask-x-to":p()}],"mask-image-y-from-pos":[{"mask-y-from":E0()}],"mask-image-y-to-pos":[{"mask-y-to":E0()}],"mask-image-y-from-color":[{"mask-y-from":p()}],"mask-image-y-to-color":[{"mask-y-to":p()}],"mask-image-radial":[{"mask-radial":[p2,S2]}],"mask-image-radial-from-pos":[{"mask-radial-from":E0()}],"mask-image-radial-to-pos":[{"mask-radial-to":E0()}],"mask-image-radial-from-color":[{"mask-radial-from":p()}],"mask-image-radial-to-color":[{"mask-radial-to":p()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":f()}],"mask-image-conic-pos":[{"mask-conic":[_6]}],"mask-image-conic-from-pos":[{"mask-conic-from":E0()}],"mask-image-conic-to-pos":[{"mask-conic-to":E0()}],"mask-image-conic-from-color":[{"mask-conic-from":p()}],"mask-image-conic-to-color":[{"mask-conic-to":p()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:H0()}],"mask-repeat":[{mask:V0()}],"mask-size":[{mask:Q0()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",p2,S2]}],filter:[{filter:["","none",p2,S2]}],blur:[{blur:P0()}],brightness:[{brightness:[_6,p2,S2]}],contrast:[{contrast:[_6,p2,S2]}],"drop-shadow":[{"drop-shadow":["","none",z,CF0,vF0]}],"drop-shadow-color":[{"drop-shadow":p()}],grayscale:[{grayscale:["",_6,p2,S2]}],"hue-rotate":[{"hue-rotate":[_6,p2,S2]}],invert:[{invert:["",_6,p2,S2]}],saturate:[{saturate:[_6,p2,S2]}],sepia:[{sepia:["",_6,p2,S2]}],"backdrop-filter":[{"backdrop-filter":["","none",p2,S2]}],"backdrop-blur":[{"backdrop-blur":P0()}],"backdrop-brightness":[{"backdrop-brightness":[_6,p2,S2]}],"backdrop-contrast":[{"backdrop-contrast":[_6,p2,S2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",_6,p2,S2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[_6,p2,S2]}],"backdrop-invert":[{"backdrop-invert":["",_6,p2,S2]}],"backdrop-opacity":[{"backdrop-opacity":[_6,p2,S2]}],"backdrop-saturate":[{"backdrop-saturate":[_6,p2,S2]}],"backdrop-sepia":[{"backdrop-sepia":["",_6,p2,S2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":y()}],"border-spacing-x":[{"border-spacing-x":y()}],"border-spacing-y":[{"border-spacing-y":y()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",p2,S2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[_6,"initial",p2,S2]}],ease:[{ease:["linear","initial",_,p2,S2]}],delay:[{delay:[_6,p2,S2]}],animate:[{animate:["none",k,p2,S2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[I,p2,S2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:M0()}],"rotate-x":[{"rotate-x":M0()}],"rotate-y":[{"rotate-y":M0()}],"rotate-z":[{"rotate-z":M0()}],scale:[{scale:O0()}],"scale-x":[{"scale-x":O0()}],"scale-y":[{"scale-y":O0()}],"scale-z":[{"scale-z":O0()}],"scale-3d":["scale-3d"],skew:[{skew:f0()}],"skew-x":[{"skew-x":f0()}],"skew-y":[{"skew-y":f0()}],transform:[{transform:[p2,S2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:S0()}],"translate-x":[{"translate-x":S0()}],"translate-y":[{"translate-y":S0()}],"translate-z":[{"translate-z":S0()}],"translate-none":["translate-none"],zoom:[{zoom:[nV,p2,S2]}],accent:[{accent:p()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:p()}],"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,S2]}],"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":p()}],"scrollbar-track-color":[{"scrollbar-track":p()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":y()}],"scroll-mx":[{"scroll-mx":y()}],"scroll-my":[{"scroll-my":y()}],"scroll-ms":[{"scroll-ms":y()}],"scroll-me":[{"scroll-me":y()}],"scroll-mbs":[{"scroll-mbs":y()}],"scroll-mbe":[{"scroll-mbe":y()}],"scroll-mt":[{"scroll-mt":y()}],"scroll-mr":[{"scroll-mr":y()}],"scroll-mb":[{"scroll-mb":y()}],"scroll-ml":[{"scroll-ml":y()}],"scroll-p":[{"scroll-p":y()}],"scroll-px":[{"scroll-px":y()}],"scroll-py":[{"scroll-py":y()}],"scroll-ps":[{"scroll-ps":y()}],"scroll-pe":[{"scroll-pe":y()}],"scroll-pbs":[{"scroll-pbs":y()}],"scroll-pbe":[{"scroll-pbe":y()}],"scroll-pt":[{"scroll-pt":y()}],"scroll-pr":[{"scroll-pr":y()}],"scroll-pb":[{"scroll-pb":y()}],"scroll-pl":[{"scroll-pl":y()}],"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,S2]}],fill:[{fill:["none",...p()]}],"stroke-w":[{stroke:[_6,Fw0,aC,gU2]}],stroke:[{stroke:["none",...p()]}],"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"]}},zlw=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:$,extend:B={},override:X={}})=>{return Fl(A,"cacheSize",Q),Fl(A,"prefix",w),Fl(A,"experimentalParseClassName",$),hF0(A.theme,X.theme),hF0(A.classGroups,X.classGroups),hF0(A.conflictingClassGroups,X.conflictingClassGroups),hF0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),Fl(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),Fl(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),EF0(A.theme,B.theme),EF0(A.classGroups,B.classGroups),EF0(A.conflictingClassGroups,B.conflictingClassGroups),EF0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),s7A(A,B,"postfixLookupClassGroups"),s7A(A,B,"orderSensitiveModifiers"),A},Fl=(A,Q,w)=>{if(w!==void 0)A[Q]=w},hF0=(A,Q)=>{if(Q)for(let w in Q)Fl(A,w,Q[w])},EF0=(A,Q)=>{if(Q)for(let w in Q)s7A(A,Q,w)},s7A=(A,Q,w)=>{let $=Q[w];if($!==void 0)A[w]=A[w]?A[w].concat($):$},gF0=(A,...Q)=>typeof A==="function"?EU2(SU2,A,...Q):EU2(()=>zlw(SU2(),A),...Q);var Jlw=gF0({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 l2(...A){return Jlw(Vl(A))}var AG2=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,QG2=Vl,f8=(A,Q)=>(w)=>{var $;if((Q===null||Q===void 0?void 0:Q.variants)==null)return QG2(A,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className);let{variants:B,defaultVariants:X}=Q,Y=Object.keys(B).map((K)=>{let U=w===null||w===void 0?void 0:w[K],G=X===null||X===void 0?void 0:X[K];if(U===null)return null;let D=AG2(U)||AG2(G);return B[K][D]}),Z=w&&Object.entries(w).reduce((K,U)=>{let[G,D]=U;if(D===void 0)return K;return K[G]=D,K},{}),W=Q===null||Q===void 0?void 0:($=Q.compoundVariants)===null||$===void 0?void 0:$.reduce((K,U)=>{let{class:G,className:D,...z}=U;return Object.entries(z).every((V)=>{let[I,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[I]):{...X,...Z}[I]===F})?[...K,G,D]:K},[]);return QG2(A,Y,W,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as e7A}from"preact/jsx-dev-runtime";var wG2=f8("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 A4A({variant:A,title:Q,children:w,className:$}){return e7A("div",{className:l2(wG2({variant:A}),$),role:"alert",children:[Q&&e7A("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),e7A("div",{className:l2(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 Vlw}from"preact/jsx-dev-runtime";var $G2=f8("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 eC({variant:A,size:Q,className:w,children:$,ssrOnClick:B,type:X="button",...Y}){return Vlw("button",{type:X,className:l2($G2({variant:A,size:Q}),w),...Y,...B&&{onclick:B},children:$},void 0,!1,void 0,this)}import{jsxDEV as Flw}from"preact/jsx-dev-runtime";var BG2=f8("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 I4({href:A,children:Q,variant:w,size:$,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return Flw("a",{href:A,className:l2(BG2({variant:w,size:$}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as yF0}from"preact/jsx-dev-runtime";var XG2=f8("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"}}),Ilw={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Il({variant:A,size:Q,className:w}){let $=Ilw[Q??"md"];return yF0("button",{onclick:"toggleTheme()",type:"button",className:l2(XG2({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:yF0("svg",{className:l2($,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[yF0("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),yF0("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 Q4A}from"preact/jsx-dev-runtime";var YG2=f8("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function TF0({items:A,className:Q,linkClassName:w="hover:text-accent transition-colors",orientation:$,children:B}){if(A.length===0&&!B)return null;let X=[...A].sort((Y,Z)=>Y.priority-Z.priority);return Q4A("ul",{className:l2(YG2({orientation:$}),Q),children:[X.map((Y)=>Q4A("li",{children:Q4A("a",{href:Y.href,className:w,children:Y.label},void 0,!1,void 0,this)},Y.href,!1,void 0,this)),B]},void 0,!0,void 0,this)}import{jsxDEV as cd8}from"preact/jsx-dev-runtime";import{jsxDEV as dd8}from"preact/jsx-dev-runtime";import{createContext as Llw,h as Nlw}from"preact";import{useContext as _lw}from"preact/hooks";var w4A=Llw(null);function Ll({headCollector:A,children:Q}){return Nlw(w4A.Provider,{value:A},Q)}function ZG2(){return _lw(w4A)}function Nw(A){let Q=ZG2();if(Q)Q.setHeadProps(A);return null}import{createContext as esw,h as Aaw}from"preact";import{useContext as Qaw}from"preact/hooks";Xa0();var Vz2=V1(Jz2(),1),asw=new CG0({gfm:!0,breaks:!0}),tsw={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 jXA(A,Q){let{imageRenderer:w}=Q??{},B=(w?new CG0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return w(X,Y,Z)??!1}}}):asw).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5792
5792
|
<cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),Vz2.default(B,tsw)}var Fz2=esw(null);function yl({imageRenderer:A,children:Q}){return Aaw(Fz2.Provider,{value:A??null},Q)}function Iz2(){return Qaw(Fz2)}function q_(){let A=Iz2();return(Q)=>jXA(Q,A?{imageRenderer:A}:void 0)}var waw=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,$aw={"&":"&","<":"<",">":">",""":'"',"'":"'"},Baw=/&(?:amp|lt|gt|quot|#39);/g;function Xaw(A){return A.replace(Baw,(Q)=>$aw[Q]??Q)}function OXA(A){return A.replace(waw,(Q,w)=>{return`<div class="mermaid">${Xaw(w)}</div>`})}var Lz2=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function Nz2(A){let Q={};for(let $ of A.matchAll(Lz2)){let B=$[1]??"";for(let Y of B.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let Z=Y[1],W=Y[2];if(Z&&W!==void 0)Q[Z]=W}let X=B.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(X)for(let Y of X.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let Z=Y[1];if(Z)Q[Z]="true"}}let w=A.replace(Lz2,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
|
|
5793
5793
|
|
|
5794
5794
|
`).trim();return{attributes:Q,markdown:w}}var Yaw=/<!--\s*\.break\s*-->/;function _z2(A){let Q=A.split(Yaw);return Q.length>1?Q:null}import{jsxDEV as AF}from"preact/jsx-dev-runtime";var fXA=({markdown:A,deck:Q})=>{let w=q_(),B=A.split(/^---$/gm).map((U)=>U.trim()).map((U)=>{let{attributes:G,markdown:D}=Nz2(U),z=_z2(D),V;if(z)V=`<div class="slide-columns">${z.map((F)=>`<div class="slide-column">${OXA(w(F.trim()))}</div>`).join("")}</div>`;else V=OXA(w(D));return{attributes:G,htmlContent:V}}),X=B.some((U)=>U.htmlContent.includes('class="mermaid"')),Y=Q?.frontmatter?.title??Q?.metadata?.title,Z=Q?.frontmatter?.description??Q?.metadata?.description,W=Q?.ogImageUrl??Q?.coverImageUrl,K=B.map(({attributes:U,htmlContent:G},D)=>AF("section",{...U,dangerouslySetInnerHTML:{__html:G}},D,!1,void 0,this));return AF("section",{className:"presentation-section",children:[Y&&AF(Nw,{title:Y,...Z?{description:Z}:{},...W?{ogImage:W}:{},ogType:"article"},void 0,!1,void 0,this),AF("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),AF("div",{className:"reveal",children:AF("div",{className:"slides",children:K},void 0,!1,void 0,this)},void 0,!1,void 0,this),AF("script",{src:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.js",defer:!0},void 0,!1,void 0,this),X&&AF("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),AF("script",{dangerouslySetInnerHTML:{__html:`
|
|
@@ -6775,13 +6775,13 @@ ${A.map((X)=>({url:`${Q}${X.path}`,lastmod:w,changefreq:X.path==="/"?"daily":"we
|
|
|
6775
6775
|
`+B:w,Y=GF(this.outputDir,"styles","main.css");await this.cssProcessor.process(X,Y,this.workingDir,this.outputDir,this.logger);let Z=await $Y.readFile(Y,"utf-8"),W=$.length>0?$:Q;if(W.length>0){let K=W.join(`
|
|
6776
6776
|
`)+`
|
|
6777
6777
|
|
|
6778
|
-
`+Z;await $Y.writeFile(Y,K,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=GF(process.cwd(),"public");try{await $Y.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await $Y.readdir(A,{withFileTypes:!0});for(let w of Q){let $=GF(A,w.name),B=GF(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory($,B);else await $Y.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,$])=>{let B=w.startsWith("/")?w.slice(1):w,X=GF(this.outputDir,B);await $Y.mkdir(uX6(X),{recursive:!0}),await $Y.writeFile(X,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${B}`)}))}async copyDirectory(A,Q){await $Y.mkdir(Q,{recursive:!0});let w=await $Y.readdir(A,{withFileTypes:!0});for(let $ of w){let B=GF(A,$.name),X=GF(Q,$.name);if($.isDirectory())await this.copyDirectory(B,X);else await $Y.copyFile(B,X)}}}function OHA(A){return new IM2(A)}u7();b0();b0();var cX6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),pX6=H.object({blurb:H.string().optional()}),Vd=H.object({title:H.string(),description:H.string(),url:H.string().optional(),copyright:H.string().optional(),logo:H.boolean().optional(),themeMode:H.enum(["light","dark"]).optional(),analyticsScript:H.string().optional(),cta:cX6.optional(),sections:H.record(H.string(),pX6).optional()});var LM2=H.object({environment:H.enum(["preview","production"]),outputDir:H.string(),workingDir:H.string().optional(),sharedImagesDir:H.string().default("./dist/images"),enableContentGeneration:H.boolean().default(!1),cleanBeforeBuild:H.boolean().default(!0),siteConfig:Vd,layouts:H.record(H.string(),H.any()),themeCSS:H.string().optional()}),RQ5=H.object({success:H.boolean(),outputDir:H.string(),filesGenerated:H.number(),routesBuilt:H.number(),errors:H.array(H.string()).optional(),warnings:H.array(H.string()).optional()});function NM2(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function _M2(A,Q,w){let $=Q.getProfile(),B=w.getNavigationItems("primary"),X=w.getNavigationItems("secondary");return{...A,...$.socialLinks!==void 0&&{socialLinks:$.socialLinks},navigation:{primary:B,secondary:X},copyright:A.copyright??"Powered by Rizom"}}u7();rY();u7();R2();b0();var lX6=H.looseObject({id:H.string(),entityType:H.string(),content:H.string(),metadata:H.looseObject({slug:H.string()})}),dX6=H.looseObject({content:H.string(),metadata:H.looseObject({width:H.number().optional(),height:H.number().optional()})});async function qN0(A,Q){let w=Q.urlGenerator??bY.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((f)=>qN0(f,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let $={},B=Object.entries(A),X=await Promise.all(B.map(([,f])=>qN0(f,{...Q,urlGenerator:w})));for(let f=0;f<B.length;f++){let R=B[f];if(R)$[R[0]]=X[f]}let Y=lX6.safeParse(A);if(!Y.success)return $;let Z=Y.data,W=Z.entityType,K=Z.metadata.slug,U=Q.pipelineContext.entityDisplay?.[W],G=U?U.label:W.charAt(0).toUpperCase()+W.slice(1),D=U?U.pluralName??U.label.toLowerCase()+"s":fD(W),z=`/${D}`,V=D.charAt(0).toUpperCase()+D.slice(1),I=re(Z),F=await iX6(I,Q),_=ZU0(Z)??I,k=await nX6(_,Q);return{...$,...Z,url:w.generateUrl(W,K),typeLabel:G,listUrl:z,listLabel:V,...F,...k&&{ogImageUrl:k}}}async function iX6(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 $=await kM2(A,Q.pipelineContext.services.entityService);if(!$)return{};return{coverImageUrl:$.url,...$.width&&{coverImageWidth:$.width},...$.height&&{coverImageHeight:$.height}}}async function nX6(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return bM2(w.src,Q.siteUrl);let $=await kM2(A,Q.pipelineContext.services.entityService);if(!$)return;if($.url.startsWith("data:"))return;return bM2($.url,Q.siteUrl)}function bM2(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function kM2(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),$=dX6.safeParse(w);if(!$.success)return;return{url:$.data.content,...$.data.metadata.width&&{width:$.data.metadata.width},...$.data.metadata.height&&{height:$.data.metadata.height}}}async function PM2(A,Q){let w=new Set;try{let $=A.getEntityTypes();for(let B of $){if(B==="image")continue;let X=await A.listEntities({entityType:B});for(let Y of X){let Z=re(Y);if(Z)w.add(Z);let W=ZU0(Y);if(W)w.add(W)}}}catch($){Q.warn("Failed to collect image IDs for pre-resolution",{error:lA($)})}return[...w]}async function MM2(A,Q,w,$,B){if(!A.template)return A.content??null;let X=A.template,Y={entityType:"site-content",entityId:`${Q.id}:${A.id}`},Z=A.dataQuery?{dataParams:A.dataQuery,savedContent:Y,fallback:A.content,publishedOnly:w,visibilityScope:$}:{savedContent:Y,fallback:A.content,visibilityScope:$},W=await B.pipelineContext.services.resolveTemplateContent(X,Z);if(!W)return null;return qN0(W,{pipelineContext:B.pipelineContext,imageBuildService:B.imageBuildService,siteUrl:B.siteUrl,urlGenerator:bY.getInstance()})}function jM2(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 $=A.parsedOptions.environment==="production";return MM2(w,Q,$,"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 _M2(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 rX6}from"path";async function OM2(A){let Q=A.parsedOptions.workingDir??rX6(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 fM2(A){await new GN0({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 xM2(A){let Q=new UN0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await PM2(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function RM2(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function vM2(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function CM2(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function hM2(A){let Q=LM2.parse(A.buildOptions),w=hZ.from(A.progress),$=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await fM2({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let B=await OM2({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),X=NM2(A.pipelineContext.routeRegistry);$.push(...X.warnings);let{routes:Y}=X;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let Z=await xM2({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),W=jM2({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Z,siteMetadata:Q.siteConfig});return await RM2({staticSiteBuilder:B,buildContext:W,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),vM2({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:$})}catch(B){let X=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:X,originalError:B}),CM2({outputDir:Q.outputDir,errorMessage:X.message})}}class t3{static instance=null;static defaultStaticSiteBuilderFactory=OHA;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){t3.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,$,B=void 0){return t3.instance??=new t3(A,t3.defaultStaticSiteBuilderFactory,Q,w,$,B),t3.instance}static resetInstance(){t3.instance=null}static createFresh(A,Q,w,$,B,X=void 0){return new t3(A,B??t3.defaultStaticSiteBuilderFactory,Q,w,$,X)}constructor(A,Q,w,$,B,X){this.pipelineContext={logger:A,services:w,routeRegistry:$,profileService:B,entityDisplay:X},this.staticSiteBuilderFactory=Q,bY.getInstance().configure(X)}async build(A,Q){return hM2({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class fHA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,$){this.config=A,this.context=Q,this.pluginId=w,this.logger=$}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new i7A(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async($)=>{let{entityType:B}=$.payload;if(!A.has(B))this.logger.debug(`Entity type ${B} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let $ of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe($,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({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})}}}u7();function oX6(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function zN0(A,Q,w){for(let $ of A)w.register({...$,pluginId:Q,sections:$.sections?oX6($.sections,Q):[]})}function EM2(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let B=N90.parse($.payload),{routes:X,pluginId:Y}=B;return zN0(X,Y,Q),{success:!0}}catch(B){return w.error("Failed to register routes",{error:B}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async($)=>{try{let B=_90.parse($.payload),{paths:X,pluginId:Y}=B;if(X)for(let Z of X)Q.unregister(Z);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch(B){return w.error("Failed to unregister routes",{error:B}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async($)=>{try{let B=b90.parse($.payload);return{success:!0,data:{routes:Q.list(B.pluginId?B:void 0)}}}catch(B){return w.error("Failed to list routes",{error:B}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async($)=>{try{let B=k90.parse($.payload);return{success:!0,data:{route:Q.get(B.path)}}}catch(B){return w.error("Failed to get route",{error:B}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as gM2}from"fs";import{join as yM2}from"path";async function sX6(A,Q,w){let $=A.siteConfig.url??"https://example.com",B=Q.list(),X=MHA($,A.environment);await gM2.writeFile(yM2(A.outputDir,"robots.txt"),X,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=jHA(B,$);await gM2.writeFile(yM2(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${B.length} URLs`)}function TM2(A){let{context:Q,routeRegistry:w,logger:$}=A;Q.messaging.subscribe("site:build:completed",async(B)=>{try{let X=B.payload;return $.info(`Received site:build:completed event for ${X.environment} environment - generating SEO files`),await sX6(X,w,$),{success:!0}}catch(X){return $.error("Failed to generate SEO files",X),{success:!1}}})}$A();b0();var SM2=H.object({environment:H.enum(["preview","production"]).optional(),outputDir:H.string(),workingDir:H.string().optional(),enableContentGeneration:H.boolean().optional(),siteConfig:Vd.optional()});u7();u7();b0();var aX6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),tX6=H.object({blurb:H.string().optional()}),mM2=H.object({title:H.string(),description:H.string(),url:H.string().optional(),copyright:H.string().optional(),logo:H.boolean().optional(),themeMode:H.enum(["light","dark"]).optional(),analyticsScript:H.string().optional(),cta:aX6.optional(),sections:H.record(H.string(),tX6).optional()});async function l60(A,Q){try{let w=await A({type:Lr,payload:void 0});if("success"in w&&w.success&&w.data){let $=mM2.safeParse(w.data);if($.success)return mM2.parse({...Q,...$.data})}}catch{}return Q}class xHA extends p6{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:SM2,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let $=A.environment??"preview",B=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:$,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${$} environment`});let X=w.createSub({scale:{start:10,end:90}}),Y=await l60(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),Z=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:B,environment:$,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}},X.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${Z.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:$,routesBuilt:Z.routesBuilt,success:Z.success}),Z.success){this.logger.info(`Emitting site:build:completed event for ${$} environment`);let W=$==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:$,routesBuilt:Z.routesBuilt,siteConfig:{...Y,url:W},generateEntityUrl:(K,U)=>bY.getInstance().generateUrl(K,U)},broadcast:!0})}return{success:Z.success,routesBuilt:Z.routesBuilt,outputDir:A.outputDir,environment:$,...Z.errors&&{errors:Z.errors},...Z.warnings&&{warnings:Z.warnings}}}catch(X){throw this.logger.error("Site build job failed",X),X}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}b0();u7();var eX6=H.object({slot:H.enum(gb).optional().default("primary"),limit:H.number().optional()});class RHA{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 $=eX6.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:$});let B=this.routeRegistry.getNavigationItems($.slot),X=$.limit?B.slice(0,$.limit):B,Y=X.map((W)=>({label:W.label,href:W.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:X.length,items:Y});let Z={navigation:Y};return Q.parse(Z)}}u7();$A();b0();var AY6=H.object({environment:H.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function uM2(A,Q){return[j$(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'.",AY6,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}b0();u7();var QY6=H.object({id:H.string(),template:H.string(),content:H.unknown().optional(),dataQuery:H.looseObject({entityType:H.string().optional(),template:H.string().optional(),query:H.looseObject({id:H.string().optional(),limit:H.number().optional(),offset:H.number().optional()}).optional()}).optional(),order:H.number().optional()}),wY6=H.object({show:H.boolean().default(!1),label:H.string().optional(),slot:H.enum(gb).default("primary"),priority:H.number().min(0).max(100).default(50)}).optional(),$Y6=H.object({id:H.string(),path:H.string(),title:H.string().default(""),pageLabel:H.string().optional(),description:H.string().default(""),sections:H.array(QY6).default([]),layout:H.string().default("default"),fullscreen:H.boolean().optional(),pluginId:H.string().optional(),sourceEntityType:H.string().optional(),external:H.boolean().optional(),navigation:wY6}),cM2=H.object({previewOutputDir:H.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:H.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:H.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:H.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:Vd.default({title:"Brain",description:"A knowledge management system"}),themeCSS:H.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:H.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:H.any().optional().describe("Template definitions to register"),routes:H.array($Y6).optional().describe("Routes to register"),layouts:H.record(H.string(),H.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:H.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:H.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:H.record(H.string(),H.object({label:H.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:H.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:H.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:H.boolean().optional().describe("Enable pagination for list pages"),pageSize:H.number().optional().describe("Items per page (default: 10)"),navigation:H.object({show:H.boolean().optional().describe("Show in navigation"),slot:H.enum(gb).optional().describe("Navigation slot (primary or secondary)"),priority:H.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:H.record(H.string(),H.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 pM2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.180",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 vHA extends Rw{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",pM2,{...A,layouts:Q},cM2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new DN0(A.logger),this._slotRegistry=new uL0,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:$,pluginId:B,render:X,priority:Y}=w.payload;return this._slotRegistry?.register($,{pluginId:B,render:X,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:$,script:B}=w.payload;return this.headScripts.set($,B),{success:!0}}),A.entities.registerDataSource(new RHA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},EM2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)zN0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,$)=>A.templates.resolve(w,$),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=t3.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new xHA(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 fHA(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(Nr,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),TM2({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 uM2(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 l60(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(($)=>({id:$.id,template:$.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((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 l60(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6778
|
+
`+Z;await $Y.writeFile(Y,K,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=GF(process.cwd(),"public");try{await $Y.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await $Y.readdir(A,{withFileTypes:!0});for(let w of Q){let $=GF(A,w.name),B=GF(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory($,B);else await $Y.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,$])=>{let B=w.startsWith("/")?w.slice(1):w,X=GF(this.outputDir,B);await $Y.mkdir(uX6(X),{recursive:!0}),await $Y.writeFile(X,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${B}`)}))}async copyDirectory(A,Q){await $Y.mkdir(Q,{recursive:!0});let w=await $Y.readdir(A,{withFileTypes:!0});for(let $ of w){let B=GF(A,$.name),X=GF(Q,$.name);if($.isDirectory())await this.copyDirectory(B,X);else await $Y.copyFile(B,X)}}}function OHA(A){return new IM2(A)}u7();b0();b0();var cX6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),pX6=H.object({blurb:H.string().optional()}),Vd=H.object({title:H.string(),description:H.string(),url:H.string().optional(),copyright:H.string().optional(),logo:H.boolean().optional(),themeMode:H.enum(["light","dark"]).optional(),analyticsScript:H.string().optional(),cta:cX6.optional(),sections:H.record(H.string(),pX6).optional()});var LM2=H.object({environment:H.enum(["preview","production"]),outputDir:H.string(),workingDir:H.string().optional(),sharedImagesDir:H.string().default("./dist/images"),enableContentGeneration:H.boolean().default(!1),cleanBeforeBuild:H.boolean().default(!0),siteConfig:Vd,layouts:H.record(H.string(),H.any()),themeCSS:H.string().optional()}),RQ5=H.object({success:H.boolean(),outputDir:H.string(),filesGenerated:H.number(),routesBuilt:H.number(),errors:H.array(H.string()).optional(),warnings:H.array(H.string()).optional()});function NM2(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function _M2(A,Q,w){let $=Q.getProfile(),B=w.getNavigationItems("primary"),X=w.getNavigationItems("secondary");return{...A,...$.socialLinks!==void 0&&{socialLinks:$.socialLinks},navigation:{primary:B,secondary:X},copyright:A.copyright??"Powered by Rizom"}}u7();rY();u7();R2();b0();var lX6=H.looseObject({id:H.string(),entityType:H.string(),content:H.string(),metadata:H.looseObject({slug:H.string()})}),dX6=H.looseObject({content:H.string(),metadata:H.looseObject({width:H.number().optional(),height:H.number().optional()})});async function qN0(A,Q){let w=Q.urlGenerator??bY.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((f)=>qN0(f,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let $={},B=Object.entries(A),X=await Promise.all(B.map(([,f])=>qN0(f,{...Q,urlGenerator:w})));for(let f=0;f<B.length;f++){let R=B[f];if(R)$[R[0]]=X[f]}let Y=lX6.safeParse(A);if(!Y.success)return $;let Z=Y.data,W=Z.entityType,K=Z.metadata.slug,U=Q.pipelineContext.entityDisplay?.[W],G=U?U.label:W.charAt(0).toUpperCase()+W.slice(1),D=U?U.pluralName??U.label.toLowerCase()+"s":fD(W),z=`/${D}`,V=D.charAt(0).toUpperCase()+D.slice(1),I=re(Z),F=await iX6(I,Q),_=ZU0(Z)??I,k=await nX6(_,Q);return{...$,...Z,url:w.generateUrl(W,K),typeLabel:G,listUrl:z,listLabel:V,...F,...k&&{ogImageUrl:k}}}async function iX6(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 $=await kM2(A,Q.pipelineContext.services.entityService);if(!$)return{};return{coverImageUrl:$.url,...$.width&&{coverImageWidth:$.width},...$.height&&{coverImageHeight:$.height}}}async function nX6(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return bM2(w.src,Q.siteUrl);let $=await kM2(A,Q.pipelineContext.services.entityService);if(!$)return;if($.url.startsWith("data:"))return;return bM2($.url,Q.siteUrl)}function bM2(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function kM2(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),$=dX6.safeParse(w);if(!$.success)return;return{url:$.data.content,...$.data.metadata.width&&{width:$.data.metadata.width},...$.data.metadata.height&&{height:$.data.metadata.height}}}async function PM2(A,Q){let w=new Set;try{let $=A.getEntityTypes();for(let B of $){if(B==="image")continue;let X=await A.listEntities({entityType:B});for(let Y of X){let Z=re(Y);if(Z)w.add(Z);let W=ZU0(Y);if(W)w.add(W)}}}catch($){Q.warn("Failed to collect image IDs for pre-resolution",{error:lA($)})}return[...w]}async function MM2(A,Q,w,$,B){if(!A.template)return A.content??null;let X=A.template,Y={entityType:"site-content",entityId:`${Q.id}:${A.id}`},Z=A.dataQuery?{dataParams:A.dataQuery,savedContent:Y,fallback:A.content,publishedOnly:w,visibilityScope:$}:{savedContent:Y,fallback:A.content,visibilityScope:$},W=await B.pipelineContext.services.resolveTemplateContent(X,Z);if(!W)return null;return qN0(W,{pipelineContext:B.pipelineContext,imageBuildService:B.imageBuildService,siteUrl:B.siteUrl,urlGenerator:bY.getInstance()})}function jM2(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 $=A.parsedOptions.environment==="production";return MM2(w,Q,$,"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 _M2(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 rX6}from"path";async function OM2(A){let Q=A.parsedOptions.workingDir??rX6(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 fM2(A){await new GN0({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 xM2(A){let Q=new UN0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await PM2(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function RM2(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function vM2(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function CM2(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function hM2(A){let Q=LM2.parse(A.buildOptions),w=hZ.from(A.progress),$=[];try{await w?.report({message:"Starting site build",progress:0,total:100}),await w?.report({message:"Generating dynamic routes",progress:10,total:100}),await fM2({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let B=await OM2({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),X=NM2(A.pipelineContext.routeRegistry);$.push(...X.warnings);let{routes:Y}=X;await w?.report({message:`Building ${Y.length} routes`,progress:20,total:100}),await w?.report({message:"Resolving images",progress:25,total:100});let Z=await xM2({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),W=jM2({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Z,siteMetadata:Q.siteConfig});return await RM2({staticSiteBuilder:B,buildContext:W,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),vM2({outputDir:Q.outputDir,routesBuilt:Y.length,warnings:$})}catch(B){let X=Error("Site build process failed");return A.pipelineContext.logger.error("Site build failed",{error:X,originalError:B}),CM2({outputDir:Q.outputDir,errorMessage:X.message})}}class t3{static instance=null;static defaultStaticSiteBuilderFactory=OHA;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){t3.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,$,B=void 0){return t3.instance??=new t3(A,t3.defaultStaticSiteBuilderFactory,Q,w,$,B),t3.instance}static resetInstance(){t3.instance=null}static createFresh(A,Q,w,$,B,X=void 0){return new t3(A,B??t3.defaultStaticSiteBuilderFactory,Q,w,$,X)}constructor(A,Q,w,$,B,X){this.pipelineContext={logger:A,services:w,routeRegistry:$,profileService:B,entityDisplay:X},this.staticSiteBuilderFactory=Q,bY.getInstance().configure(X)}async build(A,Q){return hM2({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class fHA{config;context;pluginId;logger;debounces=new Map;unsubscribeFunctions=[];constructor(A,Q,w,$){this.config=A,this.context=Q,this.pluginId=w,this.logger=$}requestBuild(A){let Q=A??(this.config.previewOutputDir?"preview":"production"),w=this.debounces.get(Q);if(!w)w=new i7A(()=>{this.enqueueBuild(Q)},this.config.rebuildDebounce),this.debounces.set(Q,w);w.trigger()}setupAutoRebuild(){let A=new Set(["note"]),Q=async($)=>{let{entityType:B}=$.payload;if(!A.has(B))this.logger.debug(`Entity type ${B} will trigger rebuild`),this.requestBuild();return{success:!0}},w=["entity:created","entity:updated","entity:deleted"];for(let $ of w)this.unsubscribeFunctions.push(this.context.messaging.subscribe($,Q));this.logger.debug(`Auto-rebuild enabled (${this.config.rebuildDebounce}ms debounce), excluding types: ${[...A].join(", ")}`)}dispose(){for(let A of this.debounces.values())A.dispose();this.debounces.clear();for(let A of this.unsubscribeFunctions)A();this.unsubscribeFunctions=[]}async enqueueBuild(A){let Q=A==="production"?this.config.productionOutputDir:this.config.previewOutputDir;this.logger.debug(`Triggering ${A} site rebuild`);try{await this.context.jobs.enqueue({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})}}}u7();function oX6(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function zN0(A,Q,w){for(let $ of A)w.register({...$,pluginId:Q,sections:$.sections?oX6($.sections,Q):[]})}function EM2(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let B=N90.parse($.payload),{routes:X,pluginId:Y}=B;return zN0(X,Y,Q),{success:!0}}catch(B){return w.error("Failed to register routes",{error:B}),{success:!1,error:"Failed to register routes"}}}),A.messaging.subscribe("plugin:site-builder:route:unregister",async($)=>{try{let B=_90.parse($.payload),{paths:X,pluginId:Y}=B;if(X)for(let Z of X)Q.unregister(Z);else if(Y)Q.unregisterByPlugin(Y);return{success:!0}}catch(B){return w.error("Failed to unregister routes",{error:B}),{success:!1,error:"Failed to unregister routes"}}}),A.messaging.subscribe("plugin:site-builder:route:list",async($)=>{try{let B=b90.parse($.payload);return{success:!0,data:{routes:Q.list(B.pluginId?B:void 0)}}}catch(B){return w.error("Failed to list routes",{error:B}),{success:!1,error:"Failed to list routes"}}}),A.messaging.subscribe("plugin:site-builder:route:get",async($)=>{try{let B=k90.parse($.payload);return{success:!0,data:{route:Q.get(B.path)}}}catch(B){return w.error("Failed to get route",{error:B}),{success:!1,error:"Failed to get route"}}}),A.messaging.subscribe("site-builder:routes:list",async()=>{return{success:!0,data:Q.list()}})}import{promises as gM2}from"fs";import{join as yM2}from"path";async function sX6(A,Q,w){let $=A.siteConfig.url??"https://example.com",B=Q.list(),X=MHA($,A.environment);await gM2.writeFile(yM2(A.outputDir,"robots.txt"),X,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=jHA(B,$);await gM2.writeFile(yM2(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${B.length} URLs`)}function TM2(A){let{context:Q,routeRegistry:w,logger:$}=A;Q.messaging.subscribe("site:build:completed",async(B)=>{try{let X=B.payload;return $.info(`Received site:build:completed event for ${X.environment} environment - generating SEO files`),await sX6(X,w,$),{success:!0}}catch(X){return $.error("Failed to generate SEO files",X),{success:!1}}})}$A();b0();var SM2=H.object({environment:H.enum(["preview","production"]).optional(),outputDir:H.string(),workingDir:H.string().optional(),enableContentGeneration:H.boolean().optional(),siteConfig:Vd.optional()});u7();u7();b0();var aX6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),tX6=H.object({blurb:H.string().optional()}),mM2=H.object({title:H.string(),description:H.string(),url:H.string().optional(),copyright:H.string().optional(),logo:H.boolean().optional(),themeMode:H.enum(["light","dark"]).optional(),analyticsScript:H.string().optional(),cta:aX6.optional(),sections:H.record(H.string(),tX6).optional()});async function l60(A,Q){try{let w=await A({type:Lr,payload:void 0});if("success"in w&&w.success&&w.data){let $=mM2.safeParse(w.data);if($.success)return mM2.parse({...Q,...$.data})}}catch{}return Q}class xHA extends p6{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:SM2,jobTypeName:"site-build"});this.sendMessage=Q,this.cfg=w}async process(A,Q,w){let $=A.environment??"preview",B=A.enableContentGeneration??!1;try{this.logger.debug("Starting site build job",{jobId:Q,environment:$,outputDir:A.outputDir}),await w.report({progress:0,total:100,message:`Starting site build for ${$} environment`});let X=w.createSub({scale:{start:10,end:90}}),Y=await l60(this.sendMessage,A.siteConfig??this.cfg.defaultSiteConfig),Z=await this.cfg.siteBuilder.build({outputDir:A.outputDir,workingDir:A.workingDir,sharedImagesDir:this.cfg.sharedImagesDir,enableContentGeneration:B,environment:$,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}},X.toCallback());if(await w.report({progress:100,total:100,message:`Site build completed: ${Z.routesBuilt} routes built`}),this.logger.debug("Site build job completed",{jobId:Q,environment:$,routesBuilt:Z.routesBuilt,success:Z.success}),Z.success){this.logger.info(`Emitting site:build:completed event for ${$} environment`);let W=$==="preview"?this.cfg.previewUrl??this.cfg.siteUrl:this.cfg.siteUrl;await this.sendMessage({type:"site:build:completed",payload:{outputDir:A.outputDir,environment:$,routesBuilt:Z.routesBuilt,siteConfig:{...Y,url:W},generateEntityUrl:(K,U)=>bY.getInstance().generateUrl(K,U)},broadcast:!0})}return{success:Z.success,routesBuilt:Z.routesBuilt,outputDir:A.outputDir,environment:$,...Z.errors&&{errors:Z.errors},...Z.warnings&&{warnings:Z.warnings}}}catch(X){throw this.logger.error("Site build job failed",X),X}}summarizeDataForLog(A){return{environment:A.environment,outputDir:A.outputDir}}}b0();u7();var eX6=H.object({slot:H.enum(gb).optional().default("primary"),limit:H.number().optional()});class RHA{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 $=eX6.parse(A??{});this.logger.debug("NavigationDataSource fetch called",{params:$});let B=this.routeRegistry.getNavigationItems($.slot),X=$.limit?B.slice(0,$.limit):B,Y=X.map((W)=>({label:W.label,href:W.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:X.length,items:Y});let Z={navigation:Y};return Q.parse(Z)}}u7();$A();b0();var AY6=H.object({environment:H.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function uM2(A,Q){return[j$(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'.",AY6,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}b0();u7();var QY6=H.object({id:H.string(),template:H.string(),content:H.unknown().optional(),dataQuery:H.looseObject({entityType:H.string().optional(),template:H.string().optional(),query:H.looseObject({id:H.string().optional(),limit:H.number().optional(),offset:H.number().optional()}).optional()}).optional(),order:H.number().optional()}),wY6=H.object({show:H.boolean().default(!1),label:H.string().optional(),slot:H.enum(gb).default("primary"),priority:H.number().min(0).max(100).default(50)}).optional(),$Y6=H.object({id:H.string(),path:H.string(),title:H.string().default(""),pageLabel:H.string().optional(),description:H.string().default(""),sections:H.array(QY6).default([]),layout:H.string().default("default"),fullscreen:H.boolean().optional(),pluginId:H.string().optional(),sourceEntityType:H.string().optional(),external:H.boolean().optional(),navigation:wY6}),cM2=H.object({previewOutputDir:H.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:H.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:H.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:H.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:Vd.default({title:"Brain",description:"A knowledge management system"}),themeCSS:H.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:H.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:H.any().optional().describe("Template definitions to register"),routes:H.array($Y6).optional().describe("Routes to register"),layouts:H.record(H.string(),H.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:H.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:H.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:H.record(H.string(),H.object({label:H.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:H.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:H.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:H.boolean().optional().describe("Enable pagination for list pages"),pageSize:H.number().optional().describe("Items per page (default: 10)"),navigation:H.object({show:H.boolean().optional().describe("Show in navigation"),slot:H.enum(gb).optional().describe("Navigation slot (primary or secondary)"),priority:H.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:H.record(H.string(),H.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 pM2={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.181",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 vHA extends Rw{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",pM2,{...A,layouts:Q},cM2);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new DN0(A.logger),this._slotRegistry=new uL0,A.messaging.subscribe("plugin:site-builder:slot:register",async(w)=>{let{slotName:$,pluginId:B,render:X,priority:Y}=w.payload;return this._slotRegistry?.register($,{pluginId:B,render:X,...Y!==void 0&&{priority:Y}}),{success:!0}}),A.messaging.subscribe("plugin:site-builder:head-script:register",async(w)=>{let{pluginId:$,script:B}=w.payload;return this.headScripts.set($,B),{success:!0}}),A.entities.registerDataSource(new RHA(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService={getProfile:()=>A.identity.getProfile()},EM2(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)zN0(this.config.routes,this.id,this.routeRegistry);let Q={entityService:A.entityService,sendMessage:A.messaging.send,resolveTemplateContent:(w,$)=>A.templates.resolve(w,$),getViewTemplate:(w)=>A.views.get(w),listViewTemplateNames:()=>A.views.list().map((w)=>w.name)};if(this.siteBuilder=t3.createFresh(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,void 0,this.config.entityDisplay),A.jobs.registerHandler("site-build",new xHA(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 fHA(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(Nr,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),TM2({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 uM2(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 l60(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(($)=>({id:$.id,template:$.template}))})),null,2)}]}}},{uri:"site://templates",name:"View Templates",description:"All registered view templates",mimeType:"application/json",handler:async()=>{let Q=A.views.list();return{contents:[{uri:"site://templates",mimeType:"application/json",text:JSON.stringify(Q.map((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 l60(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6779
6779
|
${[`**Title:** ${w.title}`,`**Description:** ${w.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
|
|
6780
6780
|
`)}
|
|
6781
6781
|
|
|
6782
6782
|
## Site Builder Actions
|
|
6783
6783
|
- When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
|
|
6784
|
-
- 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(),delete this.siteBuilder,this.logger.debug("Cleaned up all event subscriptions")}}function Ch(A={}){return new vHA(A)}$A();$A();b0();var CHA=H.object({routeId:H.string(),sectionId:H.string()}),XY6=H.object({routeId:H.string(),sectionId:H.string()}),d60=aQ.extend({entityType:H.literal("site-content"),template:H.string().optional(),content:H.string(),metadata:XY6});$A();class lM2 extends QQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:d60,frontmatterSchema:CHA})}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 hHA=new lM2;b0();var JN0=H.object({routeId:H.string().optional().describe("Optional: specific route filter"),sectionId:H.string().optional().describe("Optional: specific section filter"),dryRun:H.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:H.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),L65=H.object({jobs:H.array(H.object({jobId:H.string(),routeId:H.string(),sectionId:H.string()})),totalSections:H.number(),queuedSections:H.number(),skippedSections:H.number().optional(),batchId:H.string().optional()});b0();var YY6=H.looseObject({id:H.string(),template:H.string().optional(),content:H.unknown().optional()}),ZY6=H.looseObject({id:H.string(),title:H.string().optional(),description:H.string().optional(),sections:H.array(YY6)}),HY6=H.array(ZY6);class EHA{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=HY6.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let $=this.context.logger.child("SiteContentOperations"),B=await this.fetchRoutes(),X=B;if(A.routeId){if(X=B.filter((U)=>U.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let U of X)for(let G of U.sections){if(A.sectionId&&G.id!==A.sectionId)continue;if(G.content){$.debug("Section has static content, skipping",{routeId:U.id,sectionId:G.id});continue}if(G.template){let D=this.context.templates.getCapabilities(G.template);if(!D){$.warn("Template not found, skipping section",{routeId:U.id,sectionId:G.id,templateName:G.template});continue}if(!D.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:U.id,sectionId:G.id,templateName:G.template,capabilities:D});continue}}else{$.debug("Section has no template, skipping",{routeId:U.id,sectionId:G.id});continue}if(!A.force&&!A.dryRun){let D=`${U.id}:${G.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){$.debug("Content already exists, skipping",{routeId:U.id,sectionId:G.id});continue}}Y.push({route:U,section:G})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let W=[],K=[];for(let{route:U,section:G}of Y){let D=`${U.id}:${G.id}`,z=G.template,V={routeId:U.id,sectionId:G.id,entityId:D,entityType:"site-content",templateName:z,context:{prompt:typeof G.content==="string"?G.content:void 0,data:{routeId:U.id,sectionId:G.id,routeTitle:U.title,routeDescription:U.description,sectionContent:G.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:V})}if(K.length>0){let U=this.createJobOptions(w,"site:content-generation"),G=await this.context.jobs.enqueueBatch(K,U);for(let D=0;D<Y.length;D++){let z=Y[D];if(z)W.push({jobId:`${G}-${D}`,routeId:z.route.id,sectionId:z.section.id})}return{jobs:W,totalSections:Z,queuedSections:W.length,batchId:G}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class gHA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new EHA(A)}async generateContent(A,Q){let w=JN0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}u7();b0();var WY6=H.object({namespace:H.string(),sections:H.record(H.string(),H.any())}),dM2=H.custom((A)=>WY6.safeParse(A).success),yHA=H.object({definitions:H.union([dM2,H.array(dM2)]).optional()});$A();function iM2(A,Q){return[j$(Q,"generate","Generate content for all routes, a specific route, or a specific section",JN0,async(w,$)=>{let B=A();if(!B)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 X={rootJobId:`generate-${Date.now()}`,progressToken:$.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:$.interfaceType,channelId:$.channelId},Y=await B.generateContent(w,X);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var nM2={name:"@brains/site-content",version:"0.2.0-alpha.180",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 THA extends Rw{siteContentService;constructor(A={}){super("site-content",nM2,A,yHA)}async onRegister(A){A.entities.register("site-content",d60,hHA);for(let Q of EP(this.config.definitions))A.templates.register(db(Q),Q.namespace);this.siteContentService=new gHA(A)}async getTools(){return iM2(()=>this.siteContentService,this.id)}}function hh(A={}){return new THA(A)}$A();u7();$A();b0();u7();var UY6=H.object({}),GY6=H.object({}),i60=aQ.extend({id:H.literal("site-info"),entityType:H.literal("site-info"),metadata:GY6});var Fd=ov0.omit({url:!0,analyticsScript:!0});$A();b0();var DY6=H.record(H.string(),H.unknown());class DF extends QQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:i60,frontmatterSchema:Fd,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=Fd.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("",DY6.parse(Q))}}class qF{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return qF.instance??=new qF(A,Q,w),qF.instance}static resetInstance(){qF.instance=null}static createFresh(A,Q,w){return new qF(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new DF;let $=qF.getDefaultSiteInfo();this.defaultSiteInfo={...$,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let 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}}b0();var qY6=new DF,zY6=H.looseObject({platform:H.string(),url:H.string(),label:H.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),JY6=H.looseObject({socialLinks:H.array(zY6).optional()});class VN0{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:$}=w,B;try{let Z=await $.getEntity({entityType:"site-info",id:"site-info"});B=Z?qY6.parseSiteInfoBody(Z.content):{title:"Brain",description:"A knowledge management system"}}catch{B={title:"Brain",description:"A knowledge management system"}}let X;try{let Z=await $.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Z){let W=JY6.safeParse(Z.metadata);X=W.success?W.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var rM2={name:"@brains/site-info",version:"0.2.0-alpha.180",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 FY6=new DF,IY6="site-info";class SHA extends jw{entityType=IY6;schema=i60;adapter=FY6;defaultSiteInfo;constructor(A){super("site-info",rM2,{},yX);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new VN0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=qF.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(Lr,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let B=await Q.getSiteInfo();await A.messaging.send({type:Nr,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Eh(A){return new SHA(A)}var LY6=new DF;async function n60(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 LY6.parseSiteInfoBody(w.content)}function oM2(A,Q){let w=A.metadata.publishedAt??A.created,$=Q.metadata.publishedAt??Q.created;return new Date($).getTime()-new Date(w).getTime()}async function FN0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(oM2).slice(0,Q.count).map(Q.parse)}function mHA(A){if(!A)throw Error("CTA not configured in site-info");return A}b0();var sM2=H.object({label:H.string(),href:H.string(),priority:H.number()}),NY6=H.object({primary:H.array(sM2),secondary:H.array(sM2)}),_Y6=H.object({platform:H.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:H.string().describe("Profile or contact URL"),label:H.string().optional().describe("Optional display label")}),bY6=Fd.extend({navigation:NY6,copyright:H.string(),socialLinks:H.array(_Y6).optional().describe("Social media links from profile entity")});$A();TU();Nd();b0();var uHA=H.object({defaultPrompt:H.string().default("Write a blog post about my recent work and insights"),paginate:H.boolean().default(!0),pageSize:H.number().default(10)});$A();g$();R2();b0();var jY6=H.object({prompt:H.string().optional(),title:H.string().optional(),content:H.string().optional(),excerpt:H.string().optional(),coverImageId:H.string().optional(),seriesName:H.string().optional(),seriesIndex:H.number().optional(),skipAi:H.boolean().optional()}),s$5=JK.extend({title:H.string().optional(),slug:H.string().optional()});class cHA extends pY{constructor(A,Q){super(A,Q,{schema:jY6,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:$,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:W,excerpt:K}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");W=W??`## Introduction
|
|
6784
|
+
- 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(),delete this.siteBuilder,this.logger.debug("Cleaned up all event subscriptions")}}function Ch(A={}){return new vHA(A)}$A();$A();b0();var CHA=H.object({routeId:H.string(),sectionId:H.string()}),XY6=H.object({routeId:H.string(),sectionId:H.string()}),d60=aQ.extend({entityType:H.literal("site-content"),template:H.string().optional(),content:H.string(),metadata:XY6});$A();class lM2 extends QQ{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:d60,frontmatterSchema:CHA})}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 hHA=new lM2;b0();var JN0=H.object({routeId:H.string().optional().describe("Optional: specific route filter"),sectionId:H.string().optional().describe("Optional: specific section filter"),dryRun:H.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:H.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),L65=H.object({jobs:H.array(H.object({jobId:H.string(),routeId:H.string(),sectionId:H.string()})),totalSections:H.number(),queuedSections:H.number(),skippedSections:H.number().optional(),batchId:H.string().optional()});b0();var YY6=H.looseObject({id:H.string(),template:H.string().optional(),content:H.unknown().optional()}),ZY6=H.looseObject({id:H.string(),title:H.string().optional(),description:H.string().optional(),sections:H.array(YY6)}),HY6=H.array(ZY6);class EHA{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=HY6.safeParse(A.data);if(!Q.success)throw Error("Failed to parse routes from site-builder");return Q.data}async generate(A,Q,w){let $=this.context.logger.child("SiteContentOperations"),B=await this.fetchRoutes(),X=B;if(A.routeId){if(X=B.filter((U)=>U.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let U of X)for(let G of U.sections){if(A.sectionId&&G.id!==A.sectionId)continue;if(G.content){$.debug("Section has static content, skipping",{routeId:U.id,sectionId:G.id});continue}if(G.template){let D=this.context.templates.getCapabilities(G.template);if(!D){$.warn("Template not found, skipping section",{routeId:U.id,sectionId:G.id,templateName:G.template});continue}if(!D.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:U.id,sectionId:G.id,templateName:G.template,capabilities:D});continue}}else{$.debug("Section has no template, skipping",{routeId:U.id,sectionId:G.id});continue}if(!A.force&&!A.dryRun){let D=`${U.id}:${G.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:D})){$.debug("Content already exists, skipping",{routeId:U.id,sectionId:G.id});continue}}Y.push({route:U,section:G})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let W=[],K=[];for(let{route:U,section:G}of Y){let D=`${U.id}:${G.id}`,z=G.template,V={routeId:U.id,sectionId:G.id,entityId:D,entityType:"site-content",templateName:z,context:{prompt:typeof G.content==="string"?G.content:void 0,data:{routeId:U.id,sectionId:G.id,routeTitle:U.title,routeDescription:U.description,sectionContent:G.content},conversationId:"system"},siteConfig:Q};K.push({type:"shell:content-generation",data:V})}if(K.length>0){let U=this.createJobOptions(w,"site:content-generation"),G=await this.context.jobs.enqueueBatch(K,U);for(let D=0;D<Y.length;D++){let z=Y[D];if(z)W.push({jobId:`${G}-${D}`,routeId:z.route.id,sectionId:z.section.id})}return{jobs:W,totalSections:Z,queuedSections:W.length,batchId:G}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class gHA{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new EHA(A)}async generateContent(A,Q){let w=JN0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}u7();b0();var WY6=H.object({namespace:H.string(),sections:H.record(H.string(),H.any())}),dM2=H.custom((A)=>WY6.safeParse(A).success),yHA=H.object({definitions:H.union([dM2,H.array(dM2)]).optional()});$A();function iM2(A,Q){return[j$(Q,"generate","Generate content for all routes, a specific route, or a specific section",JN0,async(w,$)=>{let B=A();if(!B)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 X={rootJobId:`generate-${Date.now()}`,progressToken:$.progressToken,pluginId:Q,operationType:"content_operations",interfaceType:$.interfaceType,channelId:$.channelId},Y=await B.generateContent(w,X);return{success:!0,message:`Generated ${Y.queuedSections} of ${Y.totalSections} sections. ${Y.queuedSections>0?"Jobs are running in the background.":"No new content to generate."}`,data:{batchId:Y.batchId,jobsQueued:Y.queuedSections,totalSections:Y.totalSections,jobs:Y.jobs}}})]}var nM2={name:"@brains/site-content",version:"0.2.0-alpha.181",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 THA extends Rw{siteContentService;constructor(A={}){super("site-content",nM2,A,yHA)}async onRegister(A){A.entities.register("site-content",d60,hHA);for(let Q of EP(this.config.definitions))A.templates.register(db(Q),Q.namespace);this.siteContentService=new gHA(A)}async getTools(){return iM2(()=>this.siteContentService,this.id)}}function hh(A={}){return new THA(A)}$A();u7();$A();b0();u7();var UY6=H.object({}),GY6=H.object({}),i60=aQ.extend({id:H.literal("site-info"),entityType:H.literal("site-info"),metadata:GY6});var Fd=ov0.omit({url:!0,analyticsScript:!0});$A();b0();var DY6=H.record(H.string(),H.unknown());class DF extends QQ{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:i60,frontmatterSchema:Fd,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=Fd.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("",DY6.parse(Q))}}class qF{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return qF.instance??=new qF(A,Q,w),qF.instance}static resetInstance(){qF.instance=null}static createFresh(A,Q,w){return new qF(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new DF;let $=qF.getDefaultSiteInfo();this.defaultSiteInfo={...$,...w}}async initialize(){try{if(!await this.entityService.getEntity({entityType:"site-info",id:"site-info"})){if(await this.entityService.getEntity({entityType:"site-info",id:"site-info"}))return;this.logger.info("No site info found, creating default site info");let 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}}b0();var qY6=new DF,zY6=H.looseObject({platform:H.string(),url:H.string(),label:H.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),JY6=H.looseObject({socialLinks:H.array(zY6).optional()});class VN0{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:$}=w,B;try{let Z=await $.getEntity({entityType:"site-info",id:"site-info"});B=Z?qY6.parseSiteInfoBody(Z.content):{title:"Brain",description:"A knowledge management system"}}catch{B={title:"Brain",description:"A knowledge management system"}}let X;try{let Z=await $.getEntity({entityType:"anchor-profile",id:"anchor-profile"});if(Z){let W=JY6.safeParse(Z.metadata);X=W.success?W.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var rM2={name:"@brains/site-info",version:"0.2.0-alpha.181",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 FY6=new DF,IY6="site-info";class SHA extends jw{entityType=IY6;schema=i60;adapter=FY6;defaultSiteInfo;constructor(A){super("site-info",rM2,{},yX);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new VN0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=qF.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(Lr,async()=>{return{success:!0,data:await Q.getSiteInfo()}}),A.messaging.subscribe("entity:updated",async(w)=>{if(w.payload.entityType==="site-info"){let B=await Q.getSiteInfo();await A.messaging.send({type:Nr,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function Eh(A){return new SHA(A)}var LY6=new DF;async function n60(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 LY6.parseSiteInfoBody(w.content)}function oM2(A,Q){let w=A.metadata.publishedAt??A.created,$=Q.metadata.publishedAt??Q.created;return new Date($).getTime()-new Date(w).getTime()}async function FN0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(oM2).slice(0,Q.count).map(Q.parse)}function mHA(A){if(!A)throw Error("CTA not configured in site-info");return A}b0();var sM2=H.object({label:H.string(),href:H.string(),priority:H.number()}),NY6=H.object({primary:H.array(sM2),secondary:H.array(sM2)}),_Y6=H.object({platform:H.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:H.string().describe("Profile or contact URL"),label:H.string().optional().describe("Optional display label")}),bY6=Fd.extend({navigation:NY6,copyright:H.string(),socialLinks:H.array(_Y6).optional().describe("Social media links from profile entity")});$A();TU();Nd();b0();var uHA=H.object({defaultPrompt:H.string().default("Write a blog post about my recent work and insights"),paginate:H.boolean().default(!0),pageSize:H.number().default(10)});$A();g$();R2();b0();var jY6=H.object({prompt:H.string().optional(),title:H.string().optional(),content:H.string().optional(),excerpt:H.string().optional(),coverImageId:H.string().optional(),seriesName:H.string().optional(),seriesIndex:H.number().optional(),skipAi:H.boolean().optional()}),s$5=JK.extend({title:H.string().optional(),slug:H.string().optional()});class cHA extends pY{constructor(A,Q){super(A,Q,{schema:jY6,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:$,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:W,excerpt:K}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");W=W??`## Introduction
|
|
6785
6785
|
|
|
6786
6786
|
Add your introduction here.
|
|
6787
6787
|
|
|
@@ -7001,7 +7001,7 @@ ${w.content}`,templateName:"blog:excerpt"})})}$A();Nd();TU();function aY6(A){let
|
|
|
7001
7001
|
letter-spacing: 0.02em;
|
|
7002
7002
|
}
|
|
7003
7003
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
7004
|
-
`}},void 0,!1,void 0,this),BY("header",{className:"printable-hero",children:[BY("div",{className:"printable-masthead",children:Q.brandLabel&&BY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),BY("div",{children:[BY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&BY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),BY("div",{className:"printable-meta",children:[Q.author&&BY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&BY("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&&BY("figure",{className:"printable-cover-wrap",children:BY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),BY(L4,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&BY("footer",{className:"printable-footer",children:[BY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&BY("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 CZ6=26214400,hZ6=60000;class eHA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==_N0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=EZ6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await fZ6(vZ6(RZ6(),"brain-blog-printable-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/printable/post/${Q.id}`,template:Vj2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:CZ6,timeoutMs:hZ6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${gZ6(Q)}-printable.pdf`}}finally{await X.close()}}finally{await xZ6($,{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}=M$(A.content),w=R5.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function EZ6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=R5.parse(w);return{title:B.title,body:$,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.canonicalUrl?{canonicalUrl:B.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function gZ6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}import{mkdtemp as uZ6,rm as cZ6}from"fs/promises";import{tmpdir as pZ6}from"os";import{join as lZ6}from"path";Q4();R2();TU();b0();import{jsxDEV as mZ6}from"preact/jsx-dev-runtime";var e60="og-image",yZ6="blog:og-image",Fj2=H.object({title:H.string().min(1),excerpt:H.string().optional(),author:H.string().optional(),publishedAt:H.string().optional(),brandLabel:H.string().optional(),coverImageUrl:H.string().optional()}),Ij2={name:yZ6,pluginId:"blog",schema:Fj2,renderers:{image:SZ6}};function TZ6(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 SZ6(A){let Q=Fj2.parse(A);return mZ6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:TZ6(Q.publishedAt)},void 0,!1,void 0,this)}var dZ6={width:1200,height:630},iZ6=60000;class AWA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??t60}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==e60)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=nZ6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await uZ6(lZ6(pZ6(),"brain-blog-og-image-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/og/post/${Q.id}`,template:Ij2,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),dZ6,{timeoutMs:iZ6,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${rZ6(Q)}-og.png`}}finally{await X.close()}}finally{await cZ6($,{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}=M$(A.content),w=R5.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function nZ6(A,Q={}){let{frontmatter:w}=M$(A.content),$=R5.parse(w);return{title:$.title,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function rZ6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}var Lj2={name:"@brains/blog",version:"0.2.0-alpha.180",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 QWA extends jw{entityType=R_.entityType;schema=Id;adapter=R_;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Lj2,A,uHA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new cHA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return wj2()}getDataSources(){return[new lHA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (bj2(),_j2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),$j2(A,this.logger),Bj2(A,this.logger),Yj2(A,this.logger),Zj2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",_N0,new eHA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",e60,new AWA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=fB.getInstance().register(nHA()),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:e60,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 wWA(A={}){return new QWA(A)}TU();Nd();$A();b0();z9();$A();b0();var qz=H.object({title:H.string(),slug:H.string(),coverImageId:H.string().optional()}),aZ6=H.object({title:H.string(),slug:H.string()}),tZ6=H.object({title:H.string(),slug:H.string()}),cj=aQ.extend({entityType:H.literal("series"),metadata:tZ6}),bN0=cj.extend({frontmatter:qz}),eZ6=bN0.extend({description:H.string().optional(),postCount:H.number(),coverImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),kj2=H.object({description:H.string().optional()});function Sh(A){return new R6(kj2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}$A();class $WA extends QQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:cj,frontmatterSchema:qz,supportsCoverImage:!0,bodyFormatter:Sh("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,qz).coverImageId,w=Sh(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=Sh(A.metadata.title).format(w);return this.buildMarkdown(X,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,qz);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,qz);return Sh(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var pj=new $WA;$A();R2();wH();b0();var AH6=H.object({seriesName:H.string().optional(),seriesIndex:H.number().optional()});function kN0(A){let Q=AH6.safeParse(A);return Q.success?Q.data:{}}function mh(A){return kN0(A.metadata).seriesName}function Pj2(A){return kN0(A.metadata).seriesIndex}function Mj2(A,Q){let w=Pj2(A)??Number.MAX_SAFE_INTEGER,$=Pj2(Q)??Number.MAX_SAFE_INTEGER;return w-$}class BWA{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((B)=>[B.id,B])),$=new Set;for(let B of A){let X=F1(B);$.add(X);let Y=w.get(X),Z=Y?.content??this.createSeriesContent(B),W=mw(Z);if(Y?.contentHash===W)continue;let K={id:X,entityType:"series",content:Z,contentHash:W,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:F1(B)}};await this.entityService.upsertEntity({entity:K}),this.logger.debug(`Upserted series: ${B}`)}for(let B of Q)if(!$.has(B.id))await this.entityService.deleteEntity({entityType:"series",id:B.id}),this.logger.debug(`Deleted orphaned series: ${B.id}`)}async handleEntityChange(A,Q){let w=mh(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=F1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let $=this.createSeriesContent(A),B={id:Q,entityType:"series",content:$,contentHash:mw($),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:F1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=F1(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 $=await this.entityService.listEntities({entityType:w});for(let B of $){let X=mh(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:F1(A)};return Y7("",Q)}}$A();b0();var QH6=H.object({entityType:H.literal("series"),query:H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional()})}),wH6=H.object({type:H.enum(["list","detail"]),seriesName:H.string().optional()});function $H6(A){let Q=wH6.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=QH6.safeParse(A);if(w.success){let{query:$}=w.data;if($.id)return{type:"detail",seriesSlug:$.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function jj2(A){let Q=DQ(A.content,qz);return bN0.parse({...A,frontmatter:Q.metadata})}class XWA{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 $=$H6(A),B=w.entityService;if($.type==="list")return this.fetchSeriesList(Q,B);if($.seriesName)return this.fetchSeriesDetail($.seriesName,Q,B);if($.seriesSlug)return this.fetchSeriesDetailBySlug($.seriesSlug,Q,B);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),$=await this.countEntitiesPerSeries(Q),B=w.map((X)=>{let Y=jj2(X),Z=pj.parseBody(X.content);return{...Y,description:Z.description,postCount:$.get(X.metadata.title)??0}});return this.logger.debug(`Found ${B.length} series entities`),A.parse({series:B})}async fetchSeriesDetail(A,Q,w,$){if(!$)$=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!$)throw Error(`Series not found: ${A}`);let B=jj2($),X=pj.parseBody($.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:{...B,description:X.description,postCount:Y.length},description:X.description})}async fetchSeriesDetailBySlug(A,Q,w){let B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!B)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail(B.metadata.title,Q,w,B)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let $ of w){if($==="series")continue;let B=await A.listEntities({entityType:$});for(let X of B){let Y=mh(X);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],$=Q.getEntityTypes();for(let B of $){if(B==="series")continue;let X=await Q.listEntities({entityType:B,options:{filter:{metadata:{seriesName:A}}}});w.push(...X)}return w.sort(Mj2),w}}$A();b0();wH();var BH6=H.object({prompt:H.string().optional(),title:H.string().optional(),seriesId:H.string().optional()}),XH6=H.object({title:H.string().optional(),excerpt:H.string().optional()});class PN0{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 $=await this.gatherMemberSummaries(w.metadata.title);if($.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let B=A.prompt??`Series name: ${w.metadata.title}
|
|
7004
|
+
`}},void 0,!1,void 0,this),BY("header",{className:"printable-hero",children:[BY("div",{className:"printable-masthead",children:Q.brandLabel&&BY("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),BY("div",{children:[BY("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&BY("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),BY("div",{className:"printable-meta",children:[Q.author&&BY("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&BY("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&&BY("figure",{className:"printable-cover-wrap",children:BY("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),BY(L4,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&BY("footer",{className:"printable-footer",children:[BY("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&BY("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 CZ6=26214400,hZ6=60000;class eHA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==_N0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=EZ6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await fZ6(vZ6(RZ6(),"brain-blog-printable-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/printable/post/${Q.id}`,template:Vj2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:CZ6,timeoutMs:hZ6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${gZ6(Q)}-printable.pdf`}}finally{await X.close()}}finally{await xZ6($,{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}=M$(A.content),w=R5.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function EZ6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=R5.parse(w);return{title:B.title,body:$,...B.excerpt?{excerpt:B.excerpt}:{},...B.author?{author:B.author}:{},...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.canonicalUrl?{canonicalUrl:B.canonicalUrl}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function gZ6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}import{mkdtemp as uZ6,rm as cZ6}from"fs/promises";import{tmpdir as pZ6}from"os";import{join as lZ6}from"path";Q4();R2();TU();b0();import{jsxDEV as mZ6}from"preact/jsx-dev-runtime";var e60="og-image",yZ6="blog:og-image",Fj2=H.object({title:H.string().min(1),excerpt:H.string().optional(),author:H.string().optional(),publishedAt:H.string().optional(),brandLabel:H.string().optional(),coverImageUrl:H.string().optional()}),Ij2={name:yZ6,pluginId:"blog",schema:Fj2,renderers:{image:SZ6}};function TZ6(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 SZ6(A){let Q=Fj2.parse(A);return mZ6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:TZ6(Q.publishedAt)},void 0,!1,void 0,this)}var dZ6={width:1200,height:630},iZ6=60000;class AWA{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??t60}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==e60)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=nZ6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await uZ6(lZ6(pZ6(),"brain-blog-og-image-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/og/post/${Q.id}`,template:Ij2,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),dZ6,{timeoutMs:iZ6,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${rZ6(Q)}-og.png`}}finally{await X.close()}}finally{await cZ6($,{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}=M$(A.content),w=R5.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function nZ6(A,Q={}){let{frontmatter:w}=M$(A.content),$=R5.parse(w);return{title:$.title,...$.excerpt?{excerpt:$.excerpt}:{},...$.author?{author:$.author}:{},...$.publishedAt?{publishedAt:$.publishedAt}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function rZ6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}var Lj2={name:"@brains/blog",version:"0.2.0-alpha.181",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 QWA extends jw{entityType=R_.entityType;schema=Id;adapter=R_;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",Lj2,A,uHA)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new cHA(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return wj2()}getDataSources(){return[new lHA(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (bj2(),_j2));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),$j2(A,this.logger),Bj2(A,this.logger),Yj2(A,this.logger),Zj2(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",_N0,new eHA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",e60,new AWA(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=fB.getInstance().register(nHA()),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:e60,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 wWA(A={}){return new QWA(A)}TU();Nd();$A();b0();z9();$A();b0();var qz=H.object({title:H.string(),slug:H.string(),coverImageId:H.string().optional()}),aZ6=H.object({title:H.string(),slug:H.string()}),tZ6=H.object({title:H.string(),slug:H.string()}),cj=aQ.extend({entityType:H.literal("series"),metadata:tZ6}),bN0=cj.extend({frontmatter:qz}),eZ6=bN0.extend({description:H.string().optional(),postCount:H.number(),coverImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),kj2=H.object({description:H.string().optional()});function Sh(A){return new R6(kj2,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}$A();class $WA extends QQ{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:cj,frontmatterSchema:qz,supportsCoverImage:!0,bodyFormatter:Sh("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,qz).coverImageId,w=Sh(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=Sh(A.metadata.title).format(w);return this.buildMarkdown(X,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,qz);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,qz);return Sh(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var pj=new $WA;$A();R2();wH();b0();var AH6=H.object({seriesName:H.string().optional(),seriesIndex:H.number().optional()});function kN0(A){let Q=AH6.safeParse(A);return Q.success?Q.data:{}}function mh(A){return kN0(A.metadata).seriesName}function Pj2(A){return kN0(A.metadata).seriesIndex}function Mj2(A,Q){let w=Pj2(A)??Number.MAX_SAFE_INTEGER,$=Pj2(Q)??Number.MAX_SAFE_INTEGER;return w-$}class BWA{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((B)=>[B.id,B])),$=new Set;for(let B of A){let X=F1(B);$.add(X);let Y=w.get(X),Z=Y?.content??this.createSeriesContent(B),W=mw(Z);if(Y?.contentHash===W)continue;let K={id:X,entityType:"series",content:Z,contentHash:W,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:F1(B)}};await this.entityService.upsertEntity({entity:K}),this.logger.debug(`Upserted series: ${B}`)}for(let B of Q)if(!$.has(B.id))await this.entityService.deleteEntity({entityType:"series",id:B.id}),this.logger.debug(`Deleted orphaned series: ${B.id}`)}async handleEntityChange(A,Q){let w=mh(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=F1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let $=this.createSeriesContent(A),B={id:Q,entityType:"series",content:$,contentHash:mw($),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:F1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=F1(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 $=await this.entityService.listEntities({entityType:w});for(let B of $){let X=mh(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:F1(A)};return Y7("",Q)}}$A();b0();var QH6=H.object({entityType:H.literal("series"),query:H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional()})}),wH6=H.object({type:H.enum(["list","detail"]),seriesName:H.string().optional()});function $H6(A){let Q=wH6.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=QH6.safeParse(A);if(w.success){let{query:$}=w.data;if($.id)return{type:"detail",seriesSlug:$.id};return{type:"list"}}throw Error('Invalid series query format. Expected { type: "list"|"detail" } or { entityType: "series", query: { id?: string } }')}function jj2(A){let Q=DQ(A.content,qz);return bN0.parse({...A,frontmatter:Q.metadata})}class XWA{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 $=$H6(A),B=w.entityService;if($.type==="list")return this.fetchSeriesList(Q,B);if($.seriesName)return this.fetchSeriesDetail($.seriesName,Q,B);if($.seriesSlug)return this.fetchSeriesDetailBySlug($.seriesSlug,Q,B);throw Error("Invalid series query: must specify seriesName or slug for detail")}async fetchSeriesList(A,Q){let w=await Q.listEntities({entityType:"series"}),$=await this.countEntitiesPerSeries(Q),B=w.map((X)=>{let Y=jj2(X),Z=pj.parseBody(X.content);return{...Y,description:Z.description,postCount:$.get(X.metadata.title)??0}});return this.logger.debug(`Found ${B.length} series entities`),A.parse({series:B})}async fetchSeriesDetail(A,Q,w,$){if(!$)$=(await w.listEntities({entityType:"series",options:{filter:{metadata:{title:A}}}}))[0];if(!$)throw Error(`Series not found: ${A}`);let B=jj2($),X=pj.parseBody($.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:{...B,description:X.description,postCount:Y.length},description:X.description})}async fetchSeriesDetailBySlug(A,Q,w){let B=(await w.listEntities({entityType:"series",options:{filter:{metadata:{slug:A}}}}))[0];if(!B)throw Error(`Series not found with slug: ${A}`);return this.fetchSeriesDetail(B.metadata.title,Q,w,B)}async countEntitiesPerSeries(A){let Q=new Map,w=A.getEntityTypes();for(let $ of w){if($==="series")continue;let B=await A.listEntities({entityType:$});for(let X of B){let Y=mh(X);if(Y)Q.set(Y,(Q.get(Y)??0)+1)}}return Q}async getSeriesMembers(A,Q){let w=[],$=Q.getEntityTypes();for(let B of $){if(B==="series")continue;let X=await Q.listEntities({entityType:B,options:{filter:{metadata:{seriesName:A}}}});w.push(...X)}return w.sort(Mj2),w}}$A();b0();wH();var BH6=H.object({prompt:H.string().optional(),title:H.string().optional(),seriesId:H.string().optional()}),XH6=H.object({title:H.string().optional(),excerpt:H.string().optional()});class PN0{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 $=await this.gatherMemberSummaries(w.metadata.title);if($.length===0)return{success:!1,error:`No members found in series: ${w.metadata.title}`};let B=A.prompt??`Series name: ${w.metadata.title}
|
|
7005
7005
|
|
|
7006
7006
|
Content in this series:
|
|
7007
7007
|
${$.join(`
|
|
@@ -7013,7 +7013,7 @@ Your task is to write a series description (2-3 sentences) that:
|
|
|
7013
7013
|
3. Is engaging and makes readers want to explore the content
|
|
7014
7014
|
4. Works well as a series overview on a website
|
|
7015
7015
|
|
|
7016
|
-
Be concise and focus on what makes this series unique and valuable.`});async function Ej2({entity:A,config:Q}){let w=cj.parse(A),$=pj.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...$.description&&{description:$.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 YWA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:I$["ai.rizom.brain.series"],validate:!1,buildRecord:Ej2}}var gj2={name:"@brains/series",version:"0.2.0-alpha.
|
|
7016
|
+
Be concise and focus on what makes this series unique and valuable.`});async function Ej2({entity:A,config:Q}){let w=cj.parse(A),$=pj.parseBody(w.content);return{$type:"ai.rizom.brain.series",title:w.metadata.title,slug:w.metadata.slug,...$.description&&{description:$.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 YWA(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:I$["ai.rizom.brain.series"],validate:!1,buildRecord:Ej2}}var gj2={name:"@brains/series",version:"0.2.0-alpha.181",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 yj2=H.discriminatedUnion("mode",[H.object({mode:H.literal("derive"),reason:H.string().optional()}),H.object({mode:H.literal("source"),entityId:H.string(),entityType:H.string(),seriesName:H.string().optional(),previousSeriesName:H.string().optional()})]);class ZWA extends jw{entityType="series";schema=cj;adapter=pj;manager;unregisterAtprotoProjection;constructor(){super("series",gj2,{},yX)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new PN0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...Cj2(),description:hj2}}getDataSources(){return[new XWA(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=mh(Q.entity),$=kN0(Q.previousMetadata).seriesName;if(!w&&!$)return null;return{mode:"source",entityId:Q.entity.id,entityType:Q.entity.entityType,...w?{seriesName:w}:{},...$&&$!==w?{previousSeriesName:$}:{}}},jobOptions:(Q)=>{if(!Q.entity)return;return this.getSourceProjectionJobOptions(Q.entity)}}}]}async onRegister(A){this.manager=new BWA(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=fB.getInstance().register(YWA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=yj2.parse(Q);if(w.mode==="derive")return await this.projectAll(A),{success:!0};let $=await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if($)await this.projectSource($,w.previousSeriesName);else{let B=this.requireManager();for(let X of[w.seriesName,w.previousSeriesName])if(X)await B.cleanupOrphanedSeries(X)}return{success:!0}},validateAndParse:(Q)=>{let w=yj2.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 PN0(this.logger.child("SeriesGenerationHandler"),A),w=await A.entityService.listEntities({entityType:"series"});for(let $ of w)try{if(!this.adapter.parseBody($.content).description)this.logger.info(`Generating description for series: ${$.metadata.title}`),await Q.process({seriesId:$.id})}catch(B){this.logger.error(`Failed to generate description for series: ${$.id}`,{error:B})}}}function HWA(){return new ZWA}$A();b0();$A();R2();b0();$A();var Tj2=H.enum(["generating","draft","queued","published","failed"]),Sj2=H.enum(["generating","draft","queued","published","failed"]),WWA="publishedAt is required when deck status is published",KWA=(A)=>A.status==="published"&&!A.publishedAt,UWA=(A)=>{if(KWA(A))throw Error(WWA)},zF=H.object({title:H.string(),slug:H.string().optional(),description:H.string().optional(),author:H.string().optional(),status:Tj2,publishedAt:H.string().datetime().optional(),event:H.string().optional(),coverImageId:H.string().optional(),ogImageId:H.string().optional()}),p95=H.object({title:H.string(),description:H.string().optional(),status:Tj2,publishedAt:H.string().datetime().optional(),coverImageId:H.string().optional(),slug:H.string(),error:H.string().optional()}).superRefine((A,Q)=>{if(!KWA(A))return;Q.addIssue({code:H.ZodIssueCode.custom,path:["publishedAt"],message:WWA})}),qH6=H.object({title:H.string(),description:H.string().optional(),status:Sj2,publishedAt:H.string().datetime().optional(),coverImageId:H.string().optional(),slug:H.string(),error:H.string().optional()}).superRefine((A,Q)=>{if(!KWA(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:WWA})}),zH6=H.object({title:H.string(),slug:H.string().optional(),description:H.string().optional(),author:H.string().optional(),status:Sj2,publishedAt:H.string().datetime().optional(),event:H.string().optional(),coverImageId:H.string().optional(),ogImageId:H.string().optional()}),bd=aQ.extend({entityType:H.literal("deck"),metadata:qH6}),MN0=bd.extend({frontmatter:zH6,body:H.string(),ogImageUrl:H.string().optional()}),A$0=MN0.extend({url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});class GWA extends QQ{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:bd,frontmatterSchema:zF,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,zF);UWA(w);let $={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontmatter(A),w=this.extractBody(A);UWA(Q),this.validateSlideStructure(w);let $=Q.slug??F1(Q.title),B=Q.status;return{entityType:"deck",content:A,metadata:{slug:$,title:Q.title,description:Q.description,status:B,publishedAt:Q.publishedAt,coverImageId:Q.coverImageId}}}generateTitle(A){return A.metadata.title}generateSummary(A){if(A.metadata.description)return A.metadata.description;return`Presentation: ${A.metadata.title}`}generateFrontMatter(A){return this.toMarkdown(A)}buildStub(A){let Q={title:A.title,slug:A.id,status:"generating"};return{content:this.buildMarkdown(`---
|
|
7017
7017
|
`,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var Q$0=new GWA;b0();y8();var JH6=H.object({markdown:H.string().describe("Markdown content with slide separators (---)"),deck:A$0.optional()}),DWA=$2({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:JH6,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:fXA,fullscreen:!0}});y8();b0();var qWA=H.object({decks:H.array(MN0)}),zWA=H.object({decks:H.array(A$0),pageTitle:H.string().optional(),pageLabel:H.string().optional()});import{jsxDEV as JWA}from"preact/jsx-dev-runtime";var VH6="Presentations",VWA=({decks:A,pageLabel:Q})=>{let w=A.map((B)=>({id:B.id,url:B.url,title:B.frontmatter.title,date:B.frontmatter.publishedAt??B.created,description:B.frontmatter.description}));return JWA("div",{className:"deck-list bg-theme",children:JWA("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:JWA(dw0,{label:Q&&Q!=="Decks"?Q:VH6,items:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};z9();class jN0 extends R6{constructor(){super(qWA,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var FWA=$2({name:"deck-list",description:"List view of all presentation decks",schema:zWA,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new jN0,layout:{component:VWA}});b0();$A();var FH6=H.object({title:H.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:H.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:H.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),mj2=$2({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:FH6,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
|
|
7018
7018
|
|
|
7019
7019
|
Your task is to generate a complete slide deck based on the user's prompt.
|
|
@@ -7321,7 +7321,7 @@ ${Z}`,templateName:"decks:description"})).description,await this.reportProgress(
|
|
|
7321
7321
|
color: var(--carousel-accent);
|
|
7322
7322
|
font-weight: 600;
|
|
7323
7323
|
}
|
|
7324
|
-
`}},void 0,!1,void 0,this),B.map((K,U)=>VZ("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[VZ("header",{className:"deck-carousel-header",children:VZ("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[VZ("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VZ(kH6,{children:[VZ("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VZ("span",{className:"wm-secondary",children:X.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),VZ("div",{className:"deck-carousel-body",children:VZ("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:W(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VZ("footer",{className:"deck-carousel-footer",children:[VZ("span",{className:"deck-carousel-footer-meta",children:$??Q},void 0,!1,void 0,this),VZ("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[VZ("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VZ("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},U,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as PH6,rm as MH6}from"fs/promises";import{tmpdir as jH6}from"os";import{join as OH6}from"path";Q4();R2();var fH6=26214400,xH6=60000,dj2=20;class NWA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz,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=RH6(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>dj2)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${dj2}`);let $=await this.getThemeMode(),B=await PH6(OH6(jH6(),"brain-deck-carousel-"));try{let X=await mU({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:lj2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:$},themeCSS:this.context.themeCSS}),Y=await uU({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:fH6,timeoutMs:xH6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${vH6(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await MH6(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function RH6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=typeof w.title==="string"?w.title:A.metadata.title,X=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=$.split(/^---$/gm).map((Z)=>Z.trim()).filter((Z)=>Z.length>0).map((Z)=>({markdown:Z}));return{title:B,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...X?{eyebrow:X}:{}}}function vH6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}b0();import{jsxDEV as EH6}from"preact/jsx-dev-runtime";var ON0="og-image",CH6="decks:og-image",ij2=H.object({title:H.string().min(1),description:H.string().optional(),event:H.string().optional(),brandLabel:H.string().optional(),slideCount:H.number().int().positive().optional(),coverImageUrl:H.string().optional()}),nj2={name:CH6,pluginId:"decks",schema:ij2,renderers:{image:hH6}};function hH6(A){let Q=ij2.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return EH6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}Q4();R2();class _WA{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!==ON0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=M$(Q.content),B=zF.parse(w),X=gH6($),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),W={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Th({mediaPath:`/_media/og/deck/${Q.id}`,template:nj2,content:W,title:W.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${yH6(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 gH6(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function yH6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}$A();async function rj2({entity:A,config:Q}){let w=bd.parse(A),$=DQ(w.content,zF),B=$.metadata;return{$type:"ai.rizom.brain.deck",title:B.title,...B.slug&&{slug:B.slug},...B.description&&{description:B.description},body:$.content,format:"text/markdown",...B.author&&{author:B.author},...B.event&&{event:B.event},...B.publishedAt&&{publishedAt:B.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function bWA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:I$["ai.rizom.brain.deck"],validate:!1,buildRecord:rj2}}var oj2={name:"@brains/decks",version:"0.2.0-alpha.
|
|
7324
|
+
`}},void 0,!1,void 0,this),B.map((K,U)=>VZ("section",{className:`deck-carousel-slide${U===0?" is-cover":""}`,children:[VZ("header",{className:"deck-carousel-header",children:VZ("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[VZ("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VZ(kH6,{children:[VZ("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VZ("span",{className:"wm-secondary",children:X.secondary},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),VZ("div",{className:"deck-carousel-body",children:VZ("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:W(K.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VZ("footer",{className:"deck-carousel-footer",children:[VZ("span",{className:"deck-carousel-footer-meta",children:$??Q},void 0,!1,void 0,this),VZ("span",{className:"deck-carousel-counter","aria-label":`Slide ${U+1} of ${Y}`,children:[VZ("span",{className:"deck-carousel-counter-current",children:String(U+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VZ("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},U,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as PH6,rm as MH6}from"fs/promises";import{tmpdir as jH6}from"os";import{join as OH6}from"path";Q4();R2();var fH6=26214400,xH6=60000,dj2=20;class NWA{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz,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=RH6(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>dj2)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${dj2}`);let $=await this.getThemeMode(),B=await PH6(OH6(jH6(),"brain-deck-carousel-"));try{let X=await mU({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:lj2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:$},themeCSS:this.context.themeCSS}),Y=await uU({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:fH6,timeoutMs:xH6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${vH6(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await MH6(B,{recursive:!0,force:!0})}}resolveBrandLabel(){let A=this.context.domain?.trim();if(A&&A.length>0)return A;let Q=this.context.identity.getProfile().name;return Q.length>0?Q:void 0}}function RH6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=typeof w.title==="string"?w.title:A.metadata.title,X=typeof w.event==="string"&&w.event.length>0?w.event:void 0,Y=$.split(/^---$/gm).map((Z)=>Z.trim()).filter((Z)=>Z.length>0).map((Z)=>({markdown:Z}));return{title:B,slides:Y,...Q.brandLabel?{brandLabel:Q.brandLabel}:{},...X?{eyebrow:X}:{}}}function vH6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}b0();import{jsxDEV as EH6}from"preact/jsx-dev-runtime";var ON0="og-image",CH6="decks:og-image",ij2=H.object({title:H.string().min(1),description:H.string().optional(),event:H.string().optional(),brandLabel:H.string().optional(),slideCount:H.number().int().positive().optional(),coverImageUrl:H.string().optional()}),nj2={name:CH6,pluginId:"decks",schema:ij2,renderers:{image:hH6}};function hH6(A){let Q=ij2.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return EH6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}Q4();R2();class _WA{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!==ON0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=M$(Q.content),B=zF.parse(w),X=gH6($),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),W={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Th({mediaPath:`/_media/og/deck/${Q.id}`,template:nj2,content:W,title:W.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${yH6(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 gH6(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function yH6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}$A();async function rj2({entity:A,config:Q}){let w=bd.parse(A),$=DQ(w.content,zF),B=$.metadata;return{$type:"ai.rizom.brain.deck",title:B.title,...B.slug&&{slug:B.slug},...B.description&&{description:B.description},body:$.content,format:"text/markdown",...B.author&&{author:B.author},...B.event&&{event:B.event},...B.publishedAt&&{publishedAt:B.publishedAt},...Q.brainDid&&{brainDid:Q.brainDid},...Q.anchorDid&&{anchorDid:Q.anchorDid},sourceEntityType:"deck",sourceEntityId:w.id,createdAt:w.created,...w.updated&&{updatedAt:w.updated}}}function bWA(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:I$["ai.rizom.brain.deck"],validate:!1,buildRecord:rj2}}var oj2={name:"@brains/decks",version:"0.2.0-alpha.181",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 SH6=H.object({prompt:H.string(),event:H.string().optional()}),mH6=H.object({title:H.string(),content:H.string()});class kWA extends jw{deps;entityType=Q$0.entityType;schema=Q$0.schema;adapter=Q$0;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",oj2,{},yX);this.deps=A}createGenerationHandler(A){return new LWA(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":DWA,"deck-list":FWA,generation:mj2,description:uj2}}getDataSources(){return[new IWA(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=fB.getInstance().register(bWA()),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:$}=Q.payload;if(w!=="deck")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"deck",id:$});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:`Deck not found: ${$}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=new Date().toISOString(),Y={...B,metadata:{...B.metadata,status:"published",publishedAt:X}};await A.entityService.updateEntity({entity:{...Y,content:this.adapter.toMarkdown(Y)}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:$,result:{id:$}}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:lA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await n60(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",cj2,new NWA(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",ON0,new _WA(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=SH6.parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
|
|
7325
7325
|
|
|
7326
7326
|
Note: This presentation is for "${w.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let w=mH6.parse(Q);return A.ai.generate({prompt:`Title: ${w.title}
|
|
7327
7327
|
|
|
@@ -7478,9 +7478,9 @@ ${w.content}`,templateName:"decks:description"})})}}function $$0(){return new kW
|
|
|
7478
7478
|
background: transparent;
|
|
7479
7479
|
}
|
|
7480
7480
|
|
|
7481
|
-
`,XO2=()=>f7("style",{children:iH6},void 0,!1,void 0,this);import{jsxDEV as e2,Fragment as nH6}from"preact/jsx-dev-runtime";var CN0=({title:A,description:Q,children:w,detail:$=!1,footer:B=!1,contentClassName:X=""})=>e2(nH6,{children:[e2(Nw,{title:A,description:Q},void 0,!1,void 0,this),e2(XO2,{},void 0,!1,void 0,this),e2("div",{className:`docs-handbook${$?" docs-handbook--detail":""}`,children:[e2($O2,{},void 0,!1,void 0,this),e2("div",{className:`${JF.wrap} ${X}`.trim(),children:[w,B&&e2(BO2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),YO2=({docsCount:A,sectionsCount:Q,startDoc:w})=>e2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[e2("p",{className:`${JF.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),e2("h1",{className:`${JF.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",e2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),e2("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),e2("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:[e2("div",{children:[e2("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),e2("div",{children:[e2("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),e2("div",{children:[e2("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),e2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&e2("a",{className:JF.primaryButton,href:Pd(w),children:"Start reading"},void 0,!1,void 0,this),e2("a",{className:JF.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ZO2=({groups:A})=>e2("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:[e2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),e2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>e2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[e2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Md(w),"."]},void 0,!0,void 0,this),e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${vN0(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),HO2=({group:A,index:Q})=>e2("article",{className:"mb-16 last:mb-0",id:vN0(Q),children:[e2("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:[e2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Md(Q),"."]},void 0,!0,void 0,this),e2("h2",{className:`${JF.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),e2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),e2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>e2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:e2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:Pd(w),children:[e2("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&&e2("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),WO2=({title:A})=>e2("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:[e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),e2("span",{children:"/"},void 0,!1,void 0,this),e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),e2("span",{children:"/"},void 0,!1,void 0,this),e2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),KO2=({groups:A,activeGroupIndex:Q,activeSlug:w})=>e2("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:e2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[e2("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),e2("ol",{className:"m-0 list-none p-0",children:A.map(($,B)=>{let X=B===Q;return e2("li",{className:X?"mb-[22px]":"mb-3.5",children:[e2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${X?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${vN0(B)}`,children:[e2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Md(B),"."]},void 0,!0,void 0,this)," ",$.section]},void 0,!0,void 0,this),X&&e2("ol",{className:"mt-0.5 list-none p-0",children:$.docs.map((Y)=>{let Z=Y.metadata.slug===w;return e2("li",{children:e2("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${Z?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:Pd(Y),"aria-current":Z?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},$.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),UO2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return e2("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?e2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:Pd(A),children:[e2("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),e2("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):e2("span",{},void 0,!1,void 0,this),Q&&e2("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:Pd(Q),children:[e2("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),e2("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 jd}from"preact/jsx-dev-runtime";var OWA=({docs:A})=>{let Q=B$0(A),w=RN0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return jd(CN0,{title:"Documentation",description:"Brains documentation",children:[jd(YO2,{docsCount:A.length,sectionsCount:w.length,startDoc:B},void 0,!1,void 0,this),jd("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:[jd(ZO2,{groups:w},void 0,!1,void 0,this),jd("div",{children:w.map((X,Y)=>jd(HO2,{group:X,index:Y},X.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as cU}from"preact/jsx-dev-runtime";var fWA=({doc:A,docs:Q,prevDoc:w,nextDoc:$})=>{let B=RN0(Q.length>0?Q:[A]),X=B$0(Q.length>0?Q:[A]),Y=X.findIndex((W)=>W.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((W)=>W.docs.some((K)=>K.metadata.slug===A.metadata.slug)),0);return cU(CN0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[cU(WO2,{title:A.metadata.title},void 0,!1,void 0,this),cU("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[cU(KO2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),cU("article",{className:"min-w-0",children:[cU("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[cU("p",{className:`${JF.label} m-0 mb-6 flex items-baseline gap-3`,children:[cU("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Md(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),cU("h1",{className:`${JF.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&&cU("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),cU("div",{className:"docs-article__body",children:cU(L4,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),cU(UO2,{prevDoc:w,nextDoc:$},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 rH6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),oH6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),sH6=H.object({title:H.string(),section:H.string(),order:H.number().int(),sourcePath:H.string(),description:H.string().optional(),slug:H.string().optional()}),aH6=H.object({title:H.string(),section:H.string(),order:H.number().int(),description:H.string().optional(),slug:H.string()}),X$0=H.object({id:H.string(),entityType:H.literal("doc"),content:H.string(),created:H.string(),updated:H.string(),visibility:oH6,metadata:aH6,contentHash:H.string(),frontmatter:sH6,body:H.string()}),tH6=H.object({docs:H.array(X$0),pagination:rH6.nullable(),baseUrl:H.string().optional()}),eH6=H.object({doc:X$0,docs:H.array(X$0),prevDoc:X$0.nullable(),nextDoc:X$0.nullable()});function GO2(){return{"doc-list":$2({name:"doc-list",description:"Documentation index template",schema:tH6,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:OWA}}),"doc-detail":$2({name:"doc-detail",description:"Documentation page template",schema:eH6,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:fWA}})}}var DO2={name:"@brains/doc",version:"0.2.0-alpha.180",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 xWA extends jw{entityType=fN0.entityType;schema=kd;adapter=fN0;constructor(){super("docs",DO2,{},yX)}getTemplates(){return GO2()}getDataSources(){return[new xN0(this.logger.child("DocDataSource"))]}}function Y$0(){return new xWA}$A();R2();b0();_5();b0();var RWA=H.literal("application/pdf"),qO2=H.enum(["pending","draft","failed"]),vWA=H.object({title:H.string().optional(),mimeType:RWA,filename:H.string().min(1),pageCount:H.number().int().min(0).optional(),status:qO2.optional(),processingJobId:H.string().optional(),processingError:H.string().optional(),sourceEntityType:H.string().min(1).optional(),sourceEntityId:H.string().min(1).optional(),sourceUploadId:H.string().optional(),sourceFilename:H.string().optional(),sourceMediaType:H.string().optional(),attachmentType:H.string().min(1).optional(),dedupKey:H.string().min(1).optional()}),Od=aQ.extend({entityType:H.literal("document"),content:H.string().regex(/^data:application\/pdf;base64,.+$/),metadata:vWA});function Z$0(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 hN0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function CWA(A){let Q=Buffer.from(A).toString("latin1"),w=0,$=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let X of Q.matchAll($)){let Y=parseInt(X[1]??X[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class EN0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Od;toMarkdown(A){return A.content}fromMarkdown(A){return Z$0(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:$}=Z$0(Q);return{entityType:"document",content:Q,metadata:{mimeType:$,...w}}}}var v_=new EN0;async function IKA(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 B=(await Promise.resolve().then(() => (bx2(),_x2))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),X=await B.promise;try{let Y=Q.maxPages??50;if(X.numPages>Y)throw Error(`Uploaded PDF has ${X.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let Z=[];for(let K=1;K<=X.numPages;K+=1){let D=(await(await X.getPage(K)).getTextContent()).items.flatMap((z)=>("str"in z)?[z.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)Z.push(D)}let W=Z.join(`
|
|
7481
|
+
`,XO2=()=>f7("style",{children:iH6},void 0,!1,void 0,this);import{jsxDEV as e2,Fragment as nH6}from"preact/jsx-dev-runtime";var CN0=({title:A,description:Q,children:w,detail:$=!1,footer:B=!1,contentClassName:X=""})=>e2(nH6,{children:[e2(Nw,{title:A,description:Q},void 0,!1,void 0,this),e2(XO2,{},void 0,!1,void 0,this),e2("div",{className:`docs-handbook${$?" docs-handbook--detail":""}`,children:[e2($O2,{},void 0,!1,void 0,this),e2("div",{className:`${JF.wrap} ${X}`.trim(),children:[w,B&&e2(BO2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),YO2=({docsCount:A,sectionsCount:Q,startDoc:w})=>e2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[e2("p",{className:`${JF.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),e2("h1",{className:`${JF.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",e2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),e2("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),e2("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:[e2("div",{children:[e2("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),e2("div",{children:[e2("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),e2("div",{children:[e2("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),e2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&e2("a",{className:JF.primaryButton,href:Pd(w),children:"Start reading"},void 0,!1,void 0,this),e2("a",{className:JF.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),ZO2=({groups:A})=>e2("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:[e2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),e2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>e2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[e2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[Md(w),"."]},void 0,!0,void 0,this),e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${vN0(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),HO2=({group:A,index:Q})=>e2("article",{className:"mb-16 last:mb-0",id:vN0(Q),children:[e2("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:[e2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[Md(Q),"."]},void 0,!0,void 0,this),e2("h2",{className:`${JF.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),e2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),e2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>e2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:e2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:Pd(w),children:[e2("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&&e2("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),WO2=({title:A})=>e2("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:[e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),e2("span",{children:"/"},void 0,!1,void 0,this),e2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),e2("span",{children:"/"},void 0,!1,void 0,this),e2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),KO2=({groups:A,activeGroupIndex:Q,activeSlug:w})=>e2("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:e2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[e2("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),e2("ol",{className:"m-0 list-none p-0",children:A.map(($,B)=>{let X=B===Q;return e2("li",{className:X?"mb-[22px]":"mb-3.5",children:[e2("a",{className:`mb-2 flex items-baseline gap-2.5 docs-font-label text-[11px] uppercase leading-[1.4] tracking-[0.06em] transition-colors duration-150 hover:text-[var(--docs-text)] ${X?"text-[var(--docs-text)]":"text-[var(--docs-text-muted)]"}`,href:`/docs#${vN0(B)}`,children:[e2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[Md(B),"."]},void 0,!0,void 0,this)," ",$.section]},void 0,!0,void 0,this),X&&e2("ol",{className:"mt-0.5 list-none p-0",children:$.docs.map((Y)=>{let Z=Y.metadata.slug===w;return e2("li",{children:e2("a",{className:`docs-rail__doc relative block py-1.5 docs-font-body text-sm leading-[1.4] tracking-normal transition-[color,padding-left] duration-150 hover:text-[var(--docs-text)] ${Z?"pl-3.5 font-medium text-[var(--docs-accent)]":"text-[var(--docs-text-muted)]"}`,href:Pd(Y),"aria-current":Z?"page":void 0,children:Y.metadata.title},void 0,!1,void 0,this)},Y.id,!1,void 0,this)})},void 0,!1,void 0,this)]},$.section,!0,void 0,this)})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),UO2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return e2("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?e2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:Pd(A),children:[e2("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),e2("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):e2("span",{},void 0,!1,void 0,this),Q&&e2("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:Pd(Q),children:[e2("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),e2("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 jd}from"preact/jsx-dev-runtime";var OWA=({docs:A})=>{let Q=B$0(A),w=RN0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return jd(CN0,{title:"Documentation",description:"Brains documentation",children:[jd(YO2,{docsCount:A.length,sectionsCount:w.length,startDoc:B},void 0,!1,void 0,this),jd("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:[jd(ZO2,{groups:w},void 0,!1,void 0,this),jd("div",{children:w.map((X,Y)=>jd(HO2,{group:X,index:Y},X.section,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as cU}from"preact/jsx-dev-runtime";var fWA=({doc:A,docs:Q,prevDoc:w,nextDoc:$})=>{let B=RN0(Q.length>0?Q:[A]),X=B$0(Q.length>0?Q:[A]),Y=X.findIndex((W)=>W.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((W)=>W.docs.some((K)=>K.metadata.slug===A.metadata.slug)),0);return cU(CN0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[cU(WO2,{title:A.metadata.title},void 0,!1,void 0,this),cU("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[cU(KO2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),cU("article",{className:"min-w-0",children:[cU("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[cU("p",{className:`${JF.label} m-0 mb-6 flex items-baseline gap-3`,children:[cU("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[Md(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),cU("h1",{className:`${JF.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&&cU("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),cU("div",{className:"docs-article__body",children:cU(L4,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),cU(UO2,{prevDoc:w,nextDoc:$},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 rH6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),oH6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),sH6=H.object({title:H.string(),section:H.string(),order:H.number().int(),sourcePath:H.string(),description:H.string().optional(),slug:H.string().optional()}),aH6=H.object({title:H.string(),section:H.string(),order:H.number().int(),description:H.string().optional(),slug:H.string()}),X$0=H.object({id:H.string(),entityType:H.literal("doc"),content:H.string(),created:H.string(),updated:H.string(),visibility:oH6,metadata:aH6,contentHash:H.string(),frontmatter:sH6,body:H.string()}),tH6=H.object({docs:H.array(X$0),pagination:rH6.nullable(),baseUrl:H.string().optional()}),eH6=H.object({doc:X$0,docs:H.array(X$0),prevDoc:X$0.nullable(),nextDoc:X$0.nullable()});function GO2(){return{"doc-list":$2({name:"doc-list",description:"Documentation index template",schema:tH6,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:OWA}}),"doc-detail":$2({name:"doc-detail",description:"Documentation page template",schema:eH6,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:fWA}})}}var DO2={name:"@brains/doc",version:"0.2.0-alpha.181",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 xWA extends jw{entityType=fN0.entityType;schema=kd;adapter=fN0;constructor(){super("docs",DO2,{},yX)}getTemplates(){return GO2()}getDataSources(){return[new xN0(this.logger.child("DocDataSource"))]}}function Y$0(){return new xWA}$A();R2();b0();_5();b0();var RWA=H.literal("application/pdf"),qO2=H.enum(["pending","draft","failed"]),vWA=H.object({title:H.string().optional(),mimeType:RWA,filename:H.string().min(1),pageCount:H.number().int().min(0).optional(),status:qO2.optional(),processingJobId:H.string().optional(),processingError:H.string().optional(),sourceEntityType:H.string().min(1).optional(),sourceEntityId:H.string().min(1).optional(),sourceUploadId:H.string().optional(),sourceFilename:H.string().optional(),sourceMediaType:H.string().optional(),attachmentType:H.string().min(1).optional(),dedupKey:H.string().min(1).optional()}),Od=aQ.extend({entityType:H.literal("document"),content:H.string().regex(/^data:application\/pdf;base64,.+$/),metadata:vWA});function Z$0(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 hN0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function CWA(A){let Q=Buffer.from(A).toString("latin1"),w=0,$=/\/Type\s*\/Pages\b[^]*?\/Count\s+(\d+)|\/Count\s+(\d+)[^]*?\/Type\s*\/Pages\b/g;for(let X of Q.matchAll($)){let Y=parseInt(X[1]??X[2]??"0",10);if(Y>w)w=Y}if(w>0)return w;return Q.match(/\/Type\s*\/Page(?!\w)/g)?.length??0}class EN0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=Od;toMarkdown(A){return A.content}fromMarkdown(A){return Z$0(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:$}=Z$0(Q);return{entityType:"document",content:Q,metadata:{mimeType:$,...w}}}}var v_=new EN0;async function IKA(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 B=(await Promise.resolve().then(() => (bx2(),_x2))).getDocument({data:new Uint8Array(A),disableFontFace:!1,useSystemFonts:!0,useWorkerFetch:!1}),X=await B.promise;try{let Y=Q.maxPages??50;if(X.numPages>Y)throw Error(`Uploaded PDF has ${X.numPages} pages; maximum supported for synchronous markdown extraction is ${Y}`);let Z=[];for(let K=1;K<=X.numPages;K+=1){let D=(await(await X.getPage(K)).getTextContent()).items.flatMap((z)=>("str"in z)?[z.str]:[]).join(" ").replace(/\s+/g," ").trim();if(D.length>0)Z.push(D)}let W=Z.join(`
|
|
7482
7482
|
|
|
7483
|
-
`).trim();if(!W)throw Error("Could not extract text from the uploaded PDF");return W}finally{await B.destroy()}}$A();Q4();R2();b0();import{createHash as mW6}from"crypto";var uW6=26214400,cW6=20,pW6=60000,kx2=80,lW6=10,dW6={renderUrl:H.url().optional(),sourceEntityType:H.string().min(1),sourceEntityId:H.string().min(1),attachmentType:H.string().min(1),documentId:H.string().min(1).optional(),title:H.string().min(1).optional(),filename:H.string().min(1).optional(),dedupKey:H.string().min(1).optional(),replace:H.boolean().optional(),pageCount:H.number().int().min(0).optional(),maxPageCount:H.number().int().positive().optional(),maxBytes:H.number().int().positive().optional(),timeoutMs:H.number().int().positive().optional(),width:H.union([H.string(),H.number()]).optional(),height:H.union([H.string(),H.number()]).optional(),format:H.string().optional(),targetEntityType:H.string().min(1).optional(),targetEntityId:H.string().min(1).optional()},Mx2=H.object(dW6),N_0=Mx2.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 __0 extends p6{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:N_0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??Dz}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 $=A.maxPageCount??cW6,B=A.maxBytes??uW6,X=A.timeoutMs??pW6;if(A.pageCount!==void 0&&A.pageCount>$)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${$}`);let Y=await this.getDedupKey(A),Z=LKA(A,Y),W=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let K=await this.findDocumentByDedupKey(Y,W?Z:void 0);if(K&&(!W||K.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,K.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:K.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let K=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),U=K.data;if(U.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${U.byteLength} bytes`);let G=CWA(U);if(G>$)throw Error(`Rendered PDF has ${G} pages, exceeding maxPageCount=${$}`);let D=G>0?G:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let z=A.filename??(A.renderUrl===void 0?K.filename:`${Z}.pdf`),V=v_.createDocumentEntity({dataUrl:hN0(U),filename:z,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await $H({entityService:this.context.entityService,entity:{...V,id:Z}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Z,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Z,reused:!1}}catch(K){let U=lA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await dJ({entityService:this.context.entityService,entityType:"document",id:Z,error:U}),K}}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 $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if($.type!=="document")throw Error(`Attachment provider returned ${$.type}; expected document`);return $}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((B)=>B.id),preferredDocumentId:Q});let $=w.filter((B)=>B.metadata.status!=="pending"&&B.metadata.status!=="failed");return $.find((B)=>B.id===Q)??$[0]}async attachDocumentToTarget(A,Q,w,$){let B=await this.context.entityService.getEntity({entityType:A,id:Q});if(!B)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:X}=M$(B.content),Y=Array.isArray(X.documents)?X.documents.filter(nW6):[],Z=$.replace?await this.removeReferencesForSameSourceAttachment(Y,w,$):Y,W=Z.some((K)=>K.id===w)?Z:[...Z,{id:w}];await this.context.entityService.updateEntity({entity:{...B,content:n4(B.content,"documents",W)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let $=[];for(let B of A){if(B.id===Q){$.push(B);continue}let X=await this.context.entityService.getEntity({entityType:"document",id:B.id});if(!X||!rW6(X,w))$.push(B)}return $}}function LKA(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,$=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,B=A.replace===!0&&A.documentId===void 0?`${$}-${Date.now()}`:$;return iW6(B)}function iW6(A){let Q=F1(A.replace(/[/:]+/g," "))||`document-${Px2(A)}`;if(Q.length<=kx2)return Q;let w=`-${Px2(A)}`;return`${Q.slice(0,kx2-w.length).replace(/-+$/g,"")}${w}`}function Px2(A){return mW6("sha256").update(A).digest("hex").slice(0,lW6)}function nW6(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function rW6(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var jx2={name:"@brains/document-plugin",version:"0.2.0-alpha.
|
|
7483
|
+
`).trim();if(!W)throw Error("Could not extract text from the uploaded PDF");return W}finally{await B.destroy()}}$A();Q4();R2();b0();import{createHash as mW6}from"crypto";var uW6=26214400,cW6=20,pW6=60000,kx2=80,lW6=10,dW6={renderUrl:H.url().optional(),sourceEntityType:H.string().min(1),sourceEntityId:H.string().min(1),attachmentType:H.string().min(1),documentId:H.string().min(1).optional(),title:H.string().min(1).optional(),filename:H.string().min(1).optional(),dedupKey:H.string().min(1).optional(),replace:H.boolean().optional(),pageCount:H.number().int().min(0).optional(),maxPageCount:H.number().int().positive().optional(),maxBytes:H.number().int().positive().optional(),timeoutMs:H.number().int().positive().optional(),width:H.union([H.string(),H.number()]).optional(),height:H.union([H.string(),H.number()]).optional(),format:H.string().optional(),targetEntityType:H.string().min(1).optional(),targetEntityId:H.string().min(1).optional()},Mx2=H.object(dW6),N_0=Mx2.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 __0 extends p6{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:N_0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??Dz}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 $=A.maxPageCount??cW6,B=A.maxBytes??uW6,X=A.timeoutMs??pW6;if(A.pageCount!==void 0&&A.pageCount>$)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${$}`);let Y=await this.getDedupKey(A),Z=LKA(A,Y),W=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let K=await this.findDocumentByDedupKey(Y,W?Z:void 0);if(K&&(!W||K.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,K.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:K.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let K=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),U=K.data;if(U.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${U.byteLength} bytes`);let G=CWA(U);if(G>$)throw Error(`Rendered PDF has ${G} pages, exceeding maxPageCount=${$}`);let D=G>0?G:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let z=A.filename??(A.renderUrl===void 0?K.filename:`${Z}.pdf`),V=v_.createDocumentEntity({dataUrl:hN0(U),filename:z,...A.title&&{title:A.title},...D!==void 0&&{pageCount:D},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await $H({entityService:this.context.entityService,entity:{...V,id:Z}}),A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,Z,A);return await this.reportProgress(w,{progress:100,message:"PDF document generation complete"}),{success:!0,documentId:Z,reused:!1}}catch(K){let U=lA(K);throw this.logger.error("Document generation failed",{jobId:Q,error:U}),await dJ({entityService:this.context.entityService,entityType:"document",id:Z,error:U}),K}}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 $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)throw Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`);if($.type!=="document")throw Error(`Attachment provider returned ${$.type}; expected document`);return $}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((B)=>B.id),preferredDocumentId:Q});let $=w.filter((B)=>B.metadata.status!=="pending"&&B.metadata.status!=="failed");return $.find((B)=>B.id===Q)??$[0]}async attachDocumentToTarget(A,Q,w,$){let B=await this.context.entityService.getEntity({entityType:A,id:Q});if(!B)throw Error(`Target entity not found: ${A}/${Q}`);let{frontmatter:X}=M$(B.content),Y=Array.isArray(X.documents)?X.documents.filter(nW6):[],Z=$.replace?await this.removeReferencesForSameSourceAttachment(Y,w,$):Y,W=Z.some((K)=>K.id===w)?Z:[...Z,{id:w}];await this.context.entityService.updateEntity({entity:{...B,content:n4(B.content,"documents",W)}})}async removeReferencesForSameSourceAttachment(A,Q,w){let $=[];for(let B of A){if(B.id===Q){$.push(B);continue}let X=await this.context.entityService.getEntity({entityType:"document",id:B.id});if(!X||!rW6(X,w))$.push(B)}return $}}function LKA(A,Q){let w=`${A.attachmentType}:${A.sourceEntityType}:${A.sourceEntityId}:${A.renderUrl??"resolved-attachment"}`,$=A.documentId??A.filename?.replace(/\.pdf$/i,"")??Q??w,B=A.replace===!0&&A.documentId===void 0?`${$}-${Date.now()}`:$;return iW6(B)}function iW6(A){let Q=F1(A.replace(/[/:]+/g," "))||`document-${Px2(A)}`;if(Q.length<=kx2)return Q;let w=`-${Px2(A)}`;return`${Q.slice(0,kx2-w.length).replace(/-+$/g,"")}${w}`}function Px2(A){return mW6("sha256").update(A).digest("hex").slice(0,lW6)}function nW6(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function rW6(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var jx2={name:"@brains/document-plugin",version:"0.2.0-alpha.181",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 sW6=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
|
|
7484
7484
|
% Pending document placeholder
|
|
7485
7485
|
%%EOF
|
|
7486
7486
|
`).toString("base64")}`,aW6=H.object({}).catchall(H.unknown()).transform(()=>({})),NKA={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function tW6(A,Q){let w=A.title?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}function eW6(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function AK6(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 _KA extends Rw{entityType=v_.entityType;schema=Od;adapter=v_;pluginContext;constructor(){super("document",jx2,{},aW6)}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 __0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===NKA.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=N_0.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}}),$=await this.getDedupKey(w,Q),B=w.replace===!0?void 0:await this.findExistingDocument($,Q),X=B?.id??LKA(w,$);if(!B)await this.createPendingDocument(Q,{id:X,title:w.title??X,filename:`${X}.pdf`,sourceEntityType:w.sourceEntityType,sourceEntityId:w.sourceEntityId,attachmentType:w.attachmentType,dedupKey:$});let Y=await Q.jobs.enqueue({type:"generate",data:{...w,dedupKey:$,documentId:X}}),Z=`${X}.pdf`;return{kind:"handled",result:{success:!0,data:{entityId:X,jobId:Y,status:"generating",attachment:{mediaType:"application/pdf",url:`/api/chat/attachments/document?id=${encodeURIComponent(X)}`,downloadUrl:`/api/chat/attachments/document?id=${encodeURIComponent(X)}&download=1`,filename:Z,source:{entityType:"document",entityId:X,attachmentType:w.attachmentType}}}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==NKA.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $;try{$=await Q.uploads.scoped(NKA).read(w.id)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if($.record.mediaType!=="application/pdf")return{kind:"handled",result:{success:!1,error:"Only PDF uploads can be promoted to document entities"}};let B=tW6(A,$.record.filename),X=F1(B);if(!X)return{kind:"handled",result:{success:!1,error:"Could not derive a document id from the uploaded filename. Provide a title."}};let Y=new Date().toISOString(),Z=v_.createDocumentEntity({dataUrl:eW6($.record.mediaType,$.content),filename:$.record.filename,title:B,status:"draft",sourceUploadId:w.id,sourceFilename:$.record.filename,sourceMediaType:$.record.mediaType,attachmentType:"uploaded",dedupKey:`upload:${w.kind}:${w.id}`}),W=await Q.entityService.createEntity({entity:{id:X,...Z,created:Y,updated:Y},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:W.entityId,status:"created",attachment:AK6({entityId:W.entityId,filename:$.record.filename})}}}}async createPendingDocument(A,Q){let w=new Date().toISOString(),$=v_.createDocumentEntity({dataUrl:sW6,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await XR({entityService:A.entityService,entity:{id:Q.id,...$,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`,$=await Q.entityService.getEntity({entityType:A.sourceEntityType,id:A.sourceEntityId});return $?`${w}:${$.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 bKA(){return new _KA}$A();b0();$A();b0();var Ox2=H.enum(["generating","failed"]),QK6=H.enum(["generating","failed"]),sj=H.object({title:H.string().optional(),status:Ox2.optional(),error:H.string().optional()}),wK6=H.object({title:H.string(),status:Ox2.optional(),error:H.string().optional()}),$K6=H.object({title:H.string(),status:QK6.optional(),error:H.string().optional()}),aj=aQ.extend({entityType:H.literal("note"),metadata:$K6}),BK6=aj.extend({frontmatter:sj,body:H.string()});$A();b0();var XK6=H.record(H.string(),H.unknown());class kKA extends QQ{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:aj,frontmatterSchema:sj})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,sj);if(Object.values(w).some(($)=>$!==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,sj)}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,XK6);if(Object.keys(w).length===0)return Q;let $={...w,title:w.title??A},B=this.extractBody(Q);return this.buildMarkdown(B,$)}catch{return Q}}extractH1(A){return A.match(/^#\s+(.+)$/m)?.[1]?.trim()??null}}var g_=new kKA;b0();var PKA=H.object({defaultPrompt:H.string().default("Create a note summarizing key concepts from my knowledge base")});b0();$A();var fx2=H.object({title:H.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:H.string().describe("Note content in markdown format with clear organization and structure")}),MKA=$2({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:fx2,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
|
|
@@ -7498,7 +7498,7 @@ title: ${JSON.stringify(A)}
|
|
|
7498
7498
|
---
|
|
7499
7499
|
|
|
7500
7500
|
${Q.trim()}
|
|
7501
|
-
`}var KK6={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},UK6=H.object({uploadId:H.string().min(1),entityId:H.string().min(1),title:H.string().optional()});class OKA extends p6{context;constructor(A,Q){super(A,{schema:UK6,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let $=await this.context.uploads.scoped(KK6).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let B=await Cx2({upload:$,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=g_.fromMarkdown(B.content),Z=await $H({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:B.content,metadata:{title:B.title,...Y.metadata},created:X,updated:X}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:Z.entityId,status:"created"}}catch($){return await this.markStubFailed(A.entityId,lA($)),J5.failure($)}}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:n4(n4(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}}}$A();async function hx2({entity:A,config:Q}){let w=aj.parse(A),$=DQ(w.content,sj);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:$.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 fKA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:I$["ai.rizom.brain.note"],validate:!1,buildRecord:hx2}}var Ex2={name:"@brains/note",version:"0.2.0-alpha.
|
|
7501
|
+
`}var KK6={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},UK6=H.object({uploadId:H.string().min(1),entityId:H.string().min(1),title:H.string().optional()});class OKA extends p6{context;constructor(A,Q){super(A,{schema:UK6,jobTypeName:"upload-import"});this.context=Q}async process(A,Q,w){try{await this.reportProgress(w,{progress:10,message:"Reading uploaded file"});let $=await this.context.uploads.scoped(KK6).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let B=await Cx2({upload:$,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=g_.fromMarkdown(B.content),Z=await $H({entityService:this.context.entityService,entity:{id:A.entityId,entityType:"note",content:B.content,metadata:{title:B.title,...Y.metadata},created:X,updated:X}});return await this.reportProgress(w,{progress:100,message:"Upload imported as markdown note"}),{entityId:Z.entityId,status:"created"}}catch($){return await this.markStubFailed(A.entityId,lA($)),J5.failure($)}}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:n4(n4(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}}}$A();async function hx2({entity:A,config:Q}){let w=aj.parse(A),$=DQ(w.content,sj);return{$type:"ai.rizom.brain.note",title:w.metadata.title,body:$.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 fKA(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:I$["ai.rizom.brain.note"],validate:!1,buildRecord:hx2}}var Ex2={name:"@brains/note",version:"0.2.0-alpha.181",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 gx2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},DK6=H.object({prompt:H.string()});class xKA extends jw{entityType=g_.entityType;schema=aj;adapter=g_;unregisterAtprotoProjection;constructor(A={}){super("note",Ex2,A,PKA)}async interceptCreate(A,Q,w){if(A.from?.kind!==gx2.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 $=A.from.id,B;try{B=await w.uploads.scoped(gx2).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!vx2(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=jKA({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=g_.buildStub({id:X.id,title:X.title}),Z=new Date().toISOString(),W=await w.entityService.createEntity({entity:{id:X.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:Z,updated:Z},options:{deduplicateId:!0}}),K=await w.jobs.enqueue({type:"upload-import",data:{uploadId:$,entityId:W.entityId,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:W.entityId,status:"generating",jobId:K}}}}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new b_0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:MKA}}async onRegister(A){A.jobs.registerHandler("upload-import",new OKA(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=DK6.parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=fB.getInstance().register(fKA())}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 rh(A={}){return new xKA(A)}$A();b0();$A();var yx2=H.object({ref:H.string(),label:H.string()}),Tx2=H.enum(["pending","draft","published"]),qK6=H.enum(["pending","draft","published"]),C$0=H.object({status:Tx2,title:H.string(),url:H.string().url(),description:H.string().optional(),domain:H.string(),capturedAt:H.string().datetime(),source:yx2}),zK6=C$0.pick({title:!0,status:!0}),JK6=H.object({title:H.string(),status:qK6}),oh=aQ.extend({entityType:H.literal("link"),metadata:JK6});R2();b0();b0();var RKA=H.object({enableSummarization:H.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:H.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});$A();class tj extends QQ{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:oh,frontmatterSchema:C$0})}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,C$0),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 cd=new tj;$A();b0();var VK6=H.object({success:H.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:H.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:H.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:H.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:H.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),Sx2=$2({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:VK6,basePrompt:`You are an expert at extracting key information from webpage content.
|
|
7502
7502
|
|
|
7503
7503
|
You will receive webpage content in markdown format. Your job is to extract structured information from it.
|
|
7504
7504
|
|
|
@@ -7520,7 +7520,7 @@ Accuracy rules:
|
|
|
7520
7520
|
|
|
7521
7521
|
`))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 bK6}from"crypto";class ej{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(ej.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=bK6("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}}}$A();b0();g$();var kK6=H.object({interfaceId:H.string().optional(),userId:H.string().optional(),channelId:H.string().optional(),channelName:H.string().optional(),timestamp:H.string().optional()}),PK6=H.object({url:H.url(),metadata:kK6.optional()}),dH5=H.object({success:H.boolean(),entityId:H.string().optional(),title:H.string().optional(),url:H.string().optional(),status:H.enum(["pending","draft","published"]).optional(),error:H.string().optional()});class P_0 extends p6{context;linkAdapter;urlFetcher;constructor(A,Q,w){super(A,{schema:PK6,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new tj,this.urlFetcher=new pd(w?.jinaApiKey?{jinaApiKey:w.jinaApiKey}:void 0)}async process(A,Q,w){let{url:$,metadata:B}=A;try{await w.report({progress:kw.START,total:100,message:"Starting link capture"});let X=ej.generateEntityId($);await w.report({progress:kw.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity({entityType:"link",id:X});if(Y){let{frontmatter:z}=this.linkAdapter.parseLinkContent(Y.content),V=Y.metadata.status;if(V!=="pending")return this.logger.info("Link already captured, returning existing",{url:$,entityId:X}),{success:!0,entityId:Y.id,title:z.title,url:$,status:V};this.logger.info("Pending link exists, completing extraction",{url:$,entityId:X})}let Z=this.resolveSource(B),W=new Date().toISOString();await w.report({progress:kw.FETCH,total:100,message:"Fetching webpage content"});let K=await this.urlFetcher.fetch($);if(!K.success){if(K.errorType==="url_not_found"||K.errorType==="url_unreachable"){this.logger.warn("Link URL not accessible",{url:$,errorType:K.errorType,error:K.error});let z=new URL($).hostname,V=`Could not capture link: ${K.error}`,I=this.linkAdapter.createLinkContent({status:"pending",title:z,url:$,description:V,summary:V,domain:z,capturedAt:W,source:Z});return await $H({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:I,metadata:{status:"pending",title:z}}}),{success:!1,entityId:X,title:z,url:$,status:"pending",error:V}}}await w.report({progress:kw.PROCESS,total:100,message:"Extracting content with AI"});let U=await this.context.ai.generate({templateName:"link:extraction",prompt:K.success?`Extract structured information from this webpage content:
|
|
7522
7522
|
|
|
7523
|
-
${K.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${K.error}"`,data:{url:$,hasContent:K.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:U}),await w.report({progress:kw.EXTRACT,total:100,message:"Processing extraction results"}),U.success===!1||!U.title||!U.description||!U.summary){let z=U.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await w.report({progress:kw.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:z,url:$,description:U.description,summary:U.summary,domain:new URL($).hostname,capturedAt:W,source:Z}),I=await $H({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:z}}});return await w.report({progress:kw.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:I.entityId,title:z,url:$,status:"pending"}}await w.report({progress:kw.SAVE,total:100,message:`Saving link: "${U.title}"`});let G=this.linkAdapter.createLinkContent({status:"draft",title:U.title,url:$,description:U.description,summary:U.summary,domain:new URL($).hostname,capturedAt:W,source:Z}),D=await $H({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:G,metadata:{status:"draft",title:U.title}}});return await w.report({progress:kw.COMPLETE,total:100,message:`Link captured: "${U.title}"`}),{success:!0,entityId:D.entityId,title:U.title,url:$,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),J5.failure(X)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let $=A?.interfaceId??"cli";return{ref:`${$}:local`,label:$.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function cx2({entity:A,config:Q}){let w=oh.parse(A),{frontmatter:$,summary:B}=cd.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:$.title,url:$.url,...$.description&&{description:$.description},...B&&{summary:B},domain:$.domain,capturedAt:$.capturedAt,source:$.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 yKA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:I$["ai.rizom.brain.link"],validate:!1,buildRecord:cx2}}var px2={name:"@brains/link",version:"0.2.0-alpha.
|
|
7523
|
+
${K.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${K.error}"`,data:{url:$,hasContent:K.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:U}),await w.report({progress:kw.EXTRACT,total:100,message:"Processing extraction results"}),U.success===!1||!U.title||!U.description||!U.summary){let z=U.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await w.report({progress:kw.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:z,url:$,description:U.description,summary:U.summary,domain:new URL($).hostname,capturedAt:W,source:Z}),I=await $H({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:z}}});return await w.report({progress:kw.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:I.entityId,title:z,url:$,status:"pending"}}await w.report({progress:kw.SAVE,total:100,message:`Saving link: "${U.title}"`});let G=this.linkAdapter.createLinkContent({status:"draft",title:U.title,url:$,description:U.description,summary:U.summary,domain:new URL($).hostname,capturedAt:W,source:Z}),D=await $H({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:G,metadata:{status:"draft",title:U.title}}});return await w.report({progress:kw.COMPLETE,total:100,message:`Link captured: "${U.title}"`}),{success:!0,entityId:D.entityId,title:U.title,url:$,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),J5.failure(X)}}resolveSource(A){let Q=A?.channelId,w=A?.channelName;if(Q)return{ref:`matrix:${Q}`,label:w??Q};let $=A?.interfaceId??"cli";return{ref:`${$}:local`,label:$.toUpperCase()}}summarizeDataForLog(A){return{url:A.url,interfaceId:A.metadata?.interfaceId}}}async function cx2({entity:A,config:Q}){let w=oh.parse(A),{frontmatter:$,summary:B}=cd.parseLinkContent(w.content);return{$type:"ai.rizom.brain.link",title:$.title,url:$.url,...$.description&&{description:$.description},...B&&{summary:B},domain:$.domain,capturedAt:$.capturedAt,source:$.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 yKA(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:I$["ai.rizom.brain.link"],validate:!1,buildRecord:cx2}}var px2={name:"@brains/link",version:"0.2.0-alpha.181",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 jK6=H.object({url:H.url()});class TKA extends jw{entityType=cd.entityType;schema=oh;adapter=cd;shell;unregisterAtprotoProjection;constructor(A={}){super("link",px2,A,RKA)}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 P_0(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 X=this.adapter.fromMarkdown(A.content).metadata,Y=typeof X?.title==="string"?X.title:void 0,Z=typeof X?.status==="string"?X.status:void 0,W=this.extractFirstUrl(A.content);if(Y&&Z&&W){let K=F1(W)||F1(Y)||`${A.entityType}-${Date.now()}`,U=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await w.entityService.createEntity({entity:{id:K,entityType:A.entityType,content:A.content,metadata:{title:Y,status:Z},created:U,updated:U}})).entityId,status:"created"}}}}}catch{}let $=A.url??this.extractFirstUrl(A.content,A.prompt,A.title);if($){if(!this.shell)throw Error("LinkPlugin shell was not initialized during register()");try{let B=await this.createPendingLink($,A.title,Q,w),X=await this.shell.getJobQueueService().enqueue({type:"link-capture",data:{url:$,metadata:{interfaceId:Q.interfaceType,userId:Q.userId,...Q.channelId?{channelId:Q.channelId}:{},...Q.channelName?{channelName:Q.channelName}:{},timestamp:new Date().toISOString()}},options:{source:this.id,metadata:{operationType:"data_processing",pluginId:this.id,interfaceType:Q.interfaceType,...Q.channelId?{channelId:Q.channelId}:{}}}});return{kind:"handled",result:{success:!0,data:{entityId:B,status:"generating",jobId:X}}}}catch(B){return{kind:"handled",result:{success:!1,error:B instanceof Error?B.message:"Failed to queue link capture job"}}}}if(A.content)return{kind:"handled",result:{success:!1,error:"Direct link creation requires full link markdown/frontmatter, or provide a URL to capture."}};if(A.prompt)return{kind:"handled",result:{success:!1,error:"Link creation requires a URL in the prompt, content, or title, or full link markdown content for direct creation."}};return{kind:"continue",input:A}}createGenerationHandler(A){return new P_0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:Sx2,"link-list":mx2,"link-detail":ux2}}getDataSources(){return[new gKA(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=fB.getInstance().register(yKA()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=jK6.parse(Q),B=await new pd(this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0).fetch(w);if(!B.success)return{success:!1,error:B.error,errorType:B.errorType};return A.ai.generate({templateName:"link:extraction",prompt:`Extract structured information from this webpage content:
|
|
7524
7524
|
|
|
7525
7525
|
${B.content}`,data:{url:w,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,w,$){let B=ej.generateEntityId(A),X=new URL(A),Y=new Date().toISOString(),Z=Q?.trim()?Q.trim():X.hostname,W=this.adapter.createLinkContent({status:"pending",title:Z,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:X.hostname,capturedAt:Y,source:this.resolveSource(w)});return(await XR({entityService:$.entityService,entity:{id:B,entityType:"link",content:W,metadata:{status:"pending",title:Z},created:Y,updated:Y}})).entityId}resolveSource(A){if(A.channelId)return{ref:`matrix:${A.channelId}`,label:A.channelName??A.channelId};return{ref:`${A.interfaceType}:local`,label:A.interfaceType.toUpperCase()}}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[w]=ej.extractUrls(Q);if(w)return w}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function lx2(A={}){return new TKA(A)}var sh=lx2;b0();var OK6=H.object({conversationId:H.string().optional(),interfaceId:H.string().optional(),userId:H.string().optional(),messageId:H.string().optional(),timestamp:H.string().optional()}),IW5=H.object({id:H.string().optional(),metadata:OK6.optional()});$A();b0();y8();b0();$A();var dx2=H.enum(["generating","draft","published","failed"]),ix2=H.enum(["generating","draft","published","failed"]),VX=H.object({title:H.string(),slug:H.string().optional(),status:dx2,publishedAt:H.string().datetime().optional(),description:H.string(),year:H.number(),coverImageId:H.string().optional(),ogImageId:H.string().optional(),url:H.string().url().optional()}),fK6=VX.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:H.string(),error:H.string().optional()}),xK6=H.object({title:H.string(),status:ix2,publishedAt:H.string().datetime().optional(),year:H.number(),slug:H.string(),error:H.string().optional()}),RK6=H.object({title:H.string(),slug:H.string().optional(),status:ix2,publishedAt:H.string().datetime().optional(),description:H.string(),year:H.number(),coverImageId:H.string().optional(),ogImageId:H.string().optional(),url:H.string().url().optional()}),AO=aQ.extend({entityType:H.literal("project"),metadata:xK6}),M_0=H.object({context:H.string(),problem:H.string(),solution:H.string(),outcome:H.string()}),E$0=AO.extend({frontmatter:RK6,body:H.string(),structuredContent:M_0.optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional()}),vK6=E$0.extend({url:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),CK6=E$0.extend({url:H.string(),typeLabel:H.string(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});$A();R2();z9();class SKA extends R6{constructor(){super(M_0,{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 mKA=new SKA;class uKA extends QQ{constructor(){super({entityType:"project",purpose:"A project record in the user's portfolio.",schema:AO,frontmatterSchema:VX,supportsCoverImage:!0,bodyFormatter:mKA})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,VX),$={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,VX),w=Q.slug??F1(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,VX)}parseStructuredContent(A){return mKA.parse(this.extractBody(A.content))}createProjectContent(A,Q){let w=mKA.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 ah=new uKA;b0();var cKA=H.looseObject({});import{jsxDEV as sU,Fragment as EK6}from"preact/jsx-dev-runtime";var hK6=({project:A})=>{let{frontmatter:Q,url:w,coverImageUrl:$}=A;return sU(W$,{href:w,children:[$&&sU("img",{src:$,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),sU(GX,{children:Q.title},void 0,!1,void 0,this),sU("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},pKA=({projects:A,pageTitle:Q,pagination:w,baseUrl:$="/projects"})=>{let B=Q??"Projects",X=w?.totalItems??A.length,Y=`Browse all ${X} ${X===1?"project":"projects"}`;return sU(EK6,{children:[sU(Nw,{title:B,description:Y},void 0,!1,void 0,this),sU("div",{className:"project-list bg-theme",children:sU("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[sU("h1",{className:"text-4xl font-bold text-heading mb-12",children:B},void 0,!1,void 0,this),sU("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((Z)=>sU(hK6,{project:Z},Z.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&sU("div",{className:"mt-12",children:sU(F_,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as n$,Fragment as nx2}from"preact/jsx-dev-runtime";var gK6=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return n$("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:n$("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?n$(W$,{href:A.url,variant:"compact",children:[n$("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),n$("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):n$("div",{},void 0,!1,void 0,this),Q&&n$(W$,{href:Q.url,variant:"compact",className:"md:text-right",children:[n$("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),n$("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)},j_0=({title:A,content:Q})=>{if(!Q)return null;return n$("section",{className:"mb-12",children:[n$("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),n$(L4,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},lKA=({project:A,prevProject:Q,nextProject:w})=>{let{frontmatter:$,structuredContent:B,metadata:X,coverImageUrl:Y}=A,Z=A.ogImageUrl??Y;return n$(nx2,{children:[n$(Nw,{title:$.title,description:$.description,...Z?{ogImage:Z}:{},ogType:"article"},void 0,!1,void 0,this),n$("article",{className:"project-detail",children:n$("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:n$("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&n$(J_,{src:Y,alt:$.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),n$("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:$.title},void 0,!1,void 0,this),n$("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[n$("span",{className:"text-sm",children:X.year},void 0,!1,void 0,this),$.url&&n$(nx2,{children:[n$("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),n$("a",{href:$.url,target:"_blank",rel:"noopener noreferrer",className:"text-brand hover:text-brand-dark transition-colors",children:"View Project"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),n$("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:$.description},void 0,!1,void 0,this),B&&n$("div",{className:"case-study",children:[n$(j_0,{title:"Context",content:B.context},void 0,!1,void 0,this),n$(j_0,{title:"Problem",content:B.problem},void 0,!1,void 0,this),n$(j_0,{title:"Solution",content:B.solution},void 0,!1,void 0,this),n$(j_0,{title:"Outcome",content:B.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),n$(gK6,{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)};b0();$A();var yK6=H.object({title:H.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:H.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:H.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:H.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:H.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:H.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),dKA=$2({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:yK6,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
|
|
7526
7526
|
|
|
@@ -7696,7 +7696,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7696
7696
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7697
7697
|
}
|
|
7698
7698
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
7699
|
-
`}},void 0,!1,void 0,this),M4("section",{className:"project-shell",children:[M4("header",{className:"project-hero",children:[M4("div",{className:"project-index",children:[Q.brandLabel&&M4("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&M4("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M4("div",{className:"project-title-panel",children:[M4("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),M4("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&M4("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),M4("div",{className:"printable-meta",children:[Q.year&&M4("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&M4("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&&M4("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),M4(L4,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&M4("footer",{className:"printable-footer",children:[M4("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?M4("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 iK6=26214400,nK6=60000;class rKA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==x_0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=rK6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await cK6(dK6(lK6(),"brain-project-printable-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/printable/project/${Q.id}`,template:sx2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:iK6,timeoutMs:nK6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${oK6(Q)}-printable.pdf`}}finally{await X.close()}}finally{await pK6($,{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}=M$(A.content),w=VX.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function rK6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=VX.parse(w);return{title:B.title,body:$,...B.description?{description:B.description}:{},year:B.year,...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.url?{url:B.url,canonicalUrl:B.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function oK6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}Q4();R2();b0();import{jsxDEV as tK6}from"preact/jsx-dev-runtime";var R_0="og-image",sK6="portfolio:og-image",ax2=H.object({title:H.string().min(1),description:H.string().optional(),year:H.number().optional(),brandLabel:H.string().optional(),coverImageUrl:H.string().optional()}),tx2={name:sK6,pluginId:"portfolio",schema:ax2,renderers:{image:aK6}};function aK6(A){let Q=ax2.parse(A);return tK6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class oKA{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!==R_0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=M$(Q.content),$=VX.parse(w),B=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),Y={title:$.title,...$.description?{description:$.description}:{},year:$.year,...X?{coverImageUrl:X}:{},...B?{brandLabel:B}:{}};return{type:"image",data:await Th({mediaPath:`/_media/og/project/${Q.id}`,template:tx2,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:`${eK6(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 eK6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}var ex2={name:"@brains/portfolio",version:"0.2.0-alpha.180",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 QU6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),wU6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),AR2=H.enum(["generating","draft","published","failed"]),$U6=H.object({title:H.string(),slug:H.string().optional(),status:AR2,publishedAt:H.string().optional(),description:H.string(),year:H.number(),coverImageId:H.string().optional(),ogImageId:H.string().optional(),url:H.url().optional()}),BU6=H.object({title:H.string(),status:AR2,publishedAt:H.string().optional(),year:H.number(),slug:H.string(),error:H.string().optional()}),XU6=H.object({context:H.string(),problem:H.string(),solution:H.string(),outcome:H.string()}),v_0=H.object({id:H.string(),entityType:H.literal("project"),content:H.string(),created:H.string(),updated:H.string(),visibility:wU6,metadata:BU6,contentHash:H.string(),frontmatter:$U6,body:H.string(),structuredContent:XU6.optional(),url:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),YU6=H.object({projects:H.array(v_0),pageTitle:H.string().optional(),pagination:QU6.nullable(),baseUrl:H.string().optional()}),ZU6=H.object({prompt:H.string(),year:H.number()});function HU6(A,Q){for(let w of[A,Q]){let $=w?.match(/\b(19\d{2}|20\d{2})\b/);if($?.[1])return Number($[1])}return null}class sKA extends jw{entityType="project";schema=AO;adapter=ah;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",ex2,A,cKA)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let $=HU6(A.title,A.prompt);if(!$)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:$},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new O_0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":$2({name:"project-list",description:"Portfolio project list page template",schema:YU6,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:pKA}}),"project-detail":$2({name:"project-detail",description:"Individual project case study template",schema:H.object({project:v_0,prevProject:v_0.nullable(),nextProject:v_0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:lKA}}),generation:dKA}}getDataSources(){return[new f_0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",x_0,new rKA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",R_0,new oKA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=fB.getInstance().register(nKA())}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=ZU6.parse(Q);return A.ai.generate({prompt:iKA(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:$}=Q.payload;if(w!=="project")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"project",id:$});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:`Project not found: ${$}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=DQ(B.content,VX),Y=new Date().toISOString(),Z=Y7(X.content,{...X.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...B,content:Z,metadata:{...B.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:$,publishedAt:Y}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:lA(B)}})}return{success:!0}})}}function aKA(A={}){return new sKA(A)}$A();b0();y8();b0();$A();var QR2=H.enum(["available","early access","coming soon","planned"]),wR2=H.enum(["available","early access","coming soon","planned"]),$R2=H.object({title:H.string(),description:H.string()}),wD=H.object({name:H.string(),availability:QR2,order:H.number(),ogImageId:H.string().optional()}),C_0=H.object({tagline:H.string(),promise:H.string(),role:H.string(),purpose:H.string(),audience:H.string(),values:H.array(H.string()).min(1),features:H.array($R2).min(1).max(6),story:H.string()}),VU5=wD.pick({name:!0,availability:!0,order:!0}).extend({slug:H.string()}),WU6=H.object({name:H.string(),availability:wR2,order:H.number(),slug:H.string()}),KU6=H.object({name:H.string(),availability:wR2,order:H.number(),ogImageId:H.string().optional()}),ld=aQ.extend({entityType:H.literal("product"),metadata:WU6}),h_0=ld.extend({frontmatter:KU6,body:C_0,labels:H.record(H.string(),H.string()),ogImageUrl:H.string().optional()}),UU6=h_0.extend({url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),ogImageUrl:H.string().optional()});$A();R2();z9();class dd extends R6{constructor(){super(C_0,{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 tKA extends QQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:ld,frontmatterSchema:wD,bodyFormatter:new dd})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,wD);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,wD),w=F1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var E_0=new tKA;b0();$A();var BR2=H.object({title:H.string(),description:H.string()}),XR2=H.object({title:H.string(),description:H.string()}),GU6=H.object({title:H.string(),description:H.string()}),YR2=H.object({heading:H.string(),buttonText:H.string(),link:H.string()}),QO=H.object({headline:H.string(),tagline:H.string()}),DU6=H.object({title:H.string(),description:H.string()}),g_0=H.object({vision:H.string(),pillars:H.array(BR2).min(1).max(6),approach:H.array(DU6).min(1).max(6),productsIntro:H.string(),technologies:H.array(GU6).min(1).max(6),benefits:H.array(XR2).min(1).max(6),cta:YR2}),qU6=QO.pick({headline:!0}).extend({slug:H.string()}),zU6=H.object({headline:H.string(),slug:H.string()}),JU6=H.object({headline:H.string(),tagline:H.string()}),id=aQ.extend({entityType:H.literal("products-overview"),metadata:zU6}),eKA=id.extend({frontmatter:JU6,body:g_0,labels:H.record(H.string(),H.string())});$A();R2();z9();class nd extends R6{constructor(){super(g_0,{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 AUA extends QQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:id,frontmatterSchema:QO,bodyFormatter:new nd})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,QO);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,QO),w=F1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var QUA=new AUA;$A();b0();var VU6=H.object({entityType:H.string(),query:H.object({id:H.string().optional()}).optional()});function ZR2(A,Q){let w=DQ(A.content,wD),$=Q.parse(w.content),B=Q.getLabels();return h_0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}function HR2(A,Q){let w=DQ(A.content,QO),$=Q.parse(w.content),B=Q.getLabels();return eKA.parse({...A,frontmatter:w.metadata,body:$,labels:B})}class y_0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new nd;productFormatter=new dd;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let $=VU6.parse(A),B=w.entityService;if($.entityType==="products-overview"){let K=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!K)throw Error("Products overview entity not found");let U=HR2(K,this.overviewFormatter);return Q.parse(U)}if($.query?.id){let K=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:$.query.id}},limit:1}}))[0];if(!K)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:ZR2(K,this.productFormatter)})}let[X,Y]=await Promise.all([B.listEntities({entityType:"products-overview",options:{limit:1}}),B.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Z=X[0];if(!Z)throw Error("Products overview entity not found");return Q.parse({overview:HR2(Z,this.overviewFormatter),products:Y.map((W)=>ZR2(W,this.productFormatter))})}}import{jsxDEV as _1,Fragment as LU6}from"preact/jsx-dev-runtime";var WR2=({overview:A,products:Q})=>{let{frontmatter:w,body:$,labels:B}=A;return _1(LU6,{children:[_1(Nw,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),_1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[_1("style",{children:`
|
|
7699
|
+
`}},void 0,!1,void 0,this),M4("section",{className:"project-shell",children:[M4("header",{className:"project-hero",children:[M4("div",{className:"project-index",children:[Q.brandLabel&&M4("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&M4("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),M4("div",{className:"project-title-panel",children:[M4("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),M4("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&M4("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),M4("div",{className:"printable-meta",children:[Q.year&&M4("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&M4("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&&M4("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),M4(L4,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&M4("footer",{className:"printable-footer",children:[M4("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?M4("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 iK6=26214400,nK6=60000;class rKA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==x_0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=rK6(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await cK6(dK6(lK6(),"brain-project-printable-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/printable/project/${Q.id}`,template:sx2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:iK6,timeoutMs:nK6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${oK6(Q)}-printable.pdf`}}finally{await X.close()}}finally{await pK6($,{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}=M$(A.content),w=VX.parse(Q);if(!w.coverImageId)return;let $=await this.context.entityService.getEntity({entityType:"image",id:w.coverImageId});return $?.content.startsWith("data:image/")?$.content:void 0}}function rK6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=VX.parse(w);return{title:B.title,body:$,...B.description?{description:B.description}:{},year:B.year,...B.publishedAt?{publishedAt:B.publishedAt}:{},...B.url?{url:B.url,canonicalUrl:B.url}:{},...Q.coverImageUrl?{coverImageUrl:Q.coverImageUrl}:{},...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function oK6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}Q4();R2();b0();import{jsxDEV as tK6}from"preact/jsx-dev-runtime";var R_0="og-image",sK6="portfolio:og-image",ax2=H.object({title:H.string().min(1),description:H.string().optional(),year:H.number().optional(),brandLabel:H.string().optional(),coverImageUrl:H.string().optional()}),tx2={name:sK6,pluginId:"portfolio",schema:ax2,renderers:{image:aK6}};function aK6(A){let Q=ax2.parse(A);return tK6(z_,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class oKA{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!==R_0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=M$(Q.content),$=VX.parse(w),B=this.resolveBrandLabel(),X=await this.resolveCoverImageUrl($.coverImageId),Y={title:$.title,...$.description?{description:$.description}:{},year:$.year,...X?{coverImageUrl:X}:{},...B?{brandLabel:B}:{}};return{type:"image",data:await Th({mediaPath:`/_media/og/project/${Q.id}`,template:tx2,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:`${eK6(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 eK6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.title)}var ex2={name:"@brains/portfolio",version:"0.2.0-alpha.181",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 QU6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),wU6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),AR2=H.enum(["generating","draft","published","failed"]),$U6=H.object({title:H.string(),slug:H.string().optional(),status:AR2,publishedAt:H.string().optional(),description:H.string(),year:H.number(),coverImageId:H.string().optional(),ogImageId:H.string().optional(),url:H.url().optional()}),BU6=H.object({title:H.string(),status:AR2,publishedAt:H.string().optional(),year:H.number(),slug:H.string(),error:H.string().optional()}),XU6=H.object({context:H.string(),problem:H.string(),solution:H.string(),outcome:H.string()}),v_0=H.object({id:H.string(),entityType:H.literal("project"),content:H.string(),created:H.string(),updated:H.string(),visibility:wU6,metadata:BU6,contentHash:H.string(),frontmatter:$U6,body:H.string(),structuredContent:XU6.optional(),url:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),YU6=H.object({projects:H.array(v_0),pageTitle:H.string().optional(),pagination:QU6.nullable(),baseUrl:H.string().optional()}),ZU6=H.object({prompt:H.string(),year:H.number()});function HU6(A,Q){for(let w of[A,Q]){let $=w?.match(/\b(19\d{2}|20\d{2})\b/);if($?.[1])return Number($[1])}return null}class sKA extends jw{entityType="project";schema=AO;adapter=ah;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",ex2,A,cKA)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let $=HU6(A.title,A.prompt);if(!$)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:$},toolContext:Q,options:{source:this.id,metadata:{operationType:"content_operations"}}})}}}}createGenerationHandler(A){return new O_0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":$2({name:"project-list",description:"Portfolio project list page template",schema:YU6,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:pKA}}),"project-detail":$2({name:"project-detail",description:"Individual project case study template",schema:H.object({project:v_0,prevProject:v_0.nullable(),nextProject:v_0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:lKA}}),generation:dKA}}getDataSources(){return[new f_0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",x_0,new rKA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",R_0,new oKA(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=fB.getInstance().register(nKA())}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=ZU6.parse(Q);return A.ai.generate({prompt:iKA(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:$}=Q.payload;if(w!=="project")return{success:!0};try{let B=await A.entityService.getEntity({entityType:"project",id:$});if(!B)return await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:`Project not found: ${$}`}}),{success:!0};if(B.metadata.status==="published")return{success:!0};let X=DQ(B.content,VX),Y=new Date().toISOString(),Z=Y7(X.content,{...X.metadata,status:"published",publishedAt:Y});await A.entityService.updateEntity({entity:{...B,content:Z,metadata:{...B.metadata,status:"published",publishedAt:Y}}}),await A.messaging.send({type:"publish:report:success",payload:{entityType:w,entityId:$,publishedAt:Y}})}catch(B){await A.messaging.send({type:"publish:report:failure",payload:{entityType:w,entityId:$,error:lA(B)}})}return{success:!0}})}}function aKA(A={}){return new sKA(A)}$A();b0();y8();b0();$A();var QR2=H.enum(["available","early access","coming soon","planned"]),wR2=H.enum(["available","early access","coming soon","planned"]),$R2=H.object({title:H.string(),description:H.string()}),wD=H.object({name:H.string(),availability:QR2,order:H.number(),ogImageId:H.string().optional()}),C_0=H.object({tagline:H.string(),promise:H.string(),role:H.string(),purpose:H.string(),audience:H.string(),values:H.array(H.string()).min(1),features:H.array($R2).min(1).max(6),story:H.string()}),VU5=wD.pick({name:!0,availability:!0,order:!0}).extend({slug:H.string()}),WU6=H.object({name:H.string(),availability:wR2,order:H.number(),slug:H.string()}),KU6=H.object({name:H.string(),availability:wR2,order:H.number(),ogImageId:H.string().optional()}),ld=aQ.extend({entityType:H.literal("product"),metadata:WU6}),h_0=ld.extend({frontmatter:KU6,body:C_0,labels:H.record(H.string(),H.string()),ogImageUrl:H.string().optional()}),UU6=h_0.extend({url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),ogImageUrl:H.string().optional()});$A();R2();z9();class dd extends R6{constructor(){super(C_0,{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 tKA extends QQ{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:ld,frontmatterSchema:wD,bodyFormatter:new dd})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,wD);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,wD),w=F1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var E_0=new tKA;b0();$A();var BR2=H.object({title:H.string(),description:H.string()}),XR2=H.object({title:H.string(),description:H.string()}),GU6=H.object({title:H.string(),description:H.string()}),YR2=H.object({heading:H.string(),buttonText:H.string(),link:H.string()}),QO=H.object({headline:H.string(),tagline:H.string()}),DU6=H.object({title:H.string(),description:H.string()}),g_0=H.object({vision:H.string(),pillars:H.array(BR2).min(1).max(6),approach:H.array(DU6).min(1).max(6),productsIntro:H.string(),technologies:H.array(GU6).min(1).max(6),benefits:H.array(XR2).min(1).max(6),cta:YR2}),qU6=QO.pick({headline:!0}).extend({slug:H.string()}),zU6=H.object({headline:H.string(),slug:H.string()}),JU6=H.object({headline:H.string(),tagline:H.string()}),id=aQ.extend({entityType:H.literal("products-overview"),metadata:zU6}),eKA=id.extend({frontmatter:JU6,body:g_0,labels:H.record(H.string(),H.string())});$A();R2();z9();class nd extends R6{constructor(){super(g_0,{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 AUA extends QQ{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:id,frontmatterSchema:QO,bodyFormatter:new nd})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,QO);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,QO),w=F1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var QUA=new AUA;$A();b0();var VU6=H.object({entityType:H.string(),query:H.object({id:H.string().optional()}).optional()});function ZR2(A,Q){let w=DQ(A.content,wD),$=Q.parse(w.content),B=Q.getLabels();return h_0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}function HR2(A,Q){let w=DQ(A.content,QO),$=Q.parse(w.content),B=Q.getLabels();return eKA.parse({...A,frontmatter:w.metadata,body:$,labels:B})}class y_0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new nd;productFormatter=new dd;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let $=VU6.parse(A),B=w.entityService;if($.entityType==="products-overview"){let K=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!K)throw Error("Products overview entity not found");let U=HR2(K,this.overviewFormatter);return Q.parse(U)}if($.query?.id){let K=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:$.query.id}},limit:1}}))[0];if(!K)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:ZR2(K,this.productFormatter)})}let[X,Y]=await Promise.all([B.listEntities({entityType:"products-overview",options:{limit:1}}),B.listEntities({entityType:"product",options:{sortFields:[{field:"order",direction:"asc"}]}})]),Z=X[0];if(!Z)throw Error("Products overview entity not found");return Q.parse({overview:HR2(Z,this.overviewFormatter),products:Y.map((W)=>ZR2(W,this.productFormatter))})}}import{jsxDEV as _1,Fragment as LU6}from"preact/jsx-dev-runtime";var WR2=({overview:A,products:Q})=>{let{frontmatter:w,body:$,labels:B}=A;return _1(LU6,{children:[_1(Nw,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),_1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[_1("style",{children:`
|
|
7700
7700
|
@keyframes wave-drift {
|
|
7701
7701
|
from { transform: translateX(0); }
|
|
7702
7702
|
to { transform: translateX(-50%); }
|
|
@@ -7891,7 +7891,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7891
7891
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7892
7892
|
}
|
|
7893
7893
|
`}},void 0,!1,void 0,this),aU("section",{className:"product-shell",children:[aU("header",{className:"product-hero",children:[Q.brandLabel&&aU("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),aU("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&aU("div",{className:"printable-meta",children:aU("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),aU("div",{className:"product-body-wrap",children:[aU("aside",{className:"product-rail","aria-hidden":"true",children:aU("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),aU(L4,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&aU("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 OU6=26214400,fU6=60000;class $UA{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??Dz}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==T_0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let w=xU6(Q,{brandLabel:this.resolveBrandLabel()}),$=await kU6(jU6(MU6(),"brain-product-printable-"));try{let B=await mU({outputDir:$,mediaPath:`/_media/printable/product/${Q.id}`,template:GR2,format:"pdf",content:w,siteConfig:{title:w.name,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await uU({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:OU6,timeoutMs:fU6,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${RU6(Q)}-printable.pdf`}}finally{await X.close()}}finally{await PU6($,{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 xU6(A,Q={}){let{frontmatter:w,content:$}=M$(A.content),B=wD.parse(w);return{name:B.name,body:$,availability:B.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function RU6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.name)}Q4();R2();b0();import{jsxDEV as hU6}from"preact/jsx-dev-runtime";var S_0="og-image",vU6="products:og-image",DR2=H.object({name:H.string().min(1),tagline:H.string().optional(),availability:H.string().optional(),brandLabel:H.string().optional()}),qR2={name:vU6,pluginId:"products",schema:DR2,renderers:{image:CU6}};function CU6(A){let Q=DR2.parse(A);return hU6(z_,{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 BUA{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!==S_0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=M$(Q.content),B=wD.parse(w),X=EU6($,"Tagline"),Y=this.resolveBrandLabel(),Z={name:B.name,availability:B.availability,...X?{tagline:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await Th({mediaPath:`/_media/og/product/${Q.id}`,template:qR2,content:Z,title:Z.name,themeMode:"light",themeCSS:this.context.themeCSS,tmpPrefix:"brain-product-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${gU6(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 EU6(A,Q){let w=A.split(/\r?\n/),$=w.findIndex((Y)=>Y.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if($===-1)return;let B=[];for(let Y of w.slice($+1)){if(Y.trim().startsWith("## "))break;B.push(Y)}let X=B.join(`
|
|
7894
|
-
`).trim();return X.length>0?X:void 0}function gU6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.name)}var zR2={name:"@brains/products",version:"0.2.0-alpha.
|
|
7894
|
+
`).trim();return X.length>0?X:void 0}function gU6(A){let Q=A.metadata.slug;return Q.length>0?Q:F1(A.metadata.name)}var zR2={name:"@brains/products",version:"0.2.0-alpha.181",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 TU6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),JR2=H.object({id:H.string(),entityType:H.string(),content:H.string(),created:H.string(),updated:H.string(),visibility:TU6,metadata:H.record(H.string(),H.unknown()),contentHash:H.string()}),VR2=H.enum(["available","early access","coming soon","planned"]),SU6=H.object({title:H.string(),description:H.string()}),mU6=H.object({name:H.string(),availability:VR2,order:H.number(),ogImageId:H.string().optional()}),uU6=H.object({tagline:H.string(),promise:H.string(),role:H.string(),purpose:H.string(),audience:H.string(),values:H.array(H.string()).min(1),features:H.array(SU6).min(1).max(6),story:H.string()}),cU6=H.object({name:H.string(),availability:VR2,order:H.number(),slug:H.string()}),FR2=JR2.extend({entityType:H.literal("product"),metadata:cU6,frontmatter:mU6,body:uU6,labels:H.record(H.string(),H.string()),url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),ogImageUrl:H.string().optional()}),m_0=H.object({title:H.string(),description:H.string()}),pU6=H.object({heading:H.string(),buttonText:H.string(),link:H.string()}),lU6=H.object({headline:H.string(),tagline:H.string()}),dU6=H.object({vision:H.string(),pillars:H.array(m_0).min(1).max(6),approach:H.array(m_0).min(1).max(6),productsIntro:H.string(),technologies:H.array(m_0).min(1).max(6),benefits:H.array(m_0).min(1).max(6),cta:pU6}),iU6=H.object({headline:H.string(),slug:H.string()}),nU6=JR2.extend({entityType:H.literal("products-overview"),metadata:iU6,frontmatter:lU6,body:dU6,labels:H.record(H.string(),H.string())}),rU6=H.object({overview:nU6,products:H.array(FR2)}),oU6=H.object({product:FR2});class XUA extends jw{entityType=E_0.entityType;schema=ld;adapter=E_0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",zR2,A,wUA)}getTemplates(){return{"product-list":$2({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:rU6,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:WR2}}),"product-detail":$2({name:"product-detail",description:"Individual product detail page",schema:oU6,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:KR2}})}}getDataSources(){return[new y_0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",T_0,new $UA(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",S_0,new BUA(A)),A.entities.register("products-overview",id,QUA)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function g$0(A={}){return new XUA(A)}$A();b0();b0();var sU6=H.enum(["public","shared","restricted"]),IR2=H.object({includeEntityTypes:H.array(H.string()).default([]),minRelevanceScore:H.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:H.number().min(0).max(1).default(0.85),autoMerge:H.boolean().default(!0),extractableStatuses:H.array(H.string()).default(["published"]),enableAutoExtraction:H.boolean().default(!0),extractionVisibility:sU6.default("public"),sourceChangeBatchDelayMs:H.number().int().min(0).default(1000)});$A();b0();$A();var Q35=H.object({}),aU6=H.record(H.string(),H.unknown()).transform(()=>({})),rd=aQ.extend({entityType:H.literal("topic"),metadata:aU6}),w35=H.object({content:H.string()}),LR2=H.object({title:H.string().describe("Topic title")});var th="topics",r$="topic",YUA="topics-projection",NR2="topic:project",u_0="topics-plugin",_R2="topics:batch-completed",bR2="topics-source-batch";class Vz extends QQ{constructor(){super({entityType:r$,purpose:"A recurring theme or subject derived from the user's content.",schema:rd,frontmatterSchema:LR2})}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:r$}}extractMetadata(A){return{}}generateFrontMatter(A){let Q=this.parseTopicBody(A.content),$=this.buildMarkdown("",this.buildFrontmatter(Q.title)).match(/^---\n[\s\S]*?\n---/);return $?$[0]:""}parseTopicBody(A){if(A.startsWith("---"))try{let Q=this.parseFrontmatter(A);return{content:this.extractBody(A).replace(/\n*## Sources[\s\S]*$/,"").trim(),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))}}$A();b0();b0();var tU6=H.object({title:H.string().max(100),content:H.string(),relevanceScore:H.number().min(0).max(1)}),kR2=H.array(tU6);var eU6=H.object({topics:kR2}),PR2=$2({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:eU6,basePrompt:`You are an expert at analyzing content and extracting key topics.
|
|
7895
7895
|
|
|
7896
7896
|
Analyze the provided content and extract meaningful topics discussed.
|
|
7897
7897
|
|
|
@@ -7994,13 +7994,13 @@ ${A.incomingTopic.content}`})}}function UG6(A){if(A.length===0)return"";return A
|
|
|
7994
7994
|
|
|
7995
7995
|
${Q.content}`}).join(`
|
|
7996
7996
|
|
|
7997
|
-
`)}async function eh(A,Q,w,$={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let B=$.minRelevanceScore??0,X=$.autoMerge??!1,Y=$.mergeSimilarityThreshold??0.85,Z=$.targetVisibility??"public",W=gR2(A),K=new Fz(Q.entityService,w),U=$.topicMergeSynthesizer??new GUA(Q,w),G=await i_0(Q.entityService,void 0,Z),D=new Map,z=0,V=0,I=0;for(let _ of W){w.info(`Processing batch of ${_.length} entities`);let k=UG6(_),b=n_0({entityTitle:`Batch of ${_.length} entities`,entityType:"batch",content:k,existingTopicTitles:G});try{let R=(await Q.ai.generate({prompt:b,templateName:"topics:extraction"})).topics.filter((v)=>v.relevanceScore>=B);for(let v of R)try{if(X){let S=await K.findMergeCandidate({incoming:v,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(S){let l=await U.synthesize({existingTopic:S.topic,incomingTopic:v}),o=await K.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...l,title:S.title},visibility:Z});if(!o)throw Error(`Failed to merge topic: ${v.title}`);D.set(o.id,o),V++;continue}}let M=K.getTopicIdForTitle(v.title,Z);if(D.has(M)){I++;continue}let y=await K.createTopicOptimistic({title:v.title,content:v.content,visibility:Z});if(y.topic)D.set(y.topic.id,y.topic);if(y.created)z++;else I++}catch(M){w.error("Topic batch item failed",{title:v.title,error:lA(M)})}}catch(f){w.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:lA(f)})}}let F={created:z,merged:V,skipped:I,batches:W.length};if(z>0||V>0)await Q.messaging.send({type:_R2,payload:F,broadcast:!0});return F}$A();b0();var GG6=H.discriminatedUnion("mode",[H.object({mode:H.literal("derive"),reason:H.string().optional()}),H.object({mode:H.literal("rebuild"),reason:H.string().optional()}),H.object({mode:H.literal("source-batch"),minRelevanceScore:H.number().min(0).max(1).optional()})]);class DUA{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 cR2(A){let{context:Q,logger:w,config:$}=A;return{process:async(B)=>{if(B.mode==="derive")return await A.extractAllTopics(),{success:!0};if(B.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return DG6({context:Q,logger:w,config:$,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??$.minRelevanceScore})},validateAndParse:(B)=>{let X=GG6.safeParse(B??{});return X.success?X.data:null}}}async function DG6(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(K)=>({ref:K,entity:await A.context.entityService.getEntity({entityType:K.entityType,id:K.entityId})}))),$=0,B=0,X=0,Y=0,Z=[];for(let{ref:K,entity:U}of w){if(!U){B++;continue}if(U.contentHash!==K.contentHash){$++;continue}if(!A.isEntityPublished(U)){X++;continue}if(!tk(U.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(U)}if(Z.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:$,missing:B,unpublished:X,hidden:Y};let W=await eh(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...W,stale:$,missing:B,unpublished:X,hidden:Y}}function pR2(){return{priority:5,source:u_0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:th}}}async function lR2(A){let Q=await iR2(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 eh(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 dR2(A){let Q=await iR2(A),w=await qUA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function qUA(A,Q,w,$){let B=new Fz(Q.entityService,w),X=await B.listTopics({visibility:$.extractionVisibility});for(let Z of X)await B.deleteTopic(Z.id);if(A.length===0)return{deleted:X.length,created:0,merged:0,skipped:0,batches:0};let Y=await eh(A,Q,w,{minRelevanceScore:$.minRelevanceScore,autoMerge:$.autoMerge,mergeSimilarityThreshold:$.mergeSimilarityThreshold,targetVisibility:$.extractionVisibility});return{deleted:X.length,...Y}}async function iR2(A){let Q=qG6(A),w=[];for(let $ of Q){let B=await A.context.entityService.listEntities({entityType:$,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let X of B){if(!A.isEntityPublished(X))continue;w.push(X)}}return w}function qG6(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var ad=H.object({entityType:H.string(),content:H.string(),metadata:H.record(H.string(),H.unknown()).optional()}),zG6=ad.extend({minRelevanceScore:H.number().optional()}),JG6=H.object({contentA:ad,contentB:ad,minRelevanceScore:H.number().optional(),threshold:H.number().min(0).max(1).optional()}),m$0=H.object({title:H.string(),content:H.string()}),VG6=H.object({existingTopics:H.array(m$0),incomingTopic:m$0,threshold:H.number().optional()}),FG6=H.object({existingTopics:H.array(m$0).default([]),incomingTopic:m$0.extend({relevanceScore:H.number().min(0).max(1).optional()}),threshold:H.number().optional()}),IG6=H.object({entities:H.array(ad).min(1),minRelevanceScore:H.number().optional()}),LG6=H.object({existingTopics:H.array(m$0).optional(),entities:H.array(ad)}),NG6=H.object({entities:H.array(ad)});function sd(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:mw(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function nR2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function _G6(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function bG6(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:_G6(Q)}]}}async function AE(A){let Q=await A.entityService.listEntities({entityType:r$});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:r$,id:w.id})))}async function kG6(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function rR2(A){let{context:Q,logger:w,config:$}=A,B=new UUA(Q,w),X=async(Y,Z,W="")=>{let K=sd(Y,W);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await AE(Q);let Z=zG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=sd(Z);return(await B.extractFromEntity(K,W)).map((G)=>bG6(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await AE(Q);let Z=JG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=Z.threshold??$.mergeSimilarityThreshold,[U,G]=await Promise.all([X(Z.contentA,W,"-a"),X(Z.contentB,W,"-b")]),D=new Fz(Q.entityService,w),z=[];for(let F of U){let _=await D.createTopic(F);if(_)z.push(_)}let V=(await Promise.all(G.map(async(F)=>{let _=await D.findMergeCandidate({incoming:F,threshold:K,additionalCandidates:z});if(!_)return null;return{incomingTitle:F.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((F)=>F!==null),I=V.map((F)=>F.candidateTitle);return{topicsA:U.map(nR2),topicsB:G.map(nR2),matchingTitles:I,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await AE(Q);let Z=VG6.parse(Y),W=Z.threshold??$.mergeSimilarityThreshold,K=new Fz(Q.entityService,w),U=[];for(let D of Z.existingTopics){let z=await K.createTopic(D);if(z)U.push(z)}let G=await K.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:W,additionalCandidates:U});return{found:G!==null,candidateTitle:G?.title,candidateScore:G?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await AE(Q);let Z=FG6.parse(Y),W=new Fz(Q.entityService,w);for(let D of Z.existingTopics)await W.createTopic({title:D.title,content:D.content});await kG6(Q);let K=sd({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await eh([K],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??$.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:r$});return{...U,topicCount:G.length,topics:G.map(WUA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await AE(Q);let Z=LG6.parse(Y),W=new Fz(Q.entityService,w);for(let D of Z.existingTopics??[])await W.createTopic(D);let K=Z.entities.map((D,z)=>sd(D,`-rebuild-${z}`)),U=await qUA(K,Q,w,$),G=await Q.entityService.listEntities({entityType:r$});return{...U,topicCount:G.length,topics:G.map(WUA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await AE(Q);let Z=IG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=new Fz(Q.entityService,w),U=[];for(let[D,z]of Z.entities.entries()){let V=sd(z,`-sequential-${D}`),I=await B.extractFromEntity(V,W);for(let F of I)await K.createTopic({title:F.title,content:F.content});U.push({extractedTitles:I.map((F)=>F.title)})}let G=await Q.entityService.listEntities({entityType:r$});return{totalTopics:G.length,perEntity:U,topics:G.map(od)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await AE(Q);let W=NG6.parse(Y).entities.map((G,D)=>sd(G,`-batch-${D}`)),K=await eh(W,Q,w,{minRelevanceScore:$.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:r$});return{...K,topics:U.map(od)}})}var PG6=new Vz;async function oR2({entity:A,config:Q}){let w=rd.parse(A),$=PG6.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:$.title,body:$.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 zUA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:I$["ai.rizom.brain.topic"],validate:!1,buildRecord:oR2}}var sR2={name:"@brains/topics",version:"0.2.0-alpha.180",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 jG6=new Vz,OG6=H.looseObject({status:H.unknown().optional()});class aR2 extends jw{entityType=r$;schema=rd;adapter=jG6;unregisterAtprotoProjection;sourceBatch=new DUA;constructor(A={}){super(th,sR2,A,IR2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:PR2,"merge-synthesis":MR2,"topic-list":jR2,"topic-detail":OR2}}getDataSources(){return[new KUA(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:YUA,targetType:r$,job:{type:NR2,handler:cR2({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 BR(A,r$,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:pR2()},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(!tk(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:u_0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:bR2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:th}})}}]}async onRegister(A){A.insights.register("topic-distribution",RR2()),vR2({context:A,pluginId:this.id}),rR2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=fB.getInstance().register(zUA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(YUA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===r$)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=OG6.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 lR2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await dR2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function r_0(A={}){return new aR2(A)}$A();b0();$A();var JUA=H.enum(["linkedin"]),tR2=H.enum(["linkedin"]),VUA=H.enum(["generating","draft","queued","published","failed"]),eR2=H.enum(["generating","draft","queued","published","failed"]),Av2=H.enum(["post","deck"]),fG6=H.enum(["post","deck"]),Qv2=H.object({id:H.string().min(1).describe("Document entity ID")}),xG6=H.object({id:H.string().min(1)}),Iz=H.object({title:H.string().describe("Short descriptive title (3-6 words) for file naming"),platform:JUA.describe("Target platform"),status:VUA,coverImageId:H.string().optional().describe("Image entity ID for post image"),documents:H.array(Qv2).optional().describe("Document attachments for publishing"),publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional().describe("ID from platform after publishing"),sourceEntityId:H.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Av2.optional().describe("Source entity type (post, deck)")}),wv2=Iz.extend({platform:JUA.optional(),status:VUA.optional()}),RG6=Iz.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:H.string().describe("URL-friendly identifier: {platform}-{title}"),error:H.string().optional()}),vG6=H.object({title:H.string(),platform:tR2,status:eR2,publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional(),slug:H.string(),error:H.string().optional()}),CG6=H.object({title:H.string(),platform:tR2,status:eR2,coverImageId:H.string().optional(),documents:H.array(xG6).optional(),publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional(),sourceEntityId:H.string().optional(),sourceEntityType:fG6.optional()}),wO=aQ.extend({entityType:H.literal("social-post"),metadata:vG6}),o_0=wO.extend({frontmatter:CG6,body:H.string()}),hG6=o_0.extend({url:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});$A();R2();class FUA extends QQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:wO,frontmatterSchema:Iz,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,Iz),Q=this.extractBody(A.content)}catch{Q=A.content}let $={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,wv2),w=Q.platform??"linkedin",$=Q.status??"draft",B=`${w}-${F1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:w,status:$,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,Iz)}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-${F1(A.title)}`,platform:"linkedin",status:"generating"}}}}var YY=new FUA;$A();$A();b0();var EG6=H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional(),baseUrl:H.string().optional(),platform:H.enum(["linkedin"]).optional(),status:H.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:H.boolean().optional(),nextInQueue:H.boolean().optional()}),gG6=H.looseObject({entityType:H.string().optional(),query:EG6.optional()});function $v2(A){let Q=DQ(A.content,Iz);return o_0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class s_0 extends H7{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=gG6.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return $v2(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:$}=this.parseQuery(A),B=w.entityService;if($.nextInQueue)return this.fetchNextInQueue(Q,B);if($.id){let{item:U}=await this.fetchDetail($.id,B);return Q.parse(this.buildDetailResult(U,null))}let X={};if($.platform)X.platform=$.platform;if($.status)X.status=$.status;let Y=Object.keys(X).length>0,Z=$.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:W,pagination:K}=await this.fetchList($,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(W,K,$))}async fetchNextInQueue(A,Q){let $=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],B=$?$v2($):null;return A.parse({post:B})}}b0();var Bv2=H.object({accessToken:H.string().optional(),refreshToken:H.string().optional(),organizationId:H.string().optional(),apiVersion:H.string().regex(/^\d{6}$/).optional()}),IUA=H.object({linkedin:Bv2.optional(),publishInterval:H.number().default(3600000),enabled:H.boolean().default(!0),defaultPrompt:H.string().default("Create an engaging social media post that drives engagement"),maxRetries:H.number().default(3),autoGenerateOnBlogPublish:H.boolean().default(!1)});$A();R2();b0();g$();NUA();import{jsxDEV as h9,Fragment as SG6}from"preact/jsx-dev-runtime";function yG6(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function TG6(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var t_0=({posts:A,pageTitle:Q,pagination:w,baseUrl:$="/social-posts"})=>{let B=Q??"Social Posts",X=w?.totalItems??A.length,Y=`Browse all ${X} social ${X===1?"post":"posts"}`;return h9(SG6,{children:[h9(Nw,{title:B,description:Y},void 0,!1,void 0,this),h9("div",{className:"social-post-list bg-theme",children:h9("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[h9("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?h9("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):h9("ul",{className:"space-y-6",children:A.map((Z)=>h9("li",{children:h9(W$,{href:Z.url,variant:"horizontal",children:h9("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&h9("img",{src:Z.coverImageUrl,alt:Z.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),h9("div",{className:"flex-1 min-w-0",children:[h9("div",{className:"flex items-start justify-between gap-4 mb-2",children:[h9("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),h9("time",{className:"text-sm text-theme-muted shrink-0",children:TG6(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h9("div",{className:"flex items-center gap-2 mb-3",children:[h9(SW,{status:Z.frontmatter.status},void 0,!1,void 0,this),h9("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),h9("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h9("p",{className:"text-theme leading-relaxed",children:yG6(Z.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},Z.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&h9(F_,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as E9,Fragment as mG6}from"preact/jsx-dev-runtime";function Xv2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var e_0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),$=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return E9(mG6,{children:[E9(Nw,{title:Q,description:w},void 0,!1,void 0,this),E9("section",{className:"social-post-detail",children:E9("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:E9("div",{className:"max-w-3xl mx-auto",children:[E9(QF,{items:$},void 0,!1,void 0,this),E9("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),E9("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[E9(SW,{status:A.frontmatter.status},void 0,!1,void 0,this),E9("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),E9("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&&E9(J_,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),E9(W$,{className:"p-8 mb-8",children:E9("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),E9("div",{className:"space-y-4 text-sm text-theme-muted",children:[E9("div",{children:[E9("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Xv2(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&E9("div",{children:[E9("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Xv2(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&E9("div",{children:E9("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 u$0(A){return`social-media:${A}`}var uG6=H.union([H.boolean(),H.object({generate:H.boolean().optional(),prompt:H.string().optional()})]),_UA=H.object({prompt:H.string().optional(),platform:H.enum(["linkedin"]).optional(),sourceEntityType:H.enum(["post","deck"]).optional(),sourceEntityId:H.string().optional(),title:H.string().optional().describe("Required when content is provided directly"),content:H.string().optional(),addToQueue:H.boolean().optional(),generateImage:H.boolean().optional().describe("Auto-generate cover image for post"),coverImage:uG6.optional().describe("Generic cover image generation request")}),cG6=JK.extend({slug:H.string().optional()});class QE extends pY{constructor(A,Q){super(A,Q,{schema:_UA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",$=A.addToQueue??!1,{prompt:B,sourceEntityType:X,sourceEntityId:Y}=A,{content:Z,title:W}=A;if(Z&&W)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!W){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let F=await this.context.ai.generate({prompt:Z,templateName:u$0(w)});W=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let k=H.looseObject({slug:H.string()}).safeParse(F.metadata),b=k.success?k.data.slug:Y,f=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${X}:
|
|
7997
|
+
`)}async function eh(A,Q,w,$={}){if(A.length===0)return{created:0,merged:0,skipped:0,batches:0};let B=$.minRelevanceScore??0,X=$.autoMerge??!1,Y=$.mergeSimilarityThreshold??0.85,Z=$.targetVisibility??"public",W=gR2(A),K=new Fz(Q.entityService,w),U=$.topicMergeSynthesizer??new GUA(Q,w),G=await i_0(Q.entityService,void 0,Z),D=new Map,z=0,V=0,I=0;for(let _ of W){w.info(`Processing batch of ${_.length} entities`);let k=UG6(_),b=n_0({entityTitle:`Batch of ${_.length} entities`,entityType:"batch",content:k,existingTopicTitles:G});try{let R=(await Q.ai.generate({prompt:b,templateName:"topics:extraction"})).topics.filter((v)=>v.relevanceScore>=B);for(let v of R)try{if(X){let S=await K.findMergeCandidate({incoming:v,threshold:Y,additionalCandidates:Array.from(D.values()),targetVisibility:Z});if(S){let l=await U.synthesize({existingTopic:S.topic,incomingTopic:v}),o=await K.applySynthesizedMerge({existingId:S.topic.id,synthesized:{...l,title:S.title},visibility:Z});if(!o)throw Error(`Failed to merge topic: ${v.title}`);D.set(o.id,o),V++;continue}}let M=K.getTopicIdForTitle(v.title,Z);if(D.has(M)){I++;continue}let y=await K.createTopicOptimistic({title:v.title,content:v.content,visibility:Z});if(y.topic)D.set(y.topic.id,y.topic);if(y.created)z++;else I++}catch(M){w.error("Topic batch item failed",{title:v.title,error:lA(M)})}}catch(f){w.error("Batch topic extraction failed",{batchSize:_.length,promptChars:b.length,error:lA(f)})}}let F={created:z,merged:V,skipped:I,batches:W.length};if(z>0||V>0)await Q.messaging.send({type:_R2,payload:F,broadcast:!0});return F}$A();b0();var GG6=H.discriminatedUnion("mode",[H.object({mode:H.literal("derive"),reason:H.string().optional()}),H.object({mode:H.literal("rebuild"),reason:H.string().optional()}),H.object({mode:H.literal("source-batch"),minRelevanceScore:H.number().min(0).max(1).optional()})]);class DUA{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 cR2(A){let{context:Q,logger:w,config:$}=A;return{process:async(B)=>{if(B.mode==="derive")return await A.extractAllTopics(),{success:!0};if(B.mode==="rebuild")return await A.rebuildAllTopics(),{success:!0};return DG6({context:Q,logger:w,config:$,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??$.minRelevanceScore})},validateAndParse:(B)=>{let X=GG6.safeParse(B??{});return X.success?X.data:null}}}async function DG6(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(K)=>({ref:K,entity:await A.context.entityService.getEntity({entityType:K.entityType,id:K.entityId})}))),$=0,B=0,X=0,Y=0,Z=[];for(let{ref:K,entity:U}of w){if(!U){B++;continue}if(U.contentHash!==K.contentHash){$++;continue}if(!A.isEntityPublished(U)){X++;continue}if(!tk(U.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(U)}if(Z.length===0)return{success:!0,sources:Q.length,created:0,merged:0,skipped:0,batches:0,stale:$,missing:B,unpublished:X,hidden:Y};let W=await eh(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...W,stale:$,missing:B,unpublished:X,hidden:Y}}function pR2(){return{priority:5,source:u_0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:th}}}async function lR2(A){let Q=await iR2(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 eh(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 dR2(A){let Q=await iR2(A),w=await qUA(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function qUA(A,Q,w,$){let B=new Fz(Q.entityService,w),X=await B.listTopics({visibility:$.extractionVisibility});for(let Z of X)await B.deleteTopic(Z.id);if(A.length===0)return{deleted:X.length,created:0,merged:0,skipped:0,batches:0};let Y=await eh(A,Q,w,{minRelevanceScore:$.minRelevanceScore,autoMerge:$.autoMerge,mergeSimilarityThreshold:$.mergeSimilarityThreshold,targetVisibility:$.extractionVisibility});return{deleted:X.length,...Y}}async function iR2(A){let Q=qG6(A),w=[];for(let $ of Q){let B=await A.context.entityService.listEntities({entityType:$,options:{filter:{visibilityScope:A.config.extractionVisibility}}});for(let X of B){if(!A.isEntityPublished(X))continue;w.push(X)}}return w}function qG6(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var ad=H.object({entityType:H.string(),content:H.string(),metadata:H.record(H.string(),H.unknown()).optional()}),zG6=ad.extend({minRelevanceScore:H.number().optional()}),JG6=H.object({contentA:ad,contentB:ad,minRelevanceScore:H.number().optional(),threshold:H.number().min(0).max(1).optional()}),m$0=H.object({title:H.string(),content:H.string()}),VG6=H.object({existingTopics:H.array(m$0),incomingTopic:m$0,threshold:H.number().optional()}),FG6=H.object({existingTopics:H.array(m$0).default([]),incomingTopic:m$0.extend({relevanceScore:H.number().min(0).max(1).optional()}),threshold:H.number().optional()}),IG6=H.object({entities:H.array(ad).min(1),minRelevanceScore:H.number().optional()}),LG6=H.object({existingTopics:H.array(m$0).optional(),entities:H.array(ad)}),NG6=H.object({entities:H.array(ad)});function sd(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:mw(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function nR2(A){return{title:A.title,relevanceScore:A.relevanceScore}}function _G6(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function bG6(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:_G6(Q)}]}}async function AE(A){let Q=await A.entityService.listEntities({entityType:r$});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:r$,id:w.id})))}async function kG6(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function rR2(A){let{context:Q,logger:w,config:$}=A,B=new UUA(Q,w),X=async(Y,Z,W="")=>{let K=sd(Y,W);return B.extractFromEntity(K,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await AE(Q);let Z=zG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=sd(Z);return(await B.extractFromEntity(K,W)).map((G)=>bG6(G,K))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await AE(Q);let Z=JG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=Z.threshold??$.mergeSimilarityThreshold,[U,G]=await Promise.all([X(Z.contentA,W,"-a"),X(Z.contentB,W,"-b")]),D=new Fz(Q.entityService,w),z=[];for(let F of U){let _=await D.createTopic(F);if(_)z.push(_)}let V=(await Promise.all(G.map(async(F)=>{let _=await D.findMergeCandidate({incoming:F,threshold:K,additionalCandidates:z});if(!_)return null;return{incomingTitle:F.title,candidateTitle:_.title,candidateScore:_.score}}))).filter((F)=>F!==null),I=V.map((F)=>F.candidateTitle);return{topicsA:U.map(nR2),topicsB:G.map(nR2),matchingTitles:I,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await AE(Q);let Z=VG6.parse(Y),W=Z.threshold??$.mergeSimilarityThreshold,K=new Fz(Q.entityService,w),U=[];for(let D of Z.existingTopics){let z=await K.createTopic(D);if(z)U.push(z)}let G=await K.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:W,additionalCandidates:U});return{found:G!==null,candidateTitle:G?.title,candidateScore:G?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await AE(Q);let Z=FG6.parse(Y),W=new Fz(Q.entityService,w);for(let D of Z.existingTopics)await W.createTopic({title:D.title,content:D.content});await kG6(Q);let K=sd({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),U=await eh([K],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??$.mergeSimilarityThreshold}),G=await Q.entityService.listEntities({entityType:r$});return{...U,topicCount:G.length,topics:G.map(WUA)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await AE(Q);let Z=LG6.parse(Y),W=new Fz(Q.entityService,w);for(let D of Z.existingTopics??[])await W.createTopic(D);let K=Z.entities.map((D,z)=>sd(D,`-rebuild-${z}`)),U=await qUA(K,Q,w,$),G=await Q.entityService.listEntities({entityType:r$});return{...U,topicCount:G.length,topics:G.map(WUA)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await AE(Q);let Z=IG6.parse(Y),W=Z.minRelevanceScore??$.minRelevanceScore,K=new Fz(Q.entityService,w),U=[];for(let[D,z]of Z.entities.entries()){let V=sd(z,`-sequential-${D}`),I=await B.extractFromEntity(V,W);for(let F of I)await K.createTopic({title:F.title,content:F.content});U.push({extractedTitles:I.map((F)=>F.title)})}let G=await Q.entityService.listEntities({entityType:r$});return{totalTopics:G.length,perEntity:U,topics:G.map(od)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await AE(Q);let W=NG6.parse(Y).entities.map((G,D)=>sd(G,`-batch-${D}`)),K=await eh(W,Q,w,{minRelevanceScore:$.minRelevanceScore}),U=await Q.entityService.listEntities({entityType:r$});return{...K,topics:U.map(od)}})}var PG6=new Vz;async function oR2({entity:A,config:Q}){let w=rd.parse(A),$=PG6.parseTopicBody(w.content);return{$type:"ai.rizom.brain.topic",title:$.title,body:$.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 zUA(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:I$["ai.rizom.brain.topic"],validate:!1,buildRecord:oR2}}var sR2={name:"@brains/topics",version:"0.2.0-alpha.181",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 jG6=new Vz,OG6=H.looseObject({status:H.unknown().optional()});class aR2 extends jw{entityType=r$;schema=rd;adapter=jG6;unregisterAtprotoProjection;sourceBatch=new DUA;constructor(A={}){super(th,sR2,A,IR2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:PR2,"merge-synthesis":MR2,"topic-list":jR2,"topic-detail":OR2}}getDataSources(){return[new KUA(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:YUA,targetType:r$,job:{type:NR2,handler:cR2({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 BR(A,r$,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:pR2()},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(!tk(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:u_0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:bR2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:th}})}}]}async onRegister(A){A.insights.register("topic-distribution",RR2()),vR2({context:A,pluginId:this.id}),rR2({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=fB.getInstance().register(zUA())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(YUA)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===r$)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=OG6.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 lR2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await dR2({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function r_0(A={}){return new aR2(A)}$A();b0();$A();var JUA=H.enum(["linkedin"]),tR2=H.enum(["linkedin"]),VUA=H.enum(["generating","draft","queued","published","failed"]),eR2=H.enum(["generating","draft","queued","published","failed"]),Av2=H.enum(["post","deck"]),fG6=H.enum(["post","deck"]),Qv2=H.object({id:H.string().min(1).describe("Document entity ID")}),xG6=H.object({id:H.string().min(1)}),Iz=H.object({title:H.string().describe("Short descriptive title (3-6 words) for file naming"),platform:JUA.describe("Target platform"),status:VUA,coverImageId:H.string().optional().describe("Image entity ID for post image"),documents:H.array(Qv2).optional().describe("Document attachments for publishing"),publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional().describe("ID from platform after publishing"),sourceEntityId:H.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:Av2.optional().describe("Source entity type (post, deck)")}),wv2=Iz.extend({platform:JUA.optional(),status:VUA.optional()}),RG6=Iz.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:H.string().describe("URL-friendly identifier: {platform}-{title}"),error:H.string().optional()}),vG6=H.object({title:H.string(),platform:tR2,status:eR2,publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional(),slug:H.string(),error:H.string().optional()}),CG6=H.object({title:H.string(),platform:tR2,status:eR2,coverImageId:H.string().optional(),documents:H.array(xG6).optional(),publishedAt:H.string().datetime().optional(),platformPostId:H.string().optional(),sourceEntityId:H.string().optional(),sourceEntityType:fG6.optional()}),wO=aQ.extend({entityType:H.literal("social-post"),metadata:vG6}),o_0=wO.extend({frontmatter:CG6,body:H.string()}),hG6=o_0.extend({url:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});$A();R2();class FUA extends QQ{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:wO,frontmatterSchema:Iz,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,Iz),Q=this.extractBody(A.content)}catch{Q=A.content}let $={...w,title:A.metadata.title,platform:A.metadata.platform,status:A.metadata.status,...A.metadata.publishedAt!==void 0&&{publishedAt:A.metadata.publishedAt},...A.metadata.platformPostId!==void 0&&{platformPostId:A.metadata.platformPostId}};return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,wv2),w=Q.platform??"linkedin",$=Q.status??"draft",B=`${w}-${F1(Q.title)}`;return{content:A,entityType:"social-post",metadata:{title:Q.title,slug:B,platform:w,status:$,publishedAt:Q.publishedAt,platformPostId:Q.platformPostId}}}parsePostFrontmatter(A){return this.parseFrontMatter(A.content,Iz)}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-${F1(A.title)}`,platform:"linkedin",status:"generating"}}}}var YY=new FUA;$A();$A();b0();var EG6=H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional(),baseUrl:H.string().optional(),platform:H.enum(["linkedin"]).optional(),status:H.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:H.boolean().optional(),nextInQueue:H.boolean().optional()}),gG6=H.looseObject({entityType:H.string().optional(),query:EG6.optional()});function $v2(A){let Q=DQ(A.content,Iz);return o_0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class s_0 extends H7{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=gG6.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return $v2(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:$}=this.parseQuery(A),B=w.entityService;if($.nextInQueue)return this.fetchNextInQueue(Q,B);if($.id){let{item:U}=await this.fetchDetail($.id,B);return Q.parse(this.buildDetailResult(U,null))}let X={};if($.platform)X.platform=$.platform;if($.status)X.status=$.status;let Y=Object.keys(X).length>0,Z=$.sortByQueue?[{field:"queueOrder",direction:"asc"}]:this.config.defaultSort,{items:W,pagination:K}=await this.fetchList($,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(W,K,$))}async fetchNextInQueue(A,Q){let $=(await Q.listEntities({entityType:this.config.entityType,options:{filter:{metadata:{status:"queued"}},sortFields:[{field:"queueOrder",direction:"asc"}],limit:1}}))[0],B=$?$v2($):null;return A.parse({post:B})}}b0();var Bv2=H.object({accessToken:H.string().optional(),refreshToken:H.string().optional(),organizationId:H.string().optional(),apiVersion:H.string().regex(/^\d{6}$/).optional()}),IUA=H.object({linkedin:Bv2.optional(),publishInterval:H.number().default(3600000),enabled:H.boolean().default(!0),defaultPrompt:H.string().default("Create an engaging social media post that drives engagement"),maxRetries:H.number().default(3),autoGenerateOnBlogPublish:H.boolean().default(!1)});$A();R2();b0();g$();NUA();import{jsxDEV as h9,Fragment as SG6}from"preact/jsx-dev-runtime";function yG6(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function TG6(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var t_0=({posts:A,pageTitle:Q,pagination:w,baseUrl:$="/social-posts"})=>{let B=Q??"Social Posts",X=w?.totalItems??A.length,Y=`Browse all ${X} social ${X===1?"post":"posts"}`;return h9(SG6,{children:[h9(Nw,{title:B,description:Y},void 0,!1,void 0,this),h9("div",{className:"social-post-list bg-theme",children:h9("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[h9("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?h9("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):h9("ul",{className:"space-y-6",children:A.map((Z)=>h9("li",{children:h9(W$,{href:Z.url,variant:"horizontal",children:h9("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&h9("img",{src:Z.coverImageUrl,alt:Z.frontmatter.title,className:"w-full sm:w-24 h-48 sm:h-24 object-cover rounded-lg shrink-0"},void 0,!1,void 0,this),h9("div",{className:"flex-1 min-w-0",children:[h9("div",{className:"flex items-start justify-between gap-4 mb-2",children:[h9("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),h9("time",{className:"text-sm text-theme-muted shrink-0",children:TG6(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h9("div",{className:"flex items-center gap-2 mb-3",children:[h9(SW,{status:Z.frontmatter.status},void 0,!1,void 0,this),h9("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),h9("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),h9("p",{className:"text-theme leading-relaxed",children:yG6(Z.body,200)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},Z.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&h9(F_,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as E9,Fragment as mG6}from"preact/jsx-dev-runtime";function Xv2(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var e_0=({post:A})=>{let Q=`Social Post - ${A.frontmatter.platform}`,w=A.body.slice(0,160),$=[{label:"Home",href:"/"},{label:A.listLabel??"Social Posts",href:A.listUrl??"/social-posts"},{label:A.frontmatter.platform}];return E9(mG6,{children:[E9(Nw,{title:Q,description:w},void 0,!1,void 0,this),E9("section",{className:"social-post-detail",children:E9("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:E9("div",{className:"max-w-3xl mx-auto",children:[E9(QF,{items:$},void 0,!1,void 0,this),E9("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),E9("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[E9(SW,{status:A.frontmatter.status},void 0,!1,void 0,this),E9("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),E9("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&&E9(J_,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),E9(W$,{className:"p-8 mb-8",children:E9("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),E9("div",{className:"space-y-4 text-sm text-theme-muted",children:[E9("div",{children:[E9("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",Xv2(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&E9("div",{children:[E9("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",Xv2(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&E9("div",{children:E9("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 u$0(A){return`social-media:${A}`}var uG6=H.union([H.boolean(),H.object({generate:H.boolean().optional(),prompt:H.string().optional()})]),_UA=H.object({prompt:H.string().optional(),platform:H.enum(["linkedin"]).optional(),sourceEntityType:H.enum(["post","deck"]).optional(),sourceEntityId:H.string().optional(),title:H.string().optional().describe("Required when content is provided directly"),content:H.string().optional(),addToQueue:H.boolean().optional(),generateImage:H.boolean().optional().describe("Auto-generate cover image for post"),coverImage:uG6.optional().describe("Generic cover image generation request")}),cG6=JK.extend({slug:H.string().optional()});class QE extends pY{constructor(A,Q){super(A,Q,{schema:_UA,jobTypeName:"social-post-generation",entityType:"social-post"})}async generate(A,Q){let w=A.platform??"linkedin",$=A.addToQueue??!1,{prompt:B,sourceEntityType:X,sourceEntityId:Y}=A,{content:Z,title:W}=A;if(Z&&W)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!W){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let F=await this.context.ai.generate({prompt:Z,templateName:u$0(w)});W=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let k=H.looseObject({slug:H.string()}).safeParse(F.metadata),b=k.success?k.data.slug:Y,f=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${X}:
|
|
7998
7998
|
|
|
7999
7999
|
Source: ${X}/${b}
|
|
8000
8000
|
|
|
8001
8001
|
${F.content}`,templateName:u$0(w)});W=f.title,Z=f.content,await this.reportProgress(Q,{progress:50,message:"Social post generated from source"})}else if(B){await this.reportProgress(Q,{progress:10,message:"Generating social post with AI"});let F=await this.context.ai.generate({prompt:B,templateName:u$0(w)});W=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!Z||!W)this.failEarly("Content or title was not generated");let U={title:W,platform:w,status:$?"queued":"draft",...Y&&{sourceEntityId:Y},...X&&{sourceEntityType:X}},G=YY.createPostContent(U,Z),z=YY.fromMarkdown(G).metadata;if(!z)this.failEarly("Failed to parse social post metadata");let V=await $q({entityType:"social-post",title:W,deriveId:(F)=>`${w}-${F1(F)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),I=G;if(V!==W){z.title=V,z.slug=`${w}-${F1(V)}`;let F={...U,title:V};I=YY.createPostContent(F,Z)}return{id:z.slug,content:I,metadata:z,title:V,resultExtras:{slug:z.slug},createOptions:{deduplicateId:!0}}}async onGenerationFailure(A,Q){await this.context.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:Q}})}async afterCreate(A,Q,w,$){if(A.generateImage){await this.reportProgress(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: ${B}`,title:`${B} Image`,aspectRatio:"16:9",targetEntityType:"social-post",targetEntityId:Q},toolContext:{interfaceType:"job",userId:"system"}})}await this.context.messaging.send({type:"generate:report:success",payload:{entityType:"social-post",entityId:Q}})}summarizeDataForLog(A){return{platform:A.platform??"linkedin",hasPrompt:!!A.prompt,sourceEntityType:A.sourceEntityType,addToQueue:A.addToQueue??!1,generateImage:A.generateImage??!1,coverImage:!!A.coverImage}}}b0();var Yv2=200,Zv2="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function c$0(A){if(A.length<=Yv2)return A;return`${A.slice(0,Yv2)}\u2026 (truncated, ${A.length} bytes)`}var pG6=H.looseObject({sub:H.string()}),lG6=H.looseObject({id:H.string()}),dG6=H.looseObject({value:H.looseObject({asset:H.string(),uploadMechanism:H.looseObject({[Zv2]:H.looseObject({uploadUrl:H.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[Zv2].uploadUrl,assetUrn:A.value.asset})),iG6=H.looseObject({value:H.looseObject({uploadUrl:H.url(),document:H.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function nG6(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function rG6(A){let Q=dG6.safeParse(A);return Q.success?Q.data:null}function oG6(A){let Q=iG6.safeParse(A);return Q.success?Q.data:null}var sG6="202604";class bUA{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,$){if(!this.config.accessToken)throw Error("LinkedIn access token not configured");let B=await this.getAuthor(),X=$?.[0];if($&&$.length>1)this.logger.warn("LinkedIn document publishing supports one PDF",{count:$.length});let Y=null;if(X){let G=await this.uploadDocument(B,X);return this.publishDocumentPost(B,A,G,X.filename)}else if(w){let G=await this.uploadImage(B,w);if(G)Y={category:"IMAGE",urn:G}}let Z={shareCommentary:{text:A},shareMediaCategory:Y?.category??"NONE",...Y&&{media:[nG6(Y)]}},W=await this.fetch(`${this.apiBaseUrl}/ugcPosts`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({author:B,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":Z},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!W.ok){let G=c$0(await W.text());throw this.logger.error("LinkedIn API error",{status:W.status,error:G}),Error(`LinkedIn API error: ${W.status} - ${G}`)}let K=W.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:K,mediaCategory:Y?.category??"NONE"});let U={id:K};if(K)U.url=`https://www.linkedin.com/feed/update/${K}`;return U}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??sG6,"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 Z=c$0(await w.text());return this.logger.warn("LinkedIn image upload registration failed",{status:w.status,error:Z}),null}let $=rG6(await w.json());if(!$)return this.logger.warn("LinkedIn image upload registration was malformed"),null;let{uploadUrl:B,assetUrn:X}=$,Y=await this.fetch(B,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!Y.ok)return this.logger.warn("LinkedIn image binary upload failed",{status:Y.status}),null;return this.logger.info("LinkedIn image uploaded",{assetUrn:X}),X}catch(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 X=c$0(await w.text());throw Error(`LinkedIn document upload initialization failed: ${w.status} - ${X}`)}let $=oG6(await w.json());if(!$)throw Error("LinkedIn document upload initialization was malformed");let B=await this.fetch($.uploadUrl,{method:"PUT",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":Q.mimeType},body:new Uint8Array(Q.data)});if(!B.ok)throw Error(`LinkedIn document binary upload failed: ${B.status}`);return this.logger.info("LinkedIn document uploaded",{documentUrn:$.documentUrn,filename:Q.filename}),$.documentUrn}async publishDocumentPost(A,Q,w,$){let B=await this.fetch(`${this.restApiBaseUrl}/posts`,{method:"POST",headers:this.getRestHeaders(),body:JSON.stringify({author:A,commentary:Q,visibility:"PUBLIC",distribution:{feedDistribution:"MAIN_FEED",targetEntities:[],thirdPartyDistributionChannels:[]},content:{media:{id:w,title:$}},lifecycleState:"PUBLISHED",isReshareDisabledByAuthor:!1})});if(!B.ok){let Z=c$0(await B.text());throw this.logger.error("LinkedIn document post API error",{status:B.status,error:Z}),Error(`LinkedIn document post API error: ${B.status} - ${Z}`)}let X=B.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn document post created",{postId:X,documentUrn:w});let Y={id:X};if(X)Y.url=`https://www.linkedin.com/feed/update/${X}`;return Y}async validateCredentials(){if(!this.config.accessToken)return!1;try{if(this.config.organizationId)return(await this.fetch(`${this.apiBaseUrl}/organizations/${this.config.organizationId}`,{headers:{Authorization:`Bearer ${this.config.accessToken}`}})).ok;return await this.getUserId(),!0}catch{return!1}}async getAuthor(){if(this.config.organizationId)return`urn:li:organization:${this.config.organizationId}`;return this.getUserId()}async getUserId(){if(this.cachedUserId)return this.cachedUserId;if(!this.config.accessToken)throw Error("LinkedIn access token not configured");try{let w=await this.fetch("https://api.linkedin.com/v2/userinfo",{headers:{Authorization:`Bearer ${this.config.accessToken}`}});if(w.ok){let $=pG6.safeParse(await w.json());if($.success)return this.cachedUserId=`urn:li:person:${$.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=c$0(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${w}`)}let Q=lG6.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function kUA(A,Q,w={}){return new bUA(A,Q,w)}b0();y8();NUA();var aG6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),tG6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Hv2=H.enum(["linkedin"]),Wv2=H.enum(["generating","draft","queued","published","failed"]),eG6=H.enum(["post","deck"]),A36=H.object({id:H.string().min(1)}),Q36=H.object({title:H.string(),platform:Hv2,status:Wv2,coverImageId:H.string().optional(),documents:H.array(A36).optional(),publishedAt:H.string().optional(),platformPostId:H.string().optional(),sourceEntityId:H.string().optional(),sourceEntityType:eG6.optional()}),w36=H.object({title:H.string(),platform:Hv2,status:Wv2,publishedAt:H.string().optional(),platformPostId:H.string().optional(),slug:H.string(),error:H.string().optional()}),Kv2=H.object({id:H.string(),entityType:H.literal("social-post"),content:H.string(),created:H.string(),updated:H.string(),visibility:tG6,metadata:w36,contentHash:H.string(),frontmatter:Q36,body:H.string(),url:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),typeLabel:H.string().optional(),coverImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()}),$36=H.object({posts:H.array(Kv2),totalCount:H.number().optional(),pagination:aG6.nullable(),baseUrl:H.string().optional()}),B36=H.object({post:Kv2});function Uv2(){return{linkedin:a_0,"social-post-list":$2({name:"social-post-list",description:"Social post list page template",schema:$36,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:t_0}}),"social-post-detail":$2({name:"social-post-detail",description:"Individual social post template",schema:B36,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:e_0}})}}b0();var X36=H.object({prompt:H.string().optional(),content:H.string().optional(),platform:H.enum(["linkedin"]).default("linkedin")}),Y36=H.object({prompt:H.string().optional(),content:H.string().optional(),title:H.string().optional(),platform:H.enum(["linkedin"]).optional()});function Gv2(A){A.eval.registerHandler("generation",async(Q)=>{let w=X36.parse(Q),$=w.content?`Create an engaging LinkedIn post to share this content:
|
|
8002
8002
|
|
|
8003
|
-
${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:$,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=Y36.parse(Q),$=[],B=hZ.from(async(K)=>{let U={progress:K.progress};if(K.message!==void 0)U.message=K.message;$.push(U)});if(!B)throw Error("Failed to create progress reporter");let Y=await new QE(A.logger,A).process(w,`eval-${Date.now()}`,B),Z=!1,W;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!K,W=K?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:W,progressSteps:$}})}$A();class p$0{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 $=await this.entityService.getEntity({entityType:"social-post",id:w});if(!$){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let B=$;if(B.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let X=B.metadata.platform,Y=this.providers.get(X);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${X}`);return}let Z=DQ(B.content,Iz),W;if(Z.metadata.coverImageId)W=await this.fetchImageData(Z.metadata.coverImageId);let K=Z.metadata.documents??[],U=await this.fetchDocumentData(K);try{if(K.length>0&&U.length===0)throw Error(`Refusing to publish: ${K.length} document(s) referenced but none could be fetched`);let G=K.length===0?await this.resolveSourceAttachment(Z.metadata):[],D=U.length>0?U:G,z=D.length?await Y.publish(Z.content,B.metadata,W,D):await Y.publish(Z.content,B.metadata,W),V=new Date().toISOString(),I=z.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...I&&{platformPostId:I}},_=YY.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:I}}}),await this.reportSuccess(Q,w,z.id),this.logger.info(`Post published successfully: ${w}`,{platform:X,platformPostId:I})}catch(G){let D=G instanceof Error?G.message:String(G),z={...Z.metadata,status:"failed"},V=YY.createPostContent(z,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,w,D),this.logger.error(`Post publish failed: ${w}`,{platform:X,error:D})}}catch($){let B=lA($);this.logger.error("Unexpected error in publish handler",{entityId:w,error:B}),await this.reportFailure(Q,w,B)}}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 $=await this.fetchSingleDocumentData(w.id);if($)Q.push($)}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 $=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:$}}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 $=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!$?.[1]||!$[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let B=$[1],X=$[2];return{data:Buffer.from(X,"base64"),mimeType:B}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function Dv2(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 $=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:$,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function qv2(A,Q,w){let $=new p$0({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(B)=>{return await $.handle(B.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function zv2(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:$,entityId:B,entity:X}=w.payload;if($!=="post")return{success:!0};if(X.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:B}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${B}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:$,sourceEntityId:B,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${B}`),{success:!0}}catch(Z){let W=lA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:W}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Jv2(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:$,sourceEntityId:B,platform:X}=w.payload;try{let Y=await A.jobs.enqueue({type:`${YY.entityType}:generation`,data:{sourceEntityType:$,sourceEntityId:B,platform:X,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 Z=lA(Y);return Q.error(`Failed to enqueue social post generation for ${B}:`,{error:Z}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Vv2(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:$}=w.payload;if($!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let B=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if(B.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let X=null;for(let Z of B)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Z.id}},limit:1}})).length===0){X=Z;break}if(!X)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${YY.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:X.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:X.id}),{success:!0}}catch(B){let X=lA(B);return Q.error("Failed to handle generate:execute:",{error:X}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:X}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function Fv2({entity:A,config:Q}){let w=wO.parse(A),$=YY.parsePostFrontmatter(w),B=YY.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:$.title,platform:$.platform,body:B,format:"text/markdown",status:$.status,...$.publishedAt&&{publishedAt:$.publishedAt},...$.platformPostId&&{platformPostId:$.platformPostId},...$.sourceEntityType&&{sourceLocalEntityType:$.sourceEntityType},...$.sourceEntityId&&{sourceLocalEntityId:$.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 PUA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:I$["ai.rizom.brain.socialPost"],validate:!1,buildRecord:Fv2}}var Iv2={name:"@brains/social-media",version:"0.2.0-alpha.180",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 MUA extends jw{entityType=YY.entityType;schema=wO;adapter=YY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",Iv2,A,IUA)}createGenerationHandler(A){return new QE(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Uv2()}getDataSources(){return[new s_0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),Dv2(A,this.providers,this.logger),qv2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)zv2(A,this.logger),Jv2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Vv2(A,this.logger),Gv2(A),this.unregisterAtprotoProjection=fB.getInstance().register(PUA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=kUA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function l$0(A={}){return new MUA(A)}b0();var H36=H.enum(["draft","queued","published","failed"]),Lv2=H.object({status:H36.default("draft"),queueOrder:H.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:H.string().datetime().optional()});class jUA{name="internal";async publish(A,Q){return{id:"internal"}}}var y_={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},ZY={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"},$O={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"},Nv2={REGISTER:"publish-assets:register"};b0();var W36=H.enum(["provider"]),_v2=H.object({executionMode:W36.optional(),publishResultIdField:H.string().min(1).optional(),publishTimestampField:H.string().min(1).optional(),enabled:H.boolean().optional()}).strict();var K36=H.object({skipIfDraftExists:H.boolean().optional(),minSourceEntities:H.number().optional(),maxUnpublishedDrafts:H.number().optional(),sourceEntityType:H.string().optional()}),bv2=H.object({entitySchedules:H.record(H.string(),H.string()).optional(),generationSchedules:H.record(H.string(),H.string()).optional(),generationConditions:H.record(H.string(),K36).optional()});class kF{static instance=null;queues=new Map;static getInstance(){return kF.instance??=new kF,kF.instance}static resetInstance(){kF.instance=null}static createFresh(){return new kF}constructor(){}async add(A,Q,w=y_){let $=this.getOrCreateQueue(A),B=$.find((Z)=>Z.entityId===Q);if(B)return{position:B.position};let X=$.length+1,Y={entityId:Q,entityType:A,position:X,queuedAt:new Date().toISOString(),authContext:{...w}};return $.push(Y),{position:X}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let $=w.findIndex((B)=>B.entityId===Q);if($===-1)return;w.splice($,1),this.recalculatePositions(w)}async reorder(A,Q,w){let $=this.queues.get(A);if(!$)return;let B=$.findIndex((Z)=>Z.entityId===Q);if(B===-1)return;let[X]=$.splice(B,1);if(!X)return;let Y=Math.max(0,Math.min(w-1,$.length));$.splice(Y,0,X),this.recalculatePositions($)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let 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}replace(A){this.queues.clear();let Q=[...A].sort((w,$)=>w.entityType.localeCompare($.entityType)||w.position-$.position);for(let w of Q)this.getOrCreateQueue(w.entityType).push({...w,authContext:{...w.authContext}});for(let w of this.queues.values())this.recalculatePositions(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 PF{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new jUA;static getInstance(){return PF.instance??=new PF,PF.instance}static resetInstance(){PF.instance=null}static createFresh(){return new PF}constructor(){}register(A,Q,w){let $=this.providers.get(A);if($&&$.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 kv2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await U36(A,Q)}async function U36(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let $={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:ZY.FAILED,payload:$,sender:"publish-service",broadcast:!0});Q.onFailed?.($);return}OUA(A.entityType,A.entityId,w.result,Q)}catch(w){let $=lA(w);Q.retryTracker.recordFailure(A.entityId,$);let B=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:$,retryCount:B?.retryCount??1,willRetry:!1})}}function OUA(A,Q,w,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send({type:ZY.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});$.onPublish?.({entityType:A,entityId:Q,result:w})}function Pv2(A,Q,w,$){$.retryTracker.recordFailure(Q,w);let B=$.retryTracker.getRetryInfo(Q),X={entityType:A,entityId:Q,error:w,retryCount:B?.retryCount??1,willRetry:!1};if($.messageBus)$.messageBus.send({type:ZY.FAILED,payload:X,sender:"publish-service",broadcast:!0});$.onFailed?.(X)}async function Mv2(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let B=await Q.onCheckGenerationConditions(A,w);if(!B.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:$O.SKIPPED,payload:{entityType:A,reason:B.reason??"Conditions not met"},sender:"content-pipeline"});return}}let $={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:$O.EXECUTE,payload:$,sender:"content-pipeline"});Q.onGenerate?.($)}function jv2(A,Q,w){if(w)w.send({type:$O.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function Ov2(A,Q,w){if(w)w.send({type:$O.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var G36=1000;class fUA{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(G36,()=>this.processUnscheduledTypes())}async stop(){let A=Array.from(this.publishJobs.values());if(this.publishJobs.clear(),this.immediateIntervalJob)A.push(this.immediateIntervalJob),this.immediateIntervalJob=null;await Promise.all(A.map((Q)=>Q.stop()))}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let 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 kv2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class xUA{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)}}async stop(){let A=Array.from(this.generationJobs.values());this.generationJobs.clear(),await Promise.all(A.map((Q)=>Q.stop()))}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await Mv2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}class MF{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return MF.instance??=new MF(A),MF.instance}static async resetInstance(){let A=MF.instance;if(MF.instance=null,A)await A.stop()}static createFresh(A){return new MF(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new fUA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new xUA({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}stop(){if(this.stopPromise)return this.stopPromise;return this.running=!1,this.stopPromise=Promise.all([this.publishRunner.stop(),this.generationRunner.stop()]).then(()=>{return}),this.stopPromise}isRunning(){return this.running}completePublish(A,Q,w){OUA(A,Q,w,this.publishDeps)}failPublish(A,Q,w){Pv2(A,Q,w,this.publishDeps)}completeGeneration(A,Q){jv2(A,Q,this.config.messageBus)}failGeneration(A,Q){Ov2(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($){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${lA($)}`,{cause:$})}}}class jF{static instance=null;retries=new Map;static getInstance(){return jF.instance??=new jF,jF.instance}static resetInstance(){jF.instance=null}static createFresh(){return new jF}constructor(){}recordFailure(A,Q){let $=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:$,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}}}vr0();b0();var fv2=H.union([H.string().min(1),H.object({location:H.enum(["metadata","frontmatter"]),field:H.string().min(1)})]),Ab0=H.object({entityType:H.string().min(1),attachmentType:H.string().min(1),mediaEntityType:H.enum(["image","document"]),targetEntityField:fv2.optional(),requiredWhen:H.object({status:H.string().min(1).optional(),visibility:H.string().min(1).optional()}).optional(),autoGenerate:H.boolean().optional(),requiredForPublish:H.boolean().optional(),jobType:H.string().min(1).optional()});function RUA(A){return`${A.entityType}:${A.attachmentType}`}class OF{static instance=null;definitions=new Map;static getInstance(){return OF.instance??=new OF,OF.instance}static resetInstance(){OF.instance=null}static createFresh(){return new OF}constructor(){}register(A){let Q=Ab0.parse(A),w=RUA(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(RUA({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(RUA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}Q4();R2();class Qb0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter((B)=>B.autoGenerate===!0).filter((B)=>!Q.attachmentType||B.attachmentType===Q.attachmentType),$={checked:w.length,enqueued:0,skipped:0};for(let B of w)if(await this.ensureDefinition(A,B))$.enqueued+=1;else $.skipped+=1;return $}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 $=this.getPredictedMediaId(A,Q),B=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:$,dedupKey:B,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:B}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType: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 vUA(A.metadata[Q]);if(Q.location==="metadata")return vUA(A.metadata[Q.field]);let{frontmatter:w}=M$(A.content);return vUA(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 F1(`${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 vUA(A){return typeof A==="string"?A.length>0:A!==void 0}$A();b0();var q36=H.object({id:H.string().min(1)});async function Rv2(A,Q){let{bodyContent:w,coverImageId:$,documents:B,sourceEntityType:X,sourceEntityId:Y}=z36(Q.content),Z=$?await F36(A,$):void 0,W;if(B&&B.length>0){let U=await I36(A,B);if(U.length>0)W=U}W??=await V36(A,X,Y);let K={bodyContent:w};if(Z)K.imageData=Z;if(W&&W.length>0)K.documentData=W;return K}function z36(A){try{let Q=DQ(A,H.record(H.string(),H.unknown())),w=Q.metadata.coverImageId,$=typeof w==="string"?w:void 0,B=J36(Q.metadata.documents),X=xv2(Q.metadata.sourceEntityType),Y=xv2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...$&&{coverImageId:$},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function J36(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=q36.safeParse(Q);return w.success?[w.data]:[]})}function xv2(A){return typeof A==="string"&&A.length>0?A:void 0}async function V36(A,Q,w){if(!Q||!w)return;let $=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return $?[$]:void 0}async function F36(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let $=vv2(w.content);if(!$?.mimeType.startsWith("image/"))return;return{data:$.data,mimeType:$.mimeType}}async function I36(A,Q){return(await Promise.all(Q.map(($)=>L36(A,$)))).filter(($)=>$!==void 0)}async function L36(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let $=vv2(w.content);if($?.mimeType!=="application/pdf")return;return{type:"document",data:$.data,mimeType:"application/pdf",filename:N36(w,Q.id)}}function vv2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function N36(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}Q4();var _36=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function CUA(A,Q,w,$={}){let B=$.publishTimestampField??"publishedAt",X=Q.metadata[B],Y=$.publishedAt??(typeof X==="string"?X:void 0)??new Date().toISOString(),Z={...Q.metadata,status:"published",[B]:Y,platformId:w.id,...b36(w.id,$.publishResultIdField)},W={...Q,content:Cv2(Q.content,Y,w.id,$.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:W}),W}function Cv2(A,Q,w,$,B="publishedAt"){if(!_36.test(A))return A;let X=n4(n4(A,"status","published"),B,Q);if(!w||!$)return X;return n4(X,$,w)}function b36(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class td{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:$}=A;if(!w&&!$)return{error:"Either 'id' or 'slug' must be provided"};let B=await this.findPublishableEntity(Q,w,$);if(!B)return{error:`Entity not found: ${Q}:${w??$}`};if(B.visibility!=="public")return{error:`Cannot publish ${Q}:${B.id} to a public provider because visibility is ${B.visibility}`};if(B.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:B}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:$}=A,B=this.deps.providerRegistry.get($),{bodyContent:X,imageData:Y,documentData:Z}=await Rv2(this.deps.context,w),W=await B.publish(X,w.metadata,Y,Z),K=this.deps.providerRegistry.getPublishResultIdField($),U=this.deps.providerRegistry.getPublishTimestampField($),G=await CUA(this.deps.context,w,W,{...K?{publishResultIdField:K}:{},...U?{publishTimestampField:U}:{}});return await this.runPublishAssetPreflight(G),{entity:G,result:W}}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}}$A();b0();var hUA=H.object({action:H.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:H.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:H.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:H.number().optional().describe("New position for reorder action (1-based)")}),EUA=H.object({position:H.number(),entityType:H.string(),entityId:H.string(),queuedAt:H.string()}),k36=H.object({success:H.literal(!0),message:H.string().optional(),data:H.object({queue:H.array(EUA).optional(),entityType:H.string().optional(),entityId:H.string().optional(),position:H.number().optional()}).optional()}),P36=H.object({success:H.literal(!1),error:H.string(),code:H.string().optional()}),gUA=H.union([k36,P36]);function wb0(A,Q,w,$){let B=$??w;return{...j$(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",hUA,async(Y,Z)=>{let{action:W,entityType:K,entityId:U,position:G}=Y;switch(W){case"list":return M36(w,K);case"add":return j36(A,B,K,U,Z);case"remove":return O36(A,B,K,U,Z);case"reorder":return f36(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${W}`}}},{sideEffects:"writes"}),outputSchema:gUA}}async function M36(A,Q){let w=[];if(Q)w=await A.list(Q);else{let B=A.getRegisteredTypes();for(let X of B){let Y=await A.list(X);w.push(...Y)}w.sort((X,Y)=>new Date(X.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((B,X)=>({position:X+1,entityType:B.entityType,entityId:B.entityId,queuedAt:B.queuedAt}))},message:`${w.length} items in queue`}}async function j36(A,Q,w,$,B){let X=yUA("add",w,$);if(!X.success)return X.error;A.permissions.assertEntityActionAllowed(X.entityType,"publish",B??{});let Y=await Q.add(X.entityType,X.entityId,{...B,authorization:"user"});return{success:!0,data:{entityType:X.entityType,entityId:X.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function O36(A,Q,w,$,B){let X=yUA("remove",w,$);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(X.entityType,"update",B??{}),await Q.remove(X.entityType,X.entityId),{success:!0,data:{entityType:X.entityType,entityId:X.entityId},message:"Removed from queue"}}async function f36(A,Q,w,$,B,X){let Y=yUA("reorder",w,$);if(!Y.success)return Y.error;let Z=x36(B);if(!Z.success)return Z.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",X??{}),await Q.reorder(Y.entityType,Y.entityId,Z.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:Z.position},message:`Moved to position ${Z.position}`}}function yUA(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 x36(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}}b0();import{createHash as R36}from"crypto";var TUA=H.object({entityType:H.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:H.string().optional().describe("Entity ID to publish"),slug:H.string().optional().describe("Entity slug to publish"),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),contentHash:H.string().optional(),expiresAt:H.string().datetime().optional()}),v36=H.object({entityType:H.string(),id:H.string().optional(),slug:H.string().optional(),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),contentHash:H.string().optional(),expiresAt:H.string().datetime().optional()}),C36=H.object({success:H.literal(!0),message:H.string().optional(),data:H.object({entityType:H.string().optional(),entityId:H.string().optional(),platformId:H.string().optional(),url:H.string().optional()}).optional()}),h36=H.object({success:H.literal(!1),error:H.string(),code:H.string().optional()}),E36=H.object({success:H.literal(!1).optional(),error:H.string().optional(),needsConfirmation:H.literal(!0),toolName:H.string(),summary:H.string(),preview:H.string().optional(),args:H.unknown()}),SUA=H.union([C36,h36,E36]),g36=900000;function ed(A,Q,w,$){let B=$??new td({context:A,providerRegistry:w}),X=`${Q}_publish`;return{name:X,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:TUA.shape,outputSchema:SUA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let W=v36.safeParse(Y);if(!W.success)return{success:!1,error:`Invalid input: ${W.error.issues.map((I)=>`${I.path.join(".")}: ${I.message}`).join(", ")}`};let K=W.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(I){return{success:!1,error:I instanceof Error?I.message:String(I)}}let z=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in z)return{success:!1,error:z.error};let{entity:V}=z;if(K.confirmed){let I=T36(X,K,V);if(I!==null)return I;let F;try{F=await B.publish({entityType:U,id:V.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in F)return{success:!1,error:F.error};let{entity:_,result:k}=F;return{success:!0,data:{entityType:U,entityId:_.id,platformId:k.id,url:k.url},message:`Published ${U}:${_.id}`}}return y36(X,K,V)}}}function y36(A,Q,w){let $=new Date(Date.now()+g36).toISOString(),B=hv2(A,w,$),X=S36(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${X}"?`,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:B,contentHash:w.contentHash,expiresAt:$}}}function T36(A,Q,w){let{confirmationToken:$,contentHash:B,expiresAt:X}=Q;if(!$||!X)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(X);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if(B&&B!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if($!==hv2(A,w,X))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function hv2(A,Q,w){return R36("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 S36(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 $=A.metadata.slug;if(typeof $==="string"&&$.length>0)return $;return A.id}$A();b0();var mUA=H.object({entityType:H.string().min(1).describe("Entity type to reconcile"),status:H.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:H.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),uUA=H.object({success:H.literal(!0),data:H.object({entityType:H.string(),assetType:H.string().optional(),checkedEntities:H.number(),checkedAssets:H.number(),enqueued:H.number(),skipped:H.number()}),message:H.string().optional()});function $b0(A,Q,w,$){return{...j$(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",mUA,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),w.list(X.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!X.assetType||D.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let W=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),K=0,U=0,G=0;for(let D of W){let z=await $.ensureForEntity(D,{...X.assetType&&{attachmentType:X.assetType}});K+=z.checked,U+=z.enqueued,G+=z.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:W.length,checkedAssets:K,enqueued:U,skipped:G},message:`Queued ${U} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:uUA}}$A();Q4();b0();var m36="content-pipeline.queue.v1",cUA=1024,u36=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,c36=H.object({interfaceType:H.string().optional(),userId:H.string().optional(),userPermissionLevel:H.enum(["public","trusted","anchor"]).optional(),authorization:H.enum(["user","system"]).optional()}),p36=H.object({entityType:H.string(),entityId:H.string(),rank:H.number().int().positive(),queuedAt:H.string().datetime(),contentHashAtEnqueue:H.string(),authContext:c36,revision:H.number().int().positive()});class pUA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:m36,schema:p36})}async add(A,Q,w=y_){return this.enqueue(A,Q,w)}async enqueue(A,Q,w=y_){return this.runExclusive(async()=>{let $=await this.requireEntity(A,Q);await this.persistStatus($,"queued");let B=await this.queueManager.add(A,Q,w);if(!await this.store.get($D(A,Q))){let Y=(await this.queueManager.list(A)).find((W)=>W.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set($D(A,Q),{entityType:A,entityId:Q,rank:B.position*cUA,queuedAt:Y?.queuedAt??new Date().toISOString(),contentHashAtEnqueue:Z.contentHash,authContext:{...w},revision:1})}return B})}async remove(A,Q){await this.runExclusive(async()=>{let w=await this.requireEntity(A,Q);if(w.metadata.status==="queued")await this.persistStatus(w,"draft");await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async reorder(A,Q,w){await this.runExclusive(async()=>{await this.requireEntity(A,Q),await this.queueManager.reorder(A,Q,w),await this.persistCurrentOrder(A)})}async complete(A,Q){await this.runExclusive(async()=>{await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async fail(A,Q,w){await this.runExclusive(async()=>{let $=await this.context.entityService.getEntity({entityType:A,id:Q});if($)await this.persistStatus($,"failed",w);await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async reconcile(A){await this.runExclusive(async()=>{let Q=new Map;for(let W of A){let K=await this.context.entityService.listEntities({entityType:W,options:{filter:{metadata:{status:"queued"}}}});for(let U of K)Q.set($D(W,U.id),U)}let w=await this.listStored();for(let W of w)if(!Q.has($D(W.entityType,W.entityId)))await this.store.delete($D(W.entityType,W.entityId));let $=(await this.listStored()).filter((W)=>Q.has($D(W.entityType,W.entityId))),B=new Map;for(let W of $)B.set(W.entityType,Math.max(B.get(W.entityType)??0,W.rank));for(let[W,K]of Q){if($.some((G)=>$D(G.entityType,G.entityId)===W))continue;let U=(B.get(K.entityType)??0)+cUA;B.set(K.entityType,U),await this.store.set(W,{entityType:K.entityType,entityId:K.id,rank:U,queuedAt:typeof K.updated==="string"?K.updated:new Date().toISOString(),contentHashAtEnqueue:K.contentHash,authContext:{...y_},revision:1})}let X=await this.listStored(),Y=new Map,Z=X.map((W)=>{let K=(Y.get(W.entityType)??0)+1;return Y.set(W.entityType,K),{entityType:W.entityType,entityId:W.entityId,position:K,queuedAt:W.queuedAt,authContext:{...W.authContext}}});this.queueManager.replace(Z)})}async listStored(A){return(await this.store.list()).map((Q)=>Q.value).filter((Q)=>!A||Q.entityType===A).sort((Q,w)=>Q.entityType.localeCompare(w.entityType)||Q.rank-w.rank||Q.queuedAt.localeCompare(w.queuedAt)||Q.entityId.localeCompare(w.entityId))}async deleteStored(A,Q){return this.store.delete($D(A,Q))}async persistCurrentOrder(A){let Q=new Map((await this.listStored(A)).map((w)=>[w.entityId,w]));for(let w of await this.queueManager.list(A)){let $=Q.get(w.entityId);if(!$)continue;let B=w.position*cUA;if($.rank===B)continue;await this.store.set($D(A,w.entityId),{...$,rank:B,revision:$.revision+1})}}async persistStatus(A,Q,w){let $={...A.metadata,status:Q};if(w)$.error=w;else delete $.error;let B=u36.test(A.content)?n4(A.content,"status",Q):A.content;await this.context.entityService.updateEntity({entity:{...A,metadata:$,content:B}})}async requireEntity(A,Q){let w=await this.context.entityService.getEntity({entityType:A,id:Q});if(!w)throw Error(`Entity not found: ${A}:${Q}`);return w}runExclusive(A){let Q=this.mutationTail.then(A);return this.mutationTail=Q.then(()=>{return},()=>{return}),Q}}function $D(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function Ev2(A,Q){l36(A,Q),d36(A,Q),i36(A,Q),n36(A,Q)}function l36(A,Q){A.messaging.subscribe(ZY.REGISTER,async(w)=>r36(Q,w.payload)),A.messaging.subscribe(ZY.QUEUE,async(w)=>t36(A,Q,w.payload)),A.messaging.subscribe(ZY.DIRECT,async(w)=>e36(A,Q,w.payload)),A.messaging.subscribe(ZY.REMOVE,async(w)=>AD6(Q,w.payload)),A.messaging.subscribe(ZY.REORDER,async(w)=>QD6(Q,w.payload)),A.messaging.subscribe(ZY.LIST,async(w)=>wD6(A,Q,w.payload)),A.messaging.subscribe(ZY.REPORT_SUCCESS,async(w)=>$D6(Q,w.payload)),A.messaging.subscribe(ZY.REPORT_FAILURE,async(w)=>BD6(Q,w.payload)),A.messaging.subscribe(ZY.COMPLETED,async(w)=>{return await Q.publicationQueueService.complete(w.payload.entityType,w.payload.entityId),{success:!0}}),A.messaging.subscribe(ZY.FAILED,async(w)=>{return await Q.publicationQueueService.fail(w.payload.entityType,w.payload.entityId,w.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function d36(A,Q){A.messaging.subscribe($O.REPORT_SUCCESS,async(w)=>XD6(Q,w.payload)),A.messaging.subscribe($O.REPORT_FAILURE,async(w)=>YD6(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function i36(A,Q){A.messaging.subscribe(Nv2.REGISTER,async(w)=>o36(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function n36(A,Q){let w=async($)=>s36(A,Q,$.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 r36(A,Q){let{entityType:w,provider:$,config:B}=Q;try{let X=B?_v2.safeParse(B):void 0;if(X&&!X.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:X.error.message}),{success:!1};if($)A.providerRegistry.register(w,$,X?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:$.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(X){let Y=lA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function o36(A,Q){let w=Ab0.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 s36(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let $=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!a36($))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity($),{success:!0}}catch($){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:lA($)}),{success:!1}}}function a36(A){if(!A)return!1;let Q=Lv2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function t36(A,Q,w){let{entityType:$,entityId:B}=w;try{let X=w.authContext??y_;A.permissions.assertEntityActionAllowed($,"publish",X);let Y=await Q.publicationQueueService.enqueue($,B,X);return await A.messaging.send({type:ZY.QUEUED,payload:{entityType:$,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:$,position:Y.position}),{success:!0}}catch(X){let Y=lA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function e36(A,Q,w){let{entityType:$,entityId:B}=w,X=w.authContext??y_;try{if(A.permissions.assertEntityActionAllowed($,"publish",X),!Q.providerRegistry.has($))return Q.scheduler.failPublish($,B,`No publish provider registered for ${$}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:$,id:B});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: ${B}`,{entityType:$}),{success:!0}}catch(Y){let Z=lA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function AD6(A,Q){let{entityType:w,entityId:$}=Q;try{return await A.publicationQueueService.remove(w,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:w}),{success:!0}}catch(B){let X=lA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function QD6(A,Q){let{entityType:w,entityId:$,position:B}=Q;try{return await A.publicationQueueService.reorder(w,$,B),A.logger.debug(`Entity reordered: ${$}`,{entityType:w,newPosition:B}),{success:!0}}catch(X){let Y=lA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function wD6(A,Q,w){let{entityType:$}=w;try{let B=await Q.queueManager.list($);return await A.messaging.send({type:ZY.LIST_RESPONSE,payload:{entityType:$,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=lA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function $D6(A,Q){let{entityType:w,entityId:$,result:B}=Q;return A.scheduler.completePublish(w,$,B),A.logger.info(`Publish reported success: ${$}`,{entityType:w}),{success:!0}}async function BD6(A,Q){let{entityType:w,entityId:$,error:B}=Q;A.scheduler.failPublish(w,$,B);let X=A.retryTracker.getRetryInfo($);return A.logger.info(`Publish reported failure: ${$}`,{entityType:w,error:B,retryCount:X?.retryCount}),{success:!0}}async function XD6(A,Q){let{entityType:w,entityId:$}=Q;return A.scheduler.completeGeneration(w,$),A.logger.info("Generation completed",{entityType:w,entityId:$}),{success:!0}}async function YD6(A,Q){let{entityType:w,error:$}=Q;return A.scheduler.failGeneration(w,$),A.logger.warn("Generation failed",{entityType:w,error:$}),{success:!0}}async function gv2(A,Q,w,$){try{if($.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($.maxUnpublishedDrafts!==void 0){let B=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:$.maxUnpublishedDrafts+1}});if(B.length>=$.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${B.length}/${$.maxUnpublishedDrafts})`}}if($.minSourceEntities!==void 0&&$.sourceEntityType){let B=await A.listEntities({entityType:$.sourceEntityType,options:{publishedOnly:!0,limit:$.minSourceEntities}});if(B.length<$.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${B.length}/${$.minSourceEntities} ${$.sourceEntityType})`}}return{shouldGenerate:!0}}catch(B){return Q.error("Failed to check generation conditions",{entityType:w,error:lA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${lA(B)}`}}}function yv2(A){let{context:Q,config:w,queueManager:$,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,W=ZD6(Q);return MF.createFresh({queueManager:$,providerRegistry:B,retryTracker:X,logger:Z,backend:new vR({onOverlapSkipped:(K)=>{Z.debug("Skipping overlapping content scheduler cycle",{jobKey:K})},onCallbackError:(K,U)=>{Z.error("Unhandled content scheduler callback error",{jobKey:K,error:U})}}),...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:W,publishExecutor:Y,onCheckGenerationConditions:(K,U)=>gv2(Q.entityService,Z,K,U)})}function ZD6(A){return{send:async(B)=>{return A.messaging.send({type:B.type,payload:B.payload,...B.target!==void 0?{target:B.target}:{},...B.metadata!==void 0?{metadata:B.metadata}:{},...B.broadcast!==void 0?{broadcast:B.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}b0();b0();var HD6=H.enum(["draft","queued","published","failed"]),WD6=H.object({entityId:H.string(),entityType:H.string(),title:H.string(),position:H.number().int().positive(),queuedAt:H.string(),destination:H.string(),scheduledFor:H.string().optional()}),KD6=H.object({id:H.string(),label:H.string(),target:H.string(),status:H.enum(["pending","processing"])}),UD6=H.object({entityId:H.string(),entityType:H.string(),title:H.string(),error:H.string(),retryCount:H.number().int().nonnegative()}),GD6=H.object({summary:H.object({draft:H.number().int().nonnegative(),queued:H.number().int().nonnegative(),generating:H.number().int().nonnegative(),failed:H.number().int().nonnegative(),published:H.number().int().nonnegative(),needsOperator:H.number().int().nonnegative()}),queue:H.array(WD6),generating:H.array(KD6),failures:H.array(UD6),publishableEntityTypes:H.array(H.string())}),DD6=H.object({sourceEntityType:H.string(),sourceEntityId:H.string(),attachmentType:H.string().optional()});async function Bb0(A,Q,w,$){let B=Q.getRegisteredTypes().sort(),X=new Map,Y={draft:0,queued:0,generating:0,failed:0,published:0,needsOperator:0};for(let U of B){let G=await A.entityService.listEntities({entityType:U});for(let D of G){let z=HD6.safeParse(D.metadata.status);if(!z.success)continue;Y[z.data]+=1;let V=D.metadata.scheduledFor,I=D.metadata.error;X.set(Tv2(U,D.id),{entityId:D.id,entityType:U,title:zD6(D.id,D.metadata),status:z.data,...typeof V==="string"?{scheduledFor:V}:{},...typeof I==="string"?{error:I}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await w.list(U)){let z=X.get(Tv2(U,D.entityId));if(!z)continue;Z.push({entityId:D.entityId,entityType:U,title:z.title,position:D.position,queuedAt:D.queuedAt,destination:G,...z.scheduledFor?{scheduledFor:z.scheduledFor}:{}})}}let W=await qD6(A);Y.generating=W.length;let K=Array.from(X.values()).filter((U)=>U.status==="failed").map((U)=>{let G=$.getRetryInfo(U.entityId);return{entityId:U.entityId,entityType:U.entityType,title:U.title,error:U.error??G?.lastError??"Publication failed",retryCount:G?.retryCount??0}}).sort((U,G)=>U.title.localeCompare(G.title));return Y.needsOperator=Y.draft+Y.failed,GD6.parse({summary:Y,queue:Z,generating:W,failures:K,publishableEntityTypes:B})}async function qD6(A){let Q=[];for(let w of await A.jobs.getActiveJobs()){if(w.source!=="content-pipeline")continue;if(w.status!=="pending"&&w.status!=="processing")continue;let $;try{$=JSON.parse(w.data)}catch{continue}let B=DD6.safeParse($);if(!B.success)continue;Q.push({id:w.id,label:B.data.attachmentType??w.type,target:`${B.data.sourceEntityType}/${B.data.sourceEntityId}`,status:w.status})}return Q}function Tv2(A,Q){return`${A}\x00${Q}`}function zD6(A,Q){for(let w of["title","subject","slug"]){let $=Q[w];if(typeof $==="string"&&$.length>0)return $}return A}async function Sv2(A,Q,w){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:async()=>({...await Bb0(A,w.providerRegistry,w.queueManager,w.retryTracker),...w.managementUrl?{managementUrl:w.managementUrl}:{}}),digestProvider:VD6}})}var JD6=H.object({summary:H.object({draft:H.number(),queued:H.number(),generating:H.number(),published:H.number(),failed:H.number(),needsOperator:H.number()})});function VD6(A){let{summary:Q}=JD6.parse(A),w=Q.queued+Q.generating,$=w===0?"idle":`${Q.queued} queued \xB7 ${Q.generating} generating`,B=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`;return{digest:[{label:"Pipeline",value:$,...w>0?{tone:"warn"}:{}},{label:"Awaiting review",value:B,...Q.needsOperator>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Q.needsOperator}}$A();b0();var FD6=H.object({workspaceUrl:H.string()}),ID6=H.object({confirmed:H.literal(!0),confirmationToken:H.string().min(1),contentHash:H.string().min(1),expiresAt:H.string().datetime()}),LD6=H.discriminatedUnion("type",[H.object({type:H.literal("queue"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("remove"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("retry"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("reorder"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1),position:H.number().int().positive()}),H.object({type:H.literal("publish"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1),confirmation:ID6.optional()})]);async function mv2(A,Q,w){let $=ed(A,Q,w.providerRegistry,w.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",entityTypes:w.providerRegistry.getRegisteredTypes(),dataProvider:()=>Bb0(A,w.providerRegistry,w.queueManager,w.retryTracker),actionHandler:async(Z,W)=>{let K=LD6.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return ND6(A,w,$,K.data,W)}},X=await A.messaging.send({type:Ot,payload:B});if(!("success"in X)||!X.success)return;let Y=FD6.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function ND6(A,Q,w,$,B){if(!Q.providerRegistry.has($.entityType))throw Error(`No publish provider registered for ${$.entityType}`);let X=await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(!X)throw Error(`Entity not found: ${$.entityType}:${$.entityId}`);if($.type==="publish"){let W=await w.handler({entityType:$.entityType,id:$.entityId,...$.confirmation??{}},B);if("success"in W&&W.success===!0)await Q.publicationQueueService.complete($.entityType,$.entityId),Q.retryTracker.clearRetries($.entityId);return W}let Y=$.type==="queue"||$.type==="retry"?"publish":"update";A.permissions.assertEntityActionAllowed($.entityType,Y,B);let Z=X.metadata.status;switch($.type){case"queue":if(Z!=="draft")throw Error("Only draft entities can be queued");return Q.publicationQueueService.enqueue($.entityType,$.entityId,{...B,authorization:"user"});case"remove":if(Z!=="queued")throw Error("Only queued entities can be removed from the queue");return await Q.publicationQueueService.remove($.entityType,$.entityId),{success:!0};case"retry":if(Z!=="failed")throw Error("Only failed publications can be retried");return await Q.publicationQueueService.enqueue($.entityType,$.entityId,{...B,authorization:"user"}),{success:!0};case"reorder":if(Z!=="queued")throw Error("Only queued entities can be reordered");return await Q.publicationQueueService.reorder($.entityType,$.entityId,$.position),{success:!0}}}var uv2={name:"@brains/content-pipeline",version:"0.2.0-alpha.180",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/scheduler":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class lUA extends Rw{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",uv2,A,bv2)}async onRegister(A){this.pluginContext=A,this.queueManager=kF.createFresh(),this.publicationQueueService=new pUA(A,this.queueManager),this.providerRegistry=PF.createFresh(),this.retryTracker=jF.createFresh(),this.publishAssetRegistry=OF.createFresh(),this.publishAssetPreflight=new Qb0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new td({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=yv2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),Ev2(A,{queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await this.publicationQueueService.reconcile(this.providerRegistry.getRegisteredTypes());let Q=await mv2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await Sv2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,retryTracker:this.retryTracker,...Q?{managementUrl:Q}:{}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[wb0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),ed(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$b0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getPublicationQueueService(){return this.publicationQueueService}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),kF.resetInstance(),PF.resetInstance(),jF.resetInstance(),OF.resetInstance()}}function dUA(A={}){return new lUA(A)}$A();b0();var cv2=H.object({accountId:H.string().describe("Cloudflare account ID"),apiToken:H.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:H.string().describe("Cloudflare Web Analytics site tag")}),iUA=H.object({cloudflare:cv2.optional()});$A();b0();var bD6=H.object({date:H.string().describe("Single date in YYYY-MM-DD format").optional(),days:H.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:H.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:H.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:H.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function kD6(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 pv2(A,Q,w){let $=[];if(!w)return $;return $.push(j$(A,"query",`Query website analytics from Cloudflare.
|
|
8003
|
+
${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:$,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=Y36.parse(Q),$=[],B=hZ.from(async(K)=>{let U={progress:K.progress};if(K.message!==void 0)U.message=K.message;$.push(U)});if(!B)throw Error("Failed to create progress reporter");let Y=await new QE(A.logger,A).process(w,`eval-${Date.now()}`,B),Z=!1,W;if(Y.success&&Y.entityId){let K=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!K,W=K?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:W,progressSteps:$}})}$A();class p$0{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 $=await this.entityService.getEntity({entityType:"social-post",id:w});if(!$){await this.reportFailure(Q,w,`Post not found: ${w}`);return}let B=$;if(B.metadata.status==="published"){this.logger.debug("Post already published, skipping",{entityId:w});return}let X=B.metadata.platform,Y=this.providers.get(X);if(!Y){await this.reportFailure(Q,w,`No provider configured for platform: ${X}`);return}let Z=DQ(B.content,Iz),W;if(Z.metadata.coverImageId)W=await this.fetchImageData(Z.metadata.coverImageId);let K=Z.metadata.documents??[],U=await this.fetchDocumentData(K);try{if(K.length>0&&U.length===0)throw Error(`Refusing to publish: ${K.length} document(s) referenced but none could be fetched`);let G=K.length===0?await this.resolveSourceAttachment(Z.metadata):[],D=U.length>0?U:G,z=D.length?await Y.publish(Z.content,B.metadata,W,D):await Y.publish(Z.content,B.metadata,W),V=new Date().toISOString(),I=z.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...I&&{platformPostId:I}},_=YY.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:_,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:I}}}),await this.reportSuccess(Q,w,z.id),this.logger.info(`Post published successfully: ${w}`,{platform:X,platformPostId:I})}catch(G){let D=G instanceof Error?G.message:String(G),z={...Z.metadata,status:"failed"},V=YY.createPostContent(z,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,w,D),this.logger.error(`Post publish failed: ${w}`,{platform:X,error:D})}}catch($){let B=lA($);this.logger.error("Unexpected error in publish handler",{entityId:w,error:B}),await this.reportFailure(Q,w,B)}}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 $=await this.fetchSingleDocumentData(w.id);if($)Q.push($)}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 $=typeof Q.metadata.filename==="string"?Q.metadata.filename:`${A}.pdf`;return{type:"document",data:Buffer.from(w[1],"base64"),mimeType:"application/pdf",filename:$}}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 $=Q.content.match(/^data:([^;]+);base64,(.+)$/);if(!$?.[1]||!$[2]){this.logger.warn("Invalid image data URL format",{imageId:A});return}let B=$[1],X=$[2];return{data:Buffer.from(X,"base64"),mimeType:B}}catch(Q){this.logger.warn("Failed to fetch cover image",{imageId:A,error:Q});return}}}function Dv2(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 $=Q.values().next().value;return await A.messaging.send({type:"publish:register",payload:{entityType:"social-post",provider:$,config:{publishResultIdField:"platformPostId"}}}),w.info("Registered social-post with publish-pipeline"),{success:!0}})}function qv2(A,Q,w){let $=new p$0({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(B)=>{return await $.handle(B.payload),{success:!0}}),w.debug("Subscribed to publish:execute messages")}function zv2(A,Q){A.messaging.subscribe("entity:updated",async(w)=>{let{entityType:$,entityId:B,entity:X}=w.payload;if($!=="post")return{success:!0};if(X.metadata?.status!=="queued")return{success:!0};try{if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:B}},limit:1}})).length>0)return Q.debug(`Social post already exists for ${B}, skipping auto-generate`),{success:!0};return await A.messaging.send({type:"social:auto-generate",payload:{sourceEntityType:$,sourceEntityId:B,platform:"linkedin"}}),Q.info(`Auto-generate social post triggered for queued post ${B}`),{success:!0}}catch(Z){let W=lA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:W}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function Jv2(A,Q){A.messaging.subscribe("social:auto-generate",async(w)=>{let{sourceEntityType:$,sourceEntityId:B,platform:X}=w.payload;try{let Y=await A.jobs.enqueue({type:`${YY.entityType}:generation`,data:{sourceEntityType:$,sourceEntityId:B,platform:X,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 Z=lA(Y);return Q.error(`Failed to enqueue social post generation for ${B}:`,{error:Z}),{success:!1}}}),Q.debug("Subscribed to social:auto-generate messages")}function Vv2(A,Q){A.messaging.subscribe("generate:execute",async(w)=>{let{entityType:$}=w.payload;if($!=="social-post")return{success:!0};Q.info("Received generate:execute for social-post");try{let B=await A.entityService.listEntities({entityType:"post",options:{filter:{metadata:{status:"published"}},limit:5}});if(B.length===0)return Q.info("No published posts found for social post generation"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"No published posts available for social post generation"}}),{success:!0};let X=null;for(let Z of B)if((await A.entityService.listEntities({entityType:"social-post",options:{filter:{metadata:{sourceEntityType:"post",sourceEntityId:Z.id}},limit:1}})).length===0){X=Z;break}if(!X)return Q.info("All recent posts already have social posts"),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:"All recent posts already have social posts generated"}}),{success:!0};let Y=await A.jobs.enqueue({type:`${YY.entityType}:generation`,data:{sourceEntityType:"post",sourceEntityId:X.id,platform:"linkedin",addToQueue:!1},toolContext:{interfaceType:"job",userId:"system"}});return Q.info("Social post generation job queued",{jobId:Y,sourcePostId:X.id}),{success:!0}}catch(B){let X=lA(B);return Q.error("Failed to handle generate:execute:",{error:X}),await A.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:X}}),{success:!0}}}),Q.debug("Subscribed to generate:execute messages")}async function Fv2({entity:A,config:Q}){let w=wO.parse(A),$=YY.parsePostFrontmatter(w),B=YY.getPostContent(w);return{$type:"ai.rizom.brain.socialPost",title:$.title,platform:$.platform,body:B,format:"text/markdown",status:$.status,...$.publishedAt&&{publishedAt:$.publishedAt},...$.platformPostId&&{platformPostId:$.platformPostId},...$.sourceEntityType&&{sourceLocalEntityType:$.sourceEntityType},...$.sourceEntityId&&{sourceLocalEntityId:$.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 PUA(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:I$["ai.rizom.brain.socialPost"],validate:!1,buildRecord:Fv2}}var Iv2={name:"@brains/social-media",version:"0.2.0-alpha.181",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 MUA extends jw{entityType=YY.entityType;schema=wO;adapter=YY;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",Iv2,A,IUA)}createGenerationHandler(A){return new QE(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return Uv2()}getDataSources(){return[new s_0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),Dv2(A,this.providers,this.logger),qv2(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)zv2(A,this.logger),Jv2(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");Vv2(A,this.logger),Gv2(A),this.unregisterAtprotoProjection=fB.getInstance().register(PUA()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=kUA(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function l$0(A={}){return new MUA(A)}b0();var H36=H.enum(["draft","queued","published","failed"]),Lv2=H.object({status:H36.default("draft"),queueOrder:H.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:H.string().datetime().optional()});class jUA{name="internal";async publish(A,Q){return{id:"internal"}}}var y_={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},ZY={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"},$O={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"},Nv2={REGISTER:"publish-assets:register"};b0();var W36=H.enum(["provider"]),_v2=H.object({executionMode:W36.optional(),publishResultIdField:H.string().min(1).optional(),publishTimestampField:H.string().min(1).optional(),enabled:H.boolean().optional()}).strict();var K36=H.object({skipIfDraftExists:H.boolean().optional(),minSourceEntities:H.number().optional(),maxUnpublishedDrafts:H.number().optional(),sourceEntityType:H.string().optional()}),bv2=H.object({entitySchedules:H.record(H.string(),H.string()).optional(),generationSchedules:H.record(H.string(),H.string()).optional(),generationConditions:H.record(H.string(),K36).optional()});class kF{static instance=null;queues=new Map;static getInstance(){return kF.instance??=new kF,kF.instance}static resetInstance(){kF.instance=null}static createFresh(){return new kF}constructor(){}async add(A,Q,w=y_){let $=this.getOrCreateQueue(A),B=$.find((Z)=>Z.entityId===Q);if(B)return{position:B.position};let X=$.length+1,Y={entityId:Q,entityType:A,position:X,queuedAt:new Date().toISOString(),authContext:{...w}};return $.push(Y),{position:X}}async remove(A,Q){let w=this.queues.get(A);if(!w)return;let $=w.findIndex((B)=>B.entityId===Q);if($===-1)return;w.splice($,1),this.recalculatePositions(w)}async reorder(A,Q,w){let $=this.queues.get(A);if(!$)return;let B=$.findIndex((Z)=>Z.entityId===Q);if(B===-1)return;let[X]=$.splice(B,1);if(!X)return;let Y=Math.max(0,Math.min(w-1,$.length));$.splice(Y,0,X),this.recalculatePositions($)}async list(A){let Q=this.queues.get(A);if(!Q)return[];return[...Q]}async getNext(A){let Q=this.queues.get(A);if(!Q||Q.length===0)return null;return Q[0]??null}async getNextAcrossTypes(){let A=null;for(let Q of this.queues.values()){let 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}replace(A){this.queues.clear();let Q=[...A].sort((w,$)=>w.entityType.localeCompare($.entityType)||w.position-$.position);for(let w of Q)this.getOrCreateQueue(w.entityType).push({...w,authContext:{...w.authContext}});for(let w of this.queues.values())this.recalculatePositions(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 PF{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new jUA;static getInstance(){return PF.instance??=new PF,PF.instance}static resetInstance(){PF.instance=null}static createFresh(){return new PF}constructor(){}register(A,Q,w){let $=this.providers.get(A);if($&&$.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 kv2(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await U36(A,Q)}async function U36(A,Q){if(!Q.publishExecutor)return;try{let w=await Q.publishExecutor.publish({entityType:A.entityType,id:A.entityId});if("error"in w){let $={entityType:A.entityType,entityId:A.entityId,error:w.error,retryCount:0,willRetry:!1};if(Q.messageBus)await Q.messageBus.send({type:ZY.FAILED,payload:$,sender:"publish-service",broadcast:!0});Q.onFailed?.($);return}OUA(A.entityType,A.entityId,w.result,Q)}catch(w){let $=lA(w);Q.retryTracker.recordFailure(A.entityId,$);let B=Q.retryTracker.getRetryInfo(A.entityId);Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:$,retryCount:B?.retryCount??1,willRetry:!1})}}function OUA(A,Q,w,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send({type:ZY.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});$.onPublish?.({entityType:A,entityId:Q,result:w})}function Pv2(A,Q,w,$){$.retryTracker.recordFailure(Q,w);let B=$.retryTracker.getRetryInfo(Q),X={entityType:A,entityId:Q,error:w,retryCount:B?.retryCount??1,willRetry:!1};if($.messageBus)$.messageBus.send({type:ZY.FAILED,payload:X,sender:"publish-service",broadcast:!0});$.onFailed?.(X)}async function Mv2(A,Q){let w=Q.generationConditions[A];if(w&&Q.onCheckGenerationConditions){let B=await Q.onCheckGenerationConditions(A,w);if(!B.shouldGenerate){if(Q.messageBus)Q.messageBus.send({type:$O.SKIPPED,payload:{entityType:A,reason:B.reason??"Conditions not met"},sender:"content-pipeline"});return}}let $={entityType:A};if(Q.messageBus)await Q.messageBus.send({type:$O.EXECUTE,payload:$,sender:"content-pipeline"});Q.onGenerate?.($)}function jv2(A,Q,w){if(w)w.send({type:$O.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function Ov2(A,Q,w){if(w)w.send({type:$O.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var G36=1000;class fUA{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(G36,()=>this.processUnscheduledTypes())}async stop(){let A=Array.from(this.publishJobs.values());if(this.publishJobs.clear(),this.immediateIntervalJob)A.push(this.immediateIntervalJob),this.immediateIntervalJob=null;await Promise.all(A.map((Q)=>Q.stop()))}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let 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 kv2(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}class xUA{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)}}async stop(){let A=Array.from(this.generationJobs.values());this.generationJobs.clear(),await Promise.all(A.map((Q)=>Q.stop()))}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await Mv2(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}class MF{static instance=null;config;publishRunner;generationRunner;running=!1;stopPromise=null;static getInstance(A){return MF.instance??=new MF(A),MF.instance}static async resetInstance(){let A=MF.instance;if(MF.instance=null,A)await A.stop()}static createFresh(A){return new MF(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new fUA({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new xUA({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}stop(){if(this.stopPromise)return this.stopPromise;return this.running=!1,this.stopPromise=Promise.all([this.publishRunner.stop(),this.generationRunner.stop()]).then(()=>{return}),this.stopPromise}isRunning(){return this.running}completePublish(A,Q,w){OUA(A,Q,w,this.publishDeps)}failPublish(A,Q,w){Pv2(A,Q,w,this.publishDeps)}completeGeneration(A,Q){jv2(A,Q,this.config.messageBus)}failGeneration(A,Q){Ov2(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($){throw Error(`Invalid ${w} cron expression for ${A}: "${Q}" - ${lA($)}`,{cause:$})}}}class jF{static instance=null;retries=new Map;static getInstance(){return jF.instance??=new jF,jF.instance}static resetInstance(){jF.instance=null}static createFresh(){return new jF}constructor(){}recordFailure(A,Q){let $=(this.retries.get(A)?.retryCount??0)+1;this.retries.set(A,{entityId:A,retryCount:$,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}}}vr0();b0();var fv2=H.union([H.string().min(1),H.object({location:H.enum(["metadata","frontmatter"]),field:H.string().min(1)})]),Ab0=H.object({entityType:H.string().min(1),attachmentType:H.string().min(1),mediaEntityType:H.enum(["image","document"]),targetEntityField:fv2.optional(),requiredWhen:H.object({status:H.string().min(1).optional(),visibility:H.string().min(1).optional()}).optional(),autoGenerate:H.boolean().optional(),requiredForPublish:H.boolean().optional(),jobType:H.string().min(1).optional()});function RUA(A){return`${A.entityType}:${A.attachmentType}`}class OF{static instance=null;definitions=new Map;static getInstance(){return OF.instance??=new OF,OF.instance}static resetInstance(){OF.instance=null}static createFresh(){return new OF}constructor(){}register(A){let Q=Ab0.parse(A),w=RUA(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(RUA({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(RUA({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}Q4();R2();class Qb0{deps;constructor(A){this.deps=A}async ensureForEntity(A,Q={}){let w=this.deps.registry.list(A.entityType).filter((B)=>B.autoGenerate===!0).filter((B)=>!Q.attachmentType||B.attachmentType===Q.attachmentType),$={checked:w.length,enqueued:0,skipped:0};for(let B of w)if(await this.ensureDefinition(A,B))$.enqueued+=1;else $.skipped+=1;return $}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 $=this.getPredictedMediaId(A,Q),B=this.getDeduplicationKey(A,Q);return await this.deps.context.jobs.enqueue({type:w,data:{sourceEntityType:A.entityType,sourceEntityId:A.id,attachmentType:Q.attachmentType,imageId:$,dedupKey:B,targetEntityType:A.entityType,targetEntityId:A.id,...this.getTargetImageFieldData(Q.targetEntityField)},options:{source:"content-pipeline",metadata:{operationType:"content_operations"},deduplication:"skip",deduplicationKey:B}}),this.deps.context.logger.debug("Queued publish asset generation",{entityType:A.entityType,entityId:A.id,attachmentType:Q.attachmentType,jobType: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 vUA(A.metadata[Q]);if(Q.location==="metadata")return vUA(A.metadata[Q.field]);let{frontmatter:w}=M$(A.content);return vUA(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 F1(`${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 vUA(A){return typeof A==="string"?A.length>0:A!==void 0}$A();b0();var q36=H.object({id:H.string().min(1)});async function Rv2(A,Q){let{bodyContent:w,coverImageId:$,documents:B,sourceEntityType:X,sourceEntityId:Y}=z36(Q.content),Z=$?await F36(A,$):void 0,W;if(B&&B.length>0){let U=await I36(A,B);if(U.length>0)W=U}W??=await V36(A,X,Y);let K={bodyContent:w};if(Z)K.imageData=Z;if(W&&W.length>0)K.documentData=W;return K}function z36(A){try{let Q=DQ(A,H.record(H.string(),H.unknown())),w=Q.metadata.coverImageId,$=typeof w==="string"?w:void 0,B=J36(Q.metadata.documents),X=xv2(Q.metadata.sourceEntityType),Y=xv2(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...$&&{coverImageId:$},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function J36(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=q36.safeParse(Q);return w.success?[w.data]:[]})}function xv2(A){return typeof A==="string"&&A.length>0?A:void 0}async function V36(A,Q,w){if(!Q||!w)return;let $=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return $?[$]:void 0}async function F36(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let $=vv2(w.content);if(!$?.mimeType.startsWith("image/"))return;return{data:$.data,mimeType:$.mimeType}}async function I36(A,Q){return(await Promise.all(Q.map(($)=>L36(A,$)))).filter(($)=>$!==void 0)}async function L36(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let $=vv2(w.content);if($?.mimeType!=="application/pdf")return;return{type:"document",data:$.data,mimeType:"application/pdf",filename:N36(w,Q.id)}}function vv2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function N36(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}Q4();var _36=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function CUA(A,Q,w,$={}){let B=$.publishTimestampField??"publishedAt",X=Q.metadata[B],Y=$.publishedAt??(typeof X==="string"?X:void 0)??new Date().toISOString(),Z={...Q.metadata,status:"published",[B]:Y,platformId:w.id,...b36(w.id,$.publishResultIdField)},W={...Q,content:Cv2(Q.content,Y,w.id,$.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:W}),W}function Cv2(A,Q,w,$,B="publishedAt"){if(!_36.test(A))return A;let X=n4(n4(A,"status","published"),B,Q);if(!w||!$)return X;return n4(X,$,w)}function b36(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class td{deps;constructor(A){this.deps=A}async resolveCandidate(A){let{entityType:Q,id:w,slug:$}=A;if(!w&&!$)return{error:"Either 'id' or 'slug' must be provided"};let B=await this.findPublishableEntity(Q,w,$);if(!B)return{error:`Entity not found: ${Q}:${w??$}`};if(B.visibility!=="public")return{error:`Cannot publish ${Q}:${B.id} to a public provider because visibility is ${B.visibility}`};if(B.metadata.status==="published")return{error:"Entity is already published"};if(!this.deps.providerRegistry.has(Q))return{error:`No publish provider registered for ${Q}. Check that the required credentials are configured.`};return{entity:B}}async publish(A){let Q=await this.resolveCandidate(A);if("error"in Q)return Q;let{entity:w}=Q,{entityType:$}=A,B=this.deps.providerRegistry.get($),{bodyContent:X,imageData:Y,documentData:Z}=await Rv2(this.deps.context,w),W=await B.publish(X,w.metadata,Y,Z),K=this.deps.providerRegistry.getPublishResultIdField($),U=this.deps.providerRegistry.getPublishTimestampField($),G=await CUA(this.deps.context,w,W,{...K?{publishResultIdField:K}:{},...U?{publishTimestampField:U}:{}});return await this.runPublishAssetPreflight(G),{entity:G,result:W}}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}}$A();b0();var hUA=H.object({action:H.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:H.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:H.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:H.number().optional().describe("New position for reorder action (1-based)")}),EUA=H.object({position:H.number(),entityType:H.string(),entityId:H.string(),queuedAt:H.string()}),k36=H.object({success:H.literal(!0),message:H.string().optional(),data:H.object({queue:H.array(EUA).optional(),entityType:H.string().optional(),entityId:H.string().optional(),position:H.number().optional()}).optional()}),P36=H.object({success:H.literal(!1),error:H.string(),code:H.string().optional()}),gUA=H.union([k36,P36]);function wb0(A,Q,w,$){let B=$??w;return{...j$(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",hUA,async(Y,Z)=>{let{action:W,entityType:K,entityId:U,position:G}=Y;switch(W){case"list":return M36(w,K);case"add":return j36(A,B,K,U,Z);case"remove":return O36(A,B,K,U,Z);case"reorder":return f36(A,B,K,U,G,Z);default:return{success:!1,error:`Unknown action: ${W}`}}},{sideEffects:"writes"}),outputSchema:gUA}}async function M36(A,Q){let w=[];if(Q)w=await A.list(Q);else{let B=A.getRegisteredTypes();for(let X of B){let Y=await A.list(X);w.push(...Y)}w.sort((X,Y)=>new Date(X.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((B,X)=>({position:X+1,entityType:B.entityType,entityId:B.entityId,queuedAt:B.queuedAt}))},message:`${w.length} items in queue`}}async function j36(A,Q,w,$,B){let X=yUA("add",w,$);if(!X.success)return X.error;A.permissions.assertEntityActionAllowed(X.entityType,"publish",B??{});let Y=await Q.add(X.entityType,X.entityId,{...B,authorization:"user"});return{success:!0,data:{entityType:X.entityType,entityId:X.entityId,position:Y.position},message:`Added to queue at position ${Y.position}`}}async function O36(A,Q,w,$,B){let X=yUA("remove",w,$);if(!X.success)return X.error;return A.permissions.assertEntityActionAllowed(X.entityType,"update",B??{}),await Q.remove(X.entityType,X.entityId),{success:!0,data:{entityType:X.entityType,entityId:X.entityId},message:"Removed from queue"}}async function f36(A,Q,w,$,B,X){let Y=yUA("reorder",w,$);if(!Y.success)return Y.error;let Z=x36(B);if(!Z.success)return Z.error;return A.permissions.assertEntityActionAllowed(Y.entityType,"update",X??{}),await Q.reorder(Y.entityType,Y.entityId,Z.position),{success:!0,data:{entityType:Y.entityType,entityId:Y.entityId,position:Z.position},message:`Moved to position ${Z.position}`}}function yUA(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 x36(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}}b0();import{createHash as R36}from"crypto";var TUA=H.object({entityType:H.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:H.string().optional().describe("Entity ID to publish"),slug:H.string().optional().describe("Entity slug to publish"),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),contentHash:H.string().optional(),expiresAt:H.string().datetime().optional()}),v36=H.object({entityType:H.string(),id:H.string().optional(),slug:H.string().optional(),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),contentHash:H.string().optional(),expiresAt:H.string().datetime().optional()}),C36=H.object({success:H.literal(!0),message:H.string().optional(),data:H.object({entityType:H.string().optional(),entityId:H.string().optional(),platformId:H.string().optional(),url:H.string().optional()}).optional()}),h36=H.object({success:H.literal(!1),error:H.string(),code:H.string().optional()}),E36=H.object({success:H.literal(!1).optional(),error:H.string().optional(),needsConfirmation:H.literal(!0),toolName:H.string(),summary:H.string(),preview:H.string().optional(),args:H.unknown()}),SUA=H.union([C36,h36,E36]),g36=900000;function ed(A,Q,w,$){let B=$??new td({context:A,providerRegistry:w}),X=`${Q}_publish`;return{name:X,description:"Publish an entity directly to its platform. Call this when the user asks to publish; the tool will request confirmation itself. Works with any registered entity type (social-post, post, deck, etc.). For follow-up requests like 'publish it now', use the entity just read, generated, or updated in the conversation, including a post just changed to draft.",inputSchema:TUA.shape,outputSchema:SUA,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let W=v36.safeParse(Y);if(!W.success)return{success:!1,error:`Invalid input: ${W.error.issues.map((I)=>`${I.path.join(".")}: ${I.message}`).join(", ")}`};let K=W.data,{entityType:U,id:G,slug:D}=K;try{A.permissions.assertEntityActionAllowed(U,"publish",Z)}catch(I){return{success:!1,error:I instanceof Error?I.message:String(I)}}let z=await B.resolveCandidate({entityType:U,id:G,slug:D});if("error"in z)return{success:!1,error:z.error};let{entity:V}=z;if(K.confirmed){let I=T36(X,K,V);if(I!==null)return I;let F;try{F=await B.publish({entityType:U,id:V.id})}catch(b){return{success:!1,error:b instanceof Error?b.message:String(b)}}if("error"in F)return{success:!1,error:F.error};let{entity:_,result:k}=F;return{success:!0,data:{entityType:U,entityId:_.id,platformId:k.id,url:k.url},message:`Published ${U}:${_.id}`}}return y36(X,K,V)}}}function y36(A,Q,w){let $=new Date(Date.now()+g36).toISOString(),B=hv2(A,w,$),X=S36(w);return{needsConfirmation:!0,toolName:A,summary:`Publish "${X}"?`,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:B,contentHash:w.contentHash,expiresAt:$}}}function T36(A,Q,w){let{confirmationToken:$,contentHash:B,expiresAt:X}=Q;if(!$||!X)return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};let Y=Date.parse(X);if(Number.isNaN(Y))return{success:!1,error:"Invalid publish confirmation expiry. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};if(Y<=Date.now())return{success:!1,error:"Publish confirmation expired. Request confirmation again before publishing.",code:"EXPIRED_CONFIRMATION_TOKEN"};if(B&&B!==w.contentHash)return{success:!1,error:`Cannot publish ${w.entityType}:${w.id} because it changed after confirmation. Review it and try again.`};if($!==hv2(A,w,X))return{success:!1,error:"Invalid publish confirmation token. Request confirmation again and retry with the returned confirmation args.",code:"INVALID_CONFIRMATION_TOKEN"};return null}function hv2(A,Q,w){return R36("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 S36(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 $=A.metadata.slug;if(typeof $==="string"&&$.length>0)return $;return A.id}$A();b0();var mUA=H.object({entityType:H.string().min(1).describe("Entity type to reconcile"),status:H.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:H.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),uUA=H.object({success:H.literal(!0),data:H.object({entityType:H.string(),assetType:H.string().optional(),checkedEntities:H.number(),checkedAssets:H.number(),enqueued:H.number(),skipped:H.number()}),message:H.string().optional()});function $b0(A,Q,w,$){return{...j$(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",mUA,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),w.list(X.entityType).filter((D)=>D.autoGenerate===!0).filter((D)=>!X.assetType||D.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let W=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),K=0,U=0,G=0;for(let D of W){let z=await $.ensureForEntity(D,{...X.assetType&&{attachmentType:X.assetType}});K+=z.checked,U+=z.enqueued,G+=z.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:W.length,checkedAssets:K,enqueued:U,skipped:G},message:`Queued ${U} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:uUA}}$A();Q4();b0();var m36="content-pipeline.queue.v1",cUA=1024,u36=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/,c36=H.object({interfaceType:H.string().optional(),userId:H.string().optional(),userPermissionLevel:H.enum(["public","trusted","anchor"]).optional(),authorization:H.enum(["user","system"]).optional()}),p36=H.object({entityType:H.string(),entityId:H.string(),rank:H.number().int().positive(),queuedAt:H.string().datetime(),contentHashAtEnqueue:H.string(),authContext:c36,revision:H.number().int().positive()});class pUA{context;queueManager;store;mutationTail=Promise.resolve();constructor(A,Q){this.context=A,this.queueManager=Q,this.store=A.runtimeState.scoped({namespace:m36,schema:p36})}async add(A,Q,w=y_){return this.enqueue(A,Q,w)}async enqueue(A,Q,w=y_){return this.runExclusive(async()=>{let $=await this.requireEntity(A,Q);await this.persistStatus($,"queued");let B=await this.queueManager.add(A,Q,w);if(!await this.store.get($D(A,Q))){let Y=(await this.queueManager.list(A)).find((W)=>W.entityId===Q),Z=await this.requireEntity(A,Q);await this.store.set($D(A,Q),{entityType:A,entityId:Q,rank:B.position*cUA,queuedAt:Y?.queuedAt??new Date().toISOString(),contentHashAtEnqueue:Z.contentHash,authContext:{...w},revision:1})}return B})}async remove(A,Q){await this.runExclusive(async()=>{let w=await this.requireEntity(A,Q);if(w.metadata.status==="queued")await this.persistStatus(w,"draft");await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async reorder(A,Q,w){await this.runExclusive(async()=>{await this.requireEntity(A,Q),await this.queueManager.reorder(A,Q,w),await this.persistCurrentOrder(A)})}async complete(A,Q){await this.runExclusive(async()=>{await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async fail(A,Q,w){await this.runExclusive(async()=>{let $=await this.context.entityService.getEntity({entityType:A,id:Q});if($)await this.persistStatus($,"failed",w);await this.queueManager.remove(A,Q),await this.store.delete($D(A,Q)),await this.persistCurrentOrder(A)})}async reconcile(A){await this.runExclusive(async()=>{let Q=new Map;for(let W of A){let K=await this.context.entityService.listEntities({entityType:W,options:{filter:{metadata:{status:"queued"}}}});for(let U of K)Q.set($D(W,U.id),U)}let w=await this.listStored();for(let W of w)if(!Q.has($D(W.entityType,W.entityId)))await this.store.delete($D(W.entityType,W.entityId));let $=(await this.listStored()).filter((W)=>Q.has($D(W.entityType,W.entityId))),B=new Map;for(let W of $)B.set(W.entityType,Math.max(B.get(W.entityType)??0,W.rank));for(let[W,K]of Q){if($.some((G)=>$D(G.entityType,G.entityId)===W))continue;let U=(B.get(K.entityType)??0)+cUA;B.set(K.entityType,U),await this.store.set(W,{entityType:K.entityType,entityId:K.id,rank:U,queuedAt:typeof K.updated==="string"?K.updated:new Date().toISOString(),contentHashAtEnqueue:K.contentHash,authContext:{...y_},revision:1})}let X=await this.listStored(),Y=new Map,Z=X.map((W)=>{let K=(Y.get(W.entityType)??0)+1;return Y.set(W.entityType,K),{entityType:W.entityType,entityId:W.entityId,position:K,queuedAt:W.queuedAt,authContext:{...W.authContext}}});this.queueManager.replace(Z)})}async listStored(A){return(await this.store.list()).map((Q)=>Q.value).filter((Q)=>!A||Q.entityType===A).sort((Q,w)=>Q.entityType.localeCompare(w.entityType)||Q.rank-w.rank||Q.queuedAt.localeCompare(w.queuedAt)||Q.entityId.localeCompare(w.entityId))}async deleteStored(A,Q){return this.store.delete($D(A,Q))}async persistCurrentOrder(A){let Q=new Map((await this.listStored(A)).map((w)=>[w.entityId,w]));for(let w of await this.queueManager.list(A)){let $=Q.get(w.entityId);if(!$)continue;let B=w.position*cUA;if($.rank===B)continue;await this.store.set($D(A,w.entityId),{...$,rank:B,revision:$.revision+1})}}async persistStatus(A,Q,w){let $={...A.metadata,status:Q};if(w)$.error=w;else delete $.error;let B=u36.test(A.content)?n4(A.content,"status",Q):A.content;await this.context.entityService.updateEntity({entity:{...A,metadata:$,content:B}})}async requireEntity(A,Q){let w=await this.context.entityService.getEntity({entityType:A,id:Q});if(!w)throw Error(`Entity not found: ${A}:${Q}`);return w}runExclusive(A){let Q=this.mutationTail.then(A);return this.mutationTail=Q.then(()=>{return},()=>{return}),Q}}function $D(A,Q){return`${encodeURIComponent(A)}/${encodeURIComponent(Q)}`}function Ev2(A,Q){l36(A,Q),d36(A,Q),i36(A,Q),n36(A,Q)}function l36(A,Q){A.messaging.subscribe(ZY.REGISTER,async(w)=>r36(Q,w.payload)),A.messaging.subscribe(ZY.QUEUE,async(w)=>t36(A,Q,w.payload)),A.messaging.subscribe(ZY.DIRECT,async(w)=>e36(A,Q,w.payload)),A.messaging.subscribe(ZY.REMOVE,async(w)=>AD6(Q,w.payload)),A.messaging.subscribe(ZY.REORDER,async(w)=>QD6(Q,w.payload)),A.messaging.subscribe(ZY.LIST,async(w)=>wD6(A,Q,w.payload)),A.messaging.subscribe(ZY.REPORT_SUCCESS,async(w)=>$D6(Q,w.payload)),A.messaging.subscribe(ZY.REPORT_FAILURE,async(w)=>BD6(Q,w.payload)),A.messaging.subscribe(ZY.COMPLETED,async(w)=>{return await Q.publicationQueueService.complete(w.payload.entityType,w.payload.entityId),{success:!0}}),A.messaging.subscribe(ZY.FAILED,async(w)=>{return await Q.publicationQueueService.fail(w.payload.entityType,w.payload.entityId,w.payload.error),{success:!0}}),Q.logger.debug("Subscribed to publish messages")}function d36(A,Q){A.messaging.subscribe($O.REPORT_SUCCESS,async(w)=>XD6(Q,w.payload)),A.messaging.subscribe($O.REPORT_FAILURE,async(w)=>YD6(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function i36(A,Q){A.messaging.subscribe(Nv2.REGISTER,async(w)=>o36(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function n36(A,Q){let w=async($)=>s36(A,Q,$.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 r36(A,Q){let{entityType:w,provider:$,config:B}=Q;try{let X=B?_v2.safeParse(B):void 0;if(X&&!X.success)return A.logger.warn("Invalid publish provider config",{entityType:w,error:X.error.message}),{success:!1};if($)A.providerRegistry.register(w,$,X?.data),A.logger.info(`Registered provider for entity type: ${w}`,{providerName:$.name,executionMode:A.providerRegistry.getExecutionMode(w)});return{success:!0}}catch(X){let Y=lA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function o36(A,Q){let w=Ab0.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 s36(A,Q,w){try{if(Q.publishAssetRegistry.list(w.entityType).length===0)return{success:!0};let $=w.entity??await A.entityService.getEntity({entityType:w.entityType,id:w.entityId});if(!a36($))return{success:!0};return await Q.publishAssetPreflight.ensureForEntity($),{success:!0}}catch($){return Q.logger.warn("Failed to run publish asset preflight for entity event",{entityType:w.entityType,entityId:w.entityId,error:lA($)}),{success:!1}}}function a36(A){if(!A)return!1;let Q=Lv2.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function t36(A,Q,w){let{entityType:$,entityId:B}=w;try{let X=w.authContext??y_;A.permissions.assertEntityActionAllowed($,"publish",X);let Y=await Q.publicationQueueService.enqueue($,B,X);return await A.messaging.send({type:ZY.QUEUED,payload:{entityType:$,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:$,position:Y.position}),{success:!0}}catch(X){let Y=lA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function e36(A,Q,w){let{entityType:$,entityId:B}=w,X=w.authContext??y_;try{if(A.permissions.assertEntityActionAllowed($,"publish",X),!Q.providerRegistry.has($))return Q.scheduler.failPublish($,B,`No publish provider registered for ${$}`),{success:!1};let Y=await Q.publishExecutor.publish({entityType:$,id:B});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: ${B}`,{entityType:$}),{success:!0}}catch(Y){let Z=lA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function AD6(A,Q){let{entityType:w,entityId:$}=Q;try{return await A.publicationQueueService.remove(w,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:w}),{success:!0}}catch(B){let X=lA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function QD6(A,Q){let{entityType:w,entityId:$,position:B}=Q;try{return await A.publicationQueueService.reorder(w,$,B),A.logger.debug(`Entity reordered: ${$}`,{entityType:w,newPosition:B}),{success:!0}}catch(X){let Y=lA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function wD6(A,Q,w){let{entityType:$}=w;try{let B=await Q.queueManager.list($);return await A.messaging.send({type:ZY.LIST_RESPONSE,payload:{entityType:$,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=lA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function $D6(A,Q){let{entityType:w,entityId:$,result:B}=Q;return A.scheduler.completePublish(w,$,B),A.logger.info(`Publish reported success: ${$}`,{entityType:w}),{success:!0}}async function BD6(A,Q){let{entityType:w,entityId:$,error:B}=Q;A.scheduler.failPublish(w,$,B);let X=A.retryTracker.getRetryInfo($);return A.logger.info(`Publish reported failure: ${$}`,{entityType:w,error:B,retryCount:X?.retryCount}),{success:!0}}async function XD6(A,Q){let{entityType:w,entityId:$}=Q;return A.scheduler.completeGeneration(w,$),A.logger.info("Generation completed",{entityType:w,entityId:$}),{success:!0}}async function YD6(A,Q){let{entityType:w,error:$}=Q;return A.scheduler.failGeneration(w,$),A.logger.warn("Generation failed",{entityType:w,error:$}),{success:!0}}async function gv2(A,Q,w,$){try{if($.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($.maxUnpublishedDrafts!==void 0){let B=await A.listEntities({entityType:w,options:{filter:{metadata:{status:"draft"}},limit:$.maxUnpublishedDrafts+1}});if(B.length>=$.maxUnpublishedDrafts)return{shouldGenerate:!1,reason:`Max unpublished drafts reached (${B.length}/${$.maxUnpublishedDrafts})`}}if($.minSourceEntities!==void 0&&$.sourceEntityType){let B=await A.listEntities({entityType:$.sourceEntityType,options:{publishedOnly:!0,limit:$.minSourceEntities}});if(B.length<$.minSourceEntities)return{shouldGenerate:!1,reason:`Not enough source entities (${B.length}/${$.minSourceEntities} ${$.sourceEntityType})`}}return{shouldGenerate:!0}}catch(B){return Q.error("Failed to check generation conditions",{entityType:w,error:lA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${lA(B)}`}}}function yv2(A){let{context:Q,config:w,queueManager:$,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,W=ZD6(Q);return MF.createFresh({queueManager:$,providerRegistry:B,retryTracker:X,logger:Z,backend:new vR({onOverlapSkipped:(K)=>{Z.debug("Skipping overlapping content scheduler cycle",{jobKey:K})},onCallbackError:(K,U)=>{Z.error("Unhandled content scheduler callback error",{jobKey:K,error:U})}}),...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:W,publishExecutor:Y,onCheckGenerationConditions:(K,U)=>gv2(Q.entityService,Z,K,U)})}function ZD6(A){return{send:async(B)=>{return A.messaging.send({type:B.type,payload:B.payload,...B.target!==void 0?{target:B.target}:{},...B.metadata!==void 0?{metadata:B.metadata}:{},...B.broadcast!==void 0?{broadcast:B.broadcast}:{}})},subscribe:()=>()=>{},unsubscribe:()=>{}}}b0();b0();var HD6=H.enum(["draft","queued","published","failed"]),WD6=H.object({entityId:H.string(),entityType:H.string(),title:H.string(),position:H.number().int().positive(),queuedAt:H.string(),destination:H.string(),scheduledFor:H.string().optional()}),KD6=H.object({id:H.string(),label:H.string(),target:H.string(),status:H.enum(["pending","processing"])}),UD6=H.object({entityId:H.string(),entityType:H.string(),title:H.string(),error:H.string(),retryCount:H.number().int().nonnegative()}),GD6=H.object({summary:H.object({draft:H.number().int().nonnegative(),queued:H.number().int().nonnegative(),generating:H.number().int().nonnegative(),failed:H.number().int().nonnegative(),published:H.number().int().nonnegative(),needsOperator:H.number().int().nonnegative()}),queue:H.array(WD6),generating:H.array(KD6),failures:H.array(UD6),publishableEntityTypes:H.array(H.string())}),DD6=H.object({sourceEntityType:H.string(),sourceEntityId:H.string(),attachmentType:H.string().optional()});async function Bb0(A,Q,w,$){let B=Q.getRegisteredTypes().sort(),X=new Map,Y={draft:0,queued:0,generating:0,failed:0,published:0,needsOperator:0};for(let U of B){let G=await A.entityService.listEntities({entityType:U});for(let D of G){let z=HD6.safeParse(D.metadata.status);if(!z.success)continue;Y[z.data]+=1;let V=D.metadata.scheduledFor,I=D.metadata.error;X.set(Tv2(U,D.id),{entityId:D.id,entityType:U,title:zD6(D.id,D.metadata),status:z.data,...typeof V==="string"?{scheduledFor:V}:{},...typeof I==="string"?{error:I}:{}})}}let Z=[];for(let U of B){let G=Q.get(U).name;for(let D of await w.list(U)){let z=X.get(Tv2(U,D.entityId));if(!z)continue;Z.push({entityId:D.entityId,entityType:U,title:z.title,position:D.position,queuedAt:D.queuedAt,destination:G,...z.scheduledFor?{scheduledFor:z.scheduledFor}:{}})}}let W=await qD6(A);Y.generating=W.length;let K=Array.from(X.values()).filter((U)=>U.status==="failed").map((U)=>{let G=$.getRetryInfo(U.entityId);return{entityId:U.entityId,entityType:U.entityType,title:U.title,error:U.error??G?.lastError??"Publication failed",retryCount:G?.retryCount??0}}).sort((U,G)=>U.title.localeCompare(G.title));return Y.needsOperator=Y.draft+Y.failed,GD6.parse({summary:Y,queue:Z,generating:W,failures:K,publishableEntityTypes:B})}async function qD6(A){let Q=[];for(let w of await A.jobs.getActiveJobs()){if(w.source!=="content-pipeline")continue;if(w.status!=="pending"&&w.status!=="processing")continue;let $;try{$=JSON.parse(w.data)}catch{continue}let B=DD6.safeParse($);if(!B.success)continue;Q.push({id:w.id,label:B.data.attachmentType??w.type,target:`${B.data.sourceEntityType}/${B.data.sourceEntityId}`,status:w.status})}return Q}function Tv2(A,Q){return`${A}\x00${Q}`}function zD6(A,Q){for(let w of["title","subject","slug"]){let $=Q[w];if(typeof $==="string"&&$.length>0)return $}return A}async function Sv2(A,Q,w){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:async()=>({...await Bb0(A,w.providerRegistry,w.queueManager,w.retryTracker),...w.managementUrl?{managementUrl:w.managementUrl}:{}}),digestProvider:VD6}})}var JD6=H.object({summary:H.object({draft:H.number(),queued:H.number(),generating:H.number(),published:H.number(),failed:H.number(),needsOperator:H.number()})});function VD6(A){let{summary:Q}=JD6.parse(A),w=Q.queued+Q.generating,$=w===0?"idle":`${Q.queued} queued \xB7 ${Q.generating} generating`,B=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`;return{digest:[{label:"Pipeline",value:$,...w>0?{tone:"warn"}:{}},{label:"Awaiting review",value:B,...Q.needsOperator>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Q.needsOperator}}$A();b0();var FD6=H.object({workspaceUrl:H.string()}),ID6=H.object({confirmed:H.literal(!0),confirmationToken:H.string().min(1),contentHash:H.string().min(1),expiresAt:H.string().datetime()}),LD6=H.discriminatedUnion("type",[H.object({type:H.literal("queue"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("remove"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("retry"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1)}),H.object({type:H.literal("reorder"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1),position:H.number().int().positive()}),H.object({type:H.literal("publish"),entityType:H.string().trim().min(1),entityId:H.string().trim().min(1),confirmation:ID6.optional()})]);async function mv2(A,Q,w){let $=ed(A,Q,w.providerRegistry,w.publishExecutor),B={id:"publishing",pluginId:Q,label:"Publishing",rendererName:"PublishingWorkspace",entityTypes:w.providerRegistry.getRegisteredTypes(),dataProvider:()=>Bb0(A,w.providerRegistry,w.queueManager,w.retryTracker),actionHandler:async(Z,W)=>{let K=LD6.safeParse(Z);if(!K.success)throw Error("Invalid publishing workspace action");return ND6(A,w,$,K.data,W)}},X=await A.messaging.send({type:Ot,payload:B});if(!("success"in X)||!X.success)return;let Y=FD6.safeParse(X.data);return Y.success?Y.data.workspaceUrl:void 0}async function ND6(A,Q,w,$,B){if(!Q.providerRegistry.has($.entityType))throw Error(`No publish provider registered for ${$.entityType}`);let X=await A.entityService.getEntity({entityType:$.entityType,id:$.entityId});if(!X)throw Error(`Entity not found: ${$.entityType}:${$.entityId}`);if($.type==="publish"){let W=await w.handler({entityType:$.entityType,id:$.entityId,...$.confirmation??{}},B);if("success"in W&&W.success===!0)await Q.publicationQueueService.complete($.entityType,$.entityId),Q.retryTracker.clearRetries($.entityId);return W}let Y=$.type==="queue"||$.type==="retry"?"publish":"update";A.permissions.assertEntityActionAllowed($.entityType,Y,B);let Z=X.metadata.status;switch($.type){case"queue":if(Z!=="draft")throw Error("Only draft entities can be queued");return Q.publicationQueueService.enqueue($.entityType,$.entityId,{...B,authorization:"user"});case"remove":if(Z!=="queued")throw Error("Only queued entities can be removed from the queue");return await Q.publicationQueueService.remove($.entityType,$.entityId),{success:!0};case"retry":if(Z!=="failed")throw Error("Only failed publications can be retried");return await Q.publicationQueueService.enqueue($.entityType,$.entityId,{...B,authorization:"user"}),{success:!0};case"reorder":if(Z!=="queued")throw Error("Only queued entities can be reordered");return await Q.publicationQueueService.reorder($.entityType,$.entityId,$.position),{success:!0}}}var uv2={name:"@brains/content-pipeline",version:"0.2.0-alpha.181",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/scheduler":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class lUA extends Rw{pluginContext;queueManager;publicationQueueService;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",uv2,A,bv2)}async onRegister(A){this.pluginContext=A,this.queueManager=kF.createFresh(),this.publicationQueueService=new pUA(A,this.queueManager),this.providerRegistry=PF.createFresh(),this.retryTracker=jF.createFresh(),this.publishAssetRegistry=OF.createFresh(),this.publishAssetPreflight=new Qb0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new td({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=yv2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),Ev2(A,{queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await this.publicationQueueService.reconcile(this.providerRegistry.getRegisteredTypes());let Q=await mv2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,publicationQueueService:this.publicationQueueService,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor});await Sv2(A,this.id,{providerRegistry:this.providerRegistry,queueManager:this.queueManager,retryTracker:this.retryTracker,...Q?{managementUrl:Q}:{}}),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[wb0(this.pluginContext,this.id,this.queueManager,this.publicationQueueService),ed(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),$b0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getPublicationQueueService(){return this.publicationQueueService}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),kF.resetInstance(),PF.resetInstance(),jF.resetInstance(),OF.resetInstance()}}function dUA(A={}){return new lUA(A)}$A();b0();var cv2=H.object({accountId:H.string().describe("Cloudflare account ID"),apiToken:H.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:H.string().describe("Cloudflare Web Analytics site tag")}),iUA=H.object({cloudflare:cv2.optional()});$A();b0();var bD6=H.object({date:H.string().describe("Single date in YYYY-MM-DD format").optional(),days:H.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:H.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:H.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:H.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function kD6(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 pv2(A,Q,w){let $=[];if(!w)return $;return $.push(j$(A,"query",`Query website analytics from Cloudflare.
|
|
8004
8004
|
|
|
8005
8005
|
Date range options (use only one):
|
|
8006
8006
|
- No params: yesterday only
|
|
@@ -8138,7 +8138,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,bD6,
|
|
|
8138
8138
|
}
|
|
8139
8139
|
}
|
|
8140
8140
|
}
|
|
8141
|
-
`,{...this.baseVariables(A),limit:A.limit??20})).map(($)=>({country:$.dimensions.countryName,visits:$.sum.visits}))}}var rUA=7,PD6=10;function dv2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=pG0(),w=IZ1(rUA),$=Du(w),B=Du(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:B}),A.getTopPages({startDate:$,endDate:B,limit:PD6})]);return{days:rUA,startDate:$,endDate:B,pageviews:X.pageviews,visitors:X.visitors,topPages:Y}}catch(X){return{error:X instanceof Error?X.message:"Failed to fetch analytics",days:rUA}}}}var iv2={name:"@brains/analytics",version:"0.2.0-alpha.
|
|
8141
|
+
`,{...this.baseVariables(A),limit:A.limit??20})).map(($)=>({country:$.dimensions.countryName,visits:$.sum.visits}))}}var rUA=7,PD6=10;function dv2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=pG0(),w=IZ1(rUA),$=Du(w),B=Du(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:B}),A.getTopPages({startDate:$,endDate:B,limit:PD6})]);return{days:rUA,startDate:$,endDate:B,pageviews:X.pageviews,visitors:X.visitors,topPages:Y}}catch(X){return{error:X instanceof Error?X.message:"Failed to fetch analytics",days:rUA}}}}var iv2={name:"@brains/analytics",version:"0.2.0-alpha.181",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 nv2 extends Rw{cloudflareClient;constructor(A={}){super("analytics",iv2,A,iUA)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new nUA(this.config.cloudflare):void 0,A.insights.register("traffic-overview",dv2(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:lv2(Q)}})}async getTools(){return pv2(this.id,this.getContext(),this.cloudflareClient)}}function jD6(A={}){return new nv2(A)}var Xb0=jD6;$A();b0();$A();b0();import{join as gD6}from"path";R2();var rv2="note",OD6=new Set(["description","excerpt","summary","tagline","story"]);function fD6(A){if(A.endsWith("s"))return A;return fD(A)}function n$0(A){return A===rv2}function ov2(A,Q){let w=A===rv2?"Note":ib(A),$=Q?.label??w;return{label:$,pluralLabel:Q?.pluralName??fD6($)}}function d$0(A){return typeof A==="object"&&A!==null}function wE(A){if(!d$0(A))return;let Q=A.def;return d$0(Q)?Q:void 0}function sv2(A){let Q=wE(A)?.type;return typeof Q==="string"?Q:void 0}function xD6(A){return typeof A==="function"?A():A}function oUA(A,Q=!1,w){let $=sv2(A),B=wE(A);if($==="optional"||$==="nullable")return oUA(B?.innerType,!0,w);if($==="default")return oUA(B?.innerType,!0,xD6(B?.defaultValue));let X={inner:A,isOptional:Q};if(w!==void 0)X.defaultValue=w;return X}function RD6(A){let Q=wE(A)?.entries;if(!d$0(Q))return;let w=Object.values(Q);return w.every(($)=>typeof $==="string")?w:void 0}function vD6(A){let Q=wE(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function CD6(A){let Q=wE(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some((w)=>{return wE(w)?.format==="datetime"})}function hD6(A){return A==="imageId"||A.endsWith("ImageId")}function ED6(A){if(!d$0(A))return;let Q=A.shape;return d$0(Q)?Q:void 0}function i$0(A,Q){let{inner:w,isOptional:$,defaultValue:B}=oUA(Q),X=sv2(w),Y=B??vD6(w),Z={name:A,label:ib(A),widget:"string",...$&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(hD6(A))return{...Z,widget:"image"};if(CD6(w))return{...Z,widget:"datetime"};if(OD6.has(A))return{...Z,widget:"text"};return{...Z,widget:"string"}}case"number":return{...Z,widget:"number"};case"boolean":return{...Z,widget:"boolean"};case"enum":{let W=RD6(w);return{...Z,widget:"select",...W?{options:W}:{}}}case"array":{let W=wE(w)?.element,K=i$0("item",W);if(K.widget==="object"&&K.fields)return{...Z,widget:"list",fields:K.fields};return{...Z,widget:"list",field:{name:A,label:ib(A),widget:K.widget}}}case"object":{let W=Object.entries(ED6(w)??{}).map(([K,U])=>i$0(K,U));return{...Z,widget:"object",fields:W}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function av2(A){return`<!doctype html>
|
|
8142
8142
|
<html lang="en" data-climate="paper">
|
|
8143
8143
|
<head>
|
|
8144
8144
|
<meta charset="utf-8" />
|
|
@@ -8196,7 +8196,7 @@ ${Ql}
|
|
|
8196
8196
|
</html>`}var yD6=gD6(import.meta.dir,"..","dist","ui","cms-app.js"),TD6=H.object({entityType:H.string(),id:H.string(),frontmatter:H.record(H.string(),H.unknown()),body:H.string().optional(),baseContentHash:H.string().optional()}),SD6=H.object({entityType:H.string(),frontmatter:H.record(H.string(),H.unknown()),body:H.string().optional()}),mD6=H.object({id:H.string().trim().min(1),action:H.unknown()}),sUA={entityType:H.string(),body:H.string(),frontmatter:H.record(H.string(),H.unknown())},uD6=H.union([H.object({...sUA,variant:H.literal("rewrite").optional(),instruction:H.string().trim().min(1),selection:H.string().min(1).max(8000)}),H.object({...sUA,variant:H.literal("summarise"),targetField:H.string().trim().min(1),body:H.string().min(1)}),H.object({...sUA,variant:H.literal("tag-suggest"),targetField:H.string().trim().min(1),body:H.string().min(1)})]),tv2=H.object({suggestion:H.string()}),cD6=H.object({suggestions:H.array(H.string().trim().min(1)).max(12)}),pD6=H.object({selection:H.string().min(1).max(8000),instruction:H.string().trim().min(1).max(2000),agent:H.string().trim().min(1).max(253)}),lD6=H.looseObject({response:H.string()}),dD6=H.object({agents:H.array(H.object({id:H.string(),label:H.string()}))}),iD6="file",ev2=10485760,nD6=H.object({watchEnabled:H.boolean(),lastSync:H.string().nullable(),git:H.object({branch:H.string(),hasChanges:H.boolean(),ahead:H.number(),behind:H.number(),lastCommit:H.string().nullable(),remote:H.string().nullable()}).nullable()});function AC2(A){let{routePath:Q,getContext:w,resolveOperatorSession:$,getEntityDisplay:B,workspaceRegistry:X}=A,Y=`${Q}/assets/app.js`,Z=(K)=>`${Q}/api/${K}`,W=async(K)=>await $(K)?null:WQ({error:"Operator session required"},401);return[{path:Q,method:"GET",public:!0,handler:async(K)=>{if(!await $(K))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(Q)}`,"Cache-Control":"no-store"}});return new Response(av2({assetPath:Y,surfaces:Uj(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:Y,method:"GET",public:!0,handler:async()=>{let K=Bun.file(yD6);if(!await K.exists())return new Response("CMS editor UI asset not built",{status:404});return new Response(K,{headers:{"Content-Type":"text/javascript; charset=utf-8","Cache-Control":"no-cache"}})}},{path:Z("types"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return oD6(w(),B(),X)}},{path:Z("workspace"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return sD6(X,K)}},{path:Z("workspace"),method:"POST",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return aD6(X,K)}},{path:Z("schema"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return tD6(w(),K)}},{path:Z("entities"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return eD6(w(),K)}},{path:Z("entities"),method:"PUT",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return Aq6(w(),K)}},{path:Z("entities"),method:"POST",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return Qq6(w(),K)}},{path:Z("entities"),method:"DELETE",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return wq6(w(),K)}},{path:Z("upload"),method:"POST",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return Yq6(w(),K,Z("upload"))}},{path:Z("assist"),method:"POST",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return $q6(w(),K)}},{path:Z("agents"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return Bq6(w())}},{path:Z("ask-agent"),method:"POST",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return Xq6(w(),K)}},{path:Z("sync-status"),method:"GET",public:!0,handler:async(K)=>{let U=await W(K);if(U)return U;return rD6(w())}}]}async function rD6(A){let Q={directorySync:null,git:null},w=await A.messaging.send({type:"sync:status:request",payload:{}});if(!("success"in w)||!w.success)return WQ(Q);let $=nD6.safeParse(w.data);if(!$.success)return WQ(Q);return WQ({directorySync:{lastSync:$.data.lastSync,watching:$.data.watchEnabled},git:$.data.git})}async function oD6(A,Q,w){let $=new Map((await A.entityService.getEntityCounts()).map((X)=>[X.entityType,X.count])),B=A.entityService.getEntityTypes().flatMap((X)=>{if(!A.entities.getEffectiveFrontmatterSchema(X))return[];let Z=A.entities.getAdapter(X);return[{entityType:X,label:ov2(X,Q?.[X]).pluralLabel,isSingleton:Z?.isSingleton===!0,hasBody:Z?.hasBody!==!1,count:$.get(X)??0}]});return WQ({types:B,workspaces:w.listDescriptors()})}async function sD6(A,Q){let w=new URL(Q.url).searchParams.get("id");if(!w)return WQ({error:"id query parameter is required"},400);let $=A.get(w);if(!$)return WQ({error:`Unknown CMS workspace: ${w}`},404);try{return WQ({workspace:{id:$.id,rendererName:$.rendererName,data:await $.dataProvider()}})}catch(B){return WQ({error:B instanceof Error?B.message:"CMS workspace data provider failed"},502)}}async function aD6(A,Q){let w;try{w=mD6.parse(await Q.json())}catch{return WQ({error:"Invalid workspace action payload"},400)}let $=A.get(w.id);if(!$)return WQ({error:`Unknown CMS workspace: ${w.id}`},404);if(!$.actionHandler)return WQ({error:`CMS workspace ${w.id} does not provide actions`},405);let B={interfaceType:"cms",userId:"operator",userPermissionLevel:"anchor"};try{return WQ({result:await $.actionHandler(w.action,B)})}catch(X){return WQ({error:X instanceof Error?X.message:"CMS workspace action failed"},400)}}function tD6(A,Q){let w=new URL(Q.url).searchParams.get("type");if(!w)return WQ({error:"type query parameter is required"},400);let $=A.entities.getEffectiveFrontmatterSchema(w);if(!$)return WQ({error:`Unknown entity type: ${w}`},404);let B=A.entities.getAdapter(w),X=n$0(w),Y=X?[]:Object.entries($.shape).map(([Z,W])=>i$0(Z,W));return WQ({entityType:w,format:X?"raw":"frontmatter",isSingleton:B?.isSingleton===!0,hasBody:X||B?.hasBody!==!1,fields:Y})}async function eD6(A,Q){let w=new URL(Q.url).searchParams,$=w.get("type");if(!$)return WQ({error:"type query parameter is required"},400);if(!A.entities.getEffectiveFrontmatterSchema($))return WQ({error:`Unknown entity type: ${$}`},404);let B=w.get("id");if(B){let Y=await A.entityService.getEntity({entityType:$,id:B});if(!Y)return WQ({error:`Entity not found: ${B}`},404);let{frontmatter:Z,body:W}=aUA($,Y.content);return WQ({entity:{id:Y.id,entityType:Y.entityType,frontmatter:Z,body:W,contentHash:Y.contentHash,created:Y.created,updated:Y.updated}})}let X=await A.entityService.listEntities({entityType:$});return WQ({entities:X.map((Y)=>({id:Y.id,entityType:Y.entityType,frontmatter:aUA($,Y.content).frontmatter,updated:Y.updated}))})}async function Aq6(A,Q){let w;try{w=TD6.parse(await Q.json())}catch{return WQ({error:"Invalid update payload"},400)}let{entityType:$,id:B}=w,X=A.entities.getEffectiveFrontmatterSchema($);if(!X)return WQ({error:`Unknown entity type: ${$}`},404);let Y=QC2(A,$,w.body);if(Y)return Y;let Z=n$0($);if(Z&&Object.keys(w.frontmatter).length>0)return WQ({error:`Entity type ${$} is raw markdown without frontmatter`},400);let W=Z?{success:!0,data:{}}:X.safeParse(w.frontmatter);if(!W.success)return WQ({error:"Invalid frontmatter",issues:W.error.issues},400);let K=await A.entityService.getEntity({entityType:$,id:B});if(!K)return WQ({error:`Entity not found: ${B}`},404);if(w.baseContentHash!==void 0&&w.baseContentHash!==K.contentHash)return WQ({error:"This entry changed since it was opened \u2014 likely updated by "+"another writer (an agent, or a git import via directory-sync). Reload to review before saving again.",currentContentHash:K.contentHash},409);let U=w.body??aUA($,K.content).body,G=Z?U:Y7(U,W.data),D=A.entities.getAdapter($)?.fromMarkdown(G),z={...K,...D,id:K.id,entityType:K.entityType,content:G},V=await A.entityService.updateEntity({entity:z});return WQ({entityId:V.entityId,jobId:V.jobId,skipped:V.skipped})}async function Qq6(A,Q){let w;try{w=SD6.parse(await Q.json())}catch{return WQ({error:"Invalid create payload"},400)}let{entityType:$}=w,B=A.entities.getEffectiveFrontmatterSchema($);if(!B)return WQ({error:`Unknown entity type: ${$}`},404);let X=QC2(A,$,w.body);if(X)return X;let Y=n$0($);if(Y&&Object.keys(w.frontmatter).length>0)return WQ({error:`Entity type ${$} is raw markdown without frontmatter`},400);let Z=Y?{success:!0,data:{}}:B.safeParse(w.frontmatter);if(!Z.success)return WQ({error:"Invalid frontmatter",issues:Z.error.issues},400);let W=Y?w.body??"":Y7(w.body??"",Z.data),K=A.entities.getAdapter($)?.fromMarkdown(W),U=await A.entityService.createEntity({entity:{...K,entityType:$,content:W,metadata:K?.metadata??{}}});return WQ({entityId:U.entityId,jobId:U.jobId},201)}async function wq6(A,Q){let w=new URL(Q.url).searchParams,$=w.get("type"),B=w.get("id");if(!$||!B)return WQ({error:"type and id query parameters are required"},400);if(!await A.entityService.getEntity({entityType:$,id:B}))return WQ({error:`Entity not found: ${B}`},404);let Y=await A.entityService.deleteEntity({entityType:$,id:B});return WQ({deleted:Y})}async function $q6(A,Q){let w;try{w=uD6.parse(await Q.json())}catch{return WQ({error:"Invalid assist payload or selection length"},400)}let $=A.entities.getEffectiveFrontmatterSchema(w.entityType);if(!$)return WQ({error:`Unknown entity type: ${w.entityType}`},404);if(w.variant==="summarise"||w.variant==="tag-suggest"){let Y=$.shape[w.targetField];if(!Y)return WQ({error:`Unknown frontmatter field: ${w.targetField}`},400);let Z=i$0(w.targetField,Y);if(!(w.variant==="summarise"?Z.widget==="string"||Z.widget==="text":Z.widget==="list"&&Z.field?.widget==="string"))return WQ({error:`Field ${w.targetField} is incompatible with ${w.variant}`},400);let K=["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:G}=await A.ai.generateObject(["Summarise the body for the target frontmatter field.","Return only the field value in the suggestion field.",...K].join(`
|
|
8197
8197
|
`),tv2);return WQ({variant:w.variant,targetField:w.targetField,suggestion:G.suggestion})}let{object:U}=await A.ai.generateObject(["Suggest tags for the target frontmatter field.","Return concise tag strings in the suggestions field without duplicates.",...K].join(`
|
|
8198
8198
|
`),cD6);return WQ({variant:w.variant,targetField:w.targetField,suggestions:[...new Set(U.suggestions)]})}let B=["You are editing markdown for the CMS.","Rewrite only the selected text according to the instruction.","Return only replacement markdown in the suggestion field.","Do not include commentary, code fences, or unchanged surrounding body text.","",`Entity type: ${w.entityType}`,`Frontmatter JSON: ${JSON.stringify(w.frontmatter)}`,`Instruction: ${w.instruction}`,"","Selected markdown:",w.selection,"","Full body for context:",w.body].join(`
|
|
8199
|
-
`),{object:X}=await A.ai.generateObject(B,tv2);return WQ({suggestion:X.suggestion})}async function Bq6(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return WQ({agents:[]});let w=dD6.safeParse(Q.data);return WQ(w.success?w.data:{agents:[]})}async function Xq6(A,Q){let w;try{w=pD6.parse(await Q.json())}catch{return WQ({error:"Invalid agent ask payload or selection length"},400)}let $=await A.messaging.send({type:"a2a:call:request",payload:w});if(!("success"in $)||!$.success){let X="error"in $&&typeof $.error==="string"?$.error:"Agent call failed",Y=X.startsWith("No handler found");return WQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if($.data===void 0)return WQ({error:"Agent asking is unavailable"},503);let B=lD6.safeParse($.data);if(!B.success)return WQ({error:"Invalid response from agent"},502);return WQ({agentId:w.agent,response:B.data.response})}async function Yq6(A,Q,w){let $=Number(Q.headers.get("content-length"));if(Number.isFinite($)&&$>ev2)return WQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return WQ({error:"Invalid multipart upload"},400)}let X=B.get(iD6);if(!(X instanceof File))return WQ({error:"Missing upload file"},400);if(X.size>ev2)return WQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return WQ({error:`No handler accepts uploads of type ${X.type}`},415);let W=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),K=await Y.handler({upload:{kind:"upload",id:W.id}},{interfaceType:"cms",userId:"operator"});if(!K.success)return WQ({error:K.error},502);return WQ({entityId:K.data.entityId,jobId:K.data.jobId},201)}function QC2(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return WQ({error:`Entity type ${Q} does not have a body`},400);return null}function aUA(A,Q){if(n$0(A))return{frontmatter:{},body:Q};try{let w=DQ(Q,H.record(H.string(),H.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function WQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}b0();var Zq6=H.object({id:H.string().trim().min(1),pluginId:H.string().trim().min(1),label:H.string().trim().min(1),rendererName:H.literal("PublishingWorkspace"),entityTypes:H.array(H.string().trim().min(1)).default([]),dataProvider:H.custom((A)=>typeof A==="function",{message:"Expected CMS workspace data provider function"}),actionHandler:H.custom((A)=>typeof A==="function",{message:"Expected CMS workspace action handler function"}).optional()});class tUA{workspaces=new Map;register(A){let Q=Zq6.parse(A),w={id:Q.id,pluginId:Q.pluginId,label:Q.label,rendererName:Q.rendererName,entityTypes:Q.entityTypes,dataProvider:Q.dataProvider,...Q.actionHandler?{actionHandler:Q.actionHandler}:{}};return this.workspaces.set(w.id,w),w}get(A){return this.workspaces.get(A)}listDescriptors(){return Array.from(this.workspaces.values()).map(({id:A,pluginId:Q,label:w,rendererName:$,entityTypes:B})=>({id:A,pluginId:Q,label:w,rendererName:$,entityTypes:B}))}}var wC2={name:"@brains/cms",version:"0.2.0-alpha.
|
|
8199
|
+
`),{object:X}=await A.ai.generateObject(B,tv2);return WQ({suggestion:X.suggestion})}async function Bq6(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return WQ({agents:[]});let w=dD6.safeParse(Q.data);return WQ(w.success?w.data:{agents:[]})}async function Xq6(A,Q){let w;try{w=pD6.parse(await Q.json())}catch{return WQ({error:"Invalid agent ask payload or selection length"},400)}let $=await A.messaging.send({type:"a2a:call:request",payload:w});if(!("success"in $)||!$.success){let X="error"in $&&typeof $.error==="string"?$.error:"Agent call failed",Y=X.startsWith("No handler found");return WQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if($.data===void 0)return WQ({error:"Agent asking is unavailable"},503);let B=lD6.safeParse($.data);if(!B.success)return WQ({error:"Invalid response from agent"},502);return WQ({agentId:w.agent,response:B.data.response})}async function Yq6(A,Q,w){let $=Number(Q.headers.get("content-length"));if(Number.isFinite($)&&$>ev2)return WQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return WQ({error:"Invalid multipart upload"},400)}let X=B.get(iD6);if(!(X instanceof File))return WQ({error:"Missing upload file"},400);if(X.size>ev2)return WQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return WQ({error:`No handler accepts uploads of type ${X.type}`},415);let W=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),K=await Y.handler({upload:{kind:"upload",id:W.id}},{interfaceType:"cms",userId:"operator"});if(!K.success)return WQ({error:K.error},502);return WQ({entityId:K.data.entityId,jobId:K.data.jobId},201)}function QC2(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return WQ({error:`Entity type ${Q} does not have a body`},400);return null}function aUA(A,Q){if(n$0(A))return{frontmatter:{},body:Q};try{let w=DQ(Q,H.record(H.string(),H.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function WQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}b0();var Zq6=H.object({id:H.string().trim().min(1),pluginId:H.string().trim().min(1),label:H.string().trim().min(1),rendererName:H.literal("PublishingWorkspace"),entityTypes:H.array(H.string().trim().min(1)).default([]),dataProvider:H.custom((A)=>typeof A==="function",{message:"Expected CMS workspace data provider function"}),actionHandler:H.custom((A)=>typeof A==="function",{message:"Expected CMS workspace action handler function"}).optional()});class tUA{workspaces=new Map;register(A){let Q=Zq6.parse(A),w={id:Q.id,pluginId:Q.pluginId,label:Q.label,rendererName:Q.rendererName,entityTypes:Q.entityTypes,dataProvider:Q.dataProvider,...Q.actionHandler?{actionHandler:Q.actionHandler}:{}};return this.workspaces.set(w.id,w),w}get(A){return this.workspaces.get(A)}listDescriptors(){return Array.from(this.workspaces.values()).map(({id:A,pluginId:Q,label:w,rendererName:$,entityTypes:B})=>({id:A,pluginId:Q,label:w,rendererName:$,entityTypes:B}))}}var wC2={name:"@brains/cms",version:"0.2.0-alpha.181",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@codemirror/lang-markdown":"^6.5.0","@codemirror/language":"^6.12.4","@codemirror/state":"^6.7.1","@codemirror/view":"^6.43.6","@lezer/highlight":"^1.2.3","@tanstack/react-query":"^5.0.0",react:"^19.2.7","react-dom":"^19.2.7",streamdown:"^2.5.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};var Wq6=H.looseObject({label:H.string().optional(),pluralName:H.string().optional()}),Kq6=H.object({entityDisplay:H.record(H.string(),Wq6).optional(),routePath:H.string().default("/cms")});class eUA extends Rw{workspaceRegistry=new tUA;constructor(A={}){super("cms",wC2,A,Kq6)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"}),A.messaging.subscribe(Ot,async(Q)=>{try{let w=this.workspaceRegistry.register(Q.payload);return{success:!0,data:{workspaceUrl:`${this.config.routePath}#/workspace/${encodeURIComponent(w.id)}`}}}catch(w){return{success:!1,error:w instanceof Error?w.message:String(w)}}})}getWebRoutes(){return AC2({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:Uq6,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay,workspaceRegistry:this.workspaceRegistry})}}function $E(A={}){return new eUA(A)}async function Uq6(A){return Boolean(await pX()?.getOperatorSession(A))}$A();b0();$A();b0();var Yb0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],Gq6=new Set(Yb0),Dq6=H.enum(["public","trusted","anchor"]);function AGA(A){return Gq6.has(A)}var $C2=H.object({label:H.string(),value:H.string(),tone:H.enum(["plain","good","warn"]).optional()}),BC2=H.object({id:H.string(),pluginId:H.string(),title:H.string(),description:H.string().optional(),group:H.string().min(1),priority:H.number().default(50),section:H.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:H.string(),visibility:Dq6.default("public"),needsOperator:H.number().int().nonnegative().optional(),digest:H.array($C2).max(4).optional()});class Zb0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let w={...BC2.parse(A),dataProvider:A.dataProvider,...A.digestProvider?{digestProvider:A.digestProvider}:{},...A.component?{component:A.component}:{},...A.clientScript?{clientScript:A.clientScript}:{}},$=`${w.pluginId}:${w.id}`;this.widgets.set($,w),this.logger.debug("Dashboard widget registered",{key:$,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(($)=>!Q.section||$.section===Q.section).filter(($)=>w4.hasPermission(w,$.visibility)).sort(($,B)=>$.priority-B.priority)}get size(){return this.widgets.size}}class Hb0{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}}),$=await Promise.allSettled(w.map(async(B)=>{let X=await B.dataProvider(),{dataProvider:Y,digestProvider:Z,component:W,clientScript:K,visibility:U="public",...G}=B;return{key:`${B.pluginId}:${B.id}`,widget:{...G,visibility:U,...this.deriveLiveDigest(B,X)},data:X}}));for(let B=0;B<$.length;B++){let X=$[B],Y=w[B];if(!X||!Y)continue;if(X.status==="fulfilled")Q[X.value.key]={widget:X.value.widget,data:X.value.data};else this.logger.error("Widget data provider failed",{widgetId:Y.id,pluginId:Y.pluginId,error:lA(X.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:lA(w)}),{}}}async fetch(A,Q,w){return await this.getDashboardData()}}import{render as uq6}from"preact-render-to-string";var XC2=`* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8200
8200
|
html, body { min-height: 100%; max-width: 100%; }
|
|
8201
8201
|
body {
|
|
8202
8202
|
font-family: var(--console-ui);
|
|
@@ -10077,7 +10077,7 @@ ${YC2}`;import{jsxDEV as BE,Fragment as HC2}from"preact/jsx-dev-runtime";functio
|
|
|
10077
10077
|
activate(resolveId(window.location.hash), false);
|
|
10078
10078
|
});
|
|
10079
10079
|
})();`;function rq6({hiddenWidgetCount:A,loginUrl:Q}){return LA("section",{class:"card operator-gate",children:[LA("div",{children:[LA("div",{class:"card-title",children:"Operator access"},void 0,!1,void 0,this),LA("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),LA("a",{class:"operator-gate-link",href:Q,children:"Sign in"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function oq6({dashboardPath:A,surfaces:Q,operatorAccess:w}){let $=w?.isOperator?w.logoutUrl:w?.loginUrl??"/login",B=w?.isOperator?"Operator":"Visitor",X=w?.isOperator?"Sign out":"Sign in";return LA("header",{class:"console-strip","aria-label":"Operator surfaces",children:[LA("a",{class:"console-mark",href:A,"aria-label":"Dashboard home",children:[LA("span",{class:"pulse"},void 0,!1,void 0,this),LA("span",{children:["Brain"," ",LA("span",{class:"console-mark-long",children:["\xB7 ",LA("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),LA("nav",{class:"surface-nav","aria-label":"Console surfaces",children:Q.map((Y)=>LA("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),LA("button",{class:"command-chip",type:"button","aria-label":"Search or jump",children:[LA("span",{class:"command-chip-hint",children:"Search or jump\u2026"},void 0,!1,void 0,this),LA("kbd",{children:"\u2318K"},void 0,!1,void 0,this),LA("span",{class:"command-chip-icon","aria-hidden":"true",children:"\u2315"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("button",{id:"climateToggle",class:"climate-chip",type:"button","aria-label":"Toggle climate",children:"\u25D0"},void 0,!1,void 0,this),LA("a",{class:w?.isOperator?"session-chip":"session-chip is-visitor",href:$,"aria-label":`${B} \xB7 ${X}`,children:[LA("span",{children:B},void 0,!1,void 0,this),LA("strong",{children:X},void 0,!1,void 0,this),LA("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 sq6({tabs:A}){return LA("nav",{class:"dashboard-tabs","aria-label":"Dashboard sections",role:"tablist",children:[LA("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)=>LA("a",{class:"dashboard-tab",href:`#${Q.id}`,role:"tab","aria-selected":"false","data-dashboard-tab-link":Q.id,children:[LA("span",{children:Q.label},void 0,!1,void 0,this),Q.needsOperator>0?LA("span",{class:"tab-badge tab-badge--needs",children:Q.needsOperator},void 0,!1,void 0,this):Q.widgetCount>0?LA("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 BGA(A){return A.indexStatus?.ready??A.indexReady??A.appInfo.embeddings>0}function aq6({input:A}){let Q=BGA(A),w=A.activityLog?.[0],$=A.appInfo.entityCounts.length,B=A.appInfo.interactions.map((G)=>G.id).slice(0,3).join(" / "),X=A.indexStatus?.embeddedEntities??A.appInfo.embeddings,Y=A.indexStatus?.embeddableEntities,Z=A.indexStatus?(A.indexStatus.activeEmbeddingJobs??0)+(A.indexStatus.missingEmbeddings??0)+(A.indexStatus.staleEmbeddings??0):0,W=Y===void 0?`${X}`:`${X}/${Y}`,K=Z>0?`${W} embedded \xB7 ${Z} queued`:`${W} embedded`,U=(A.jobProgress??[]).some((G)=>G.status==="processing"||G.status==="pending");return LA("section",{class:"overview-vitals","aria-label":"Runtime vitals",children:[LA("article",{class:"vital-card",children:[LA("span",{class:"vital-label",children:"Entities"},void 0,!1,void 0,this),LA("strong",{class:"vital-num",children:A.appInfo.entities},void 0,!1,void 0,this),LA("span",{class:"vital-sub",children:$===1?"1 type":`${$} types`},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("article",{class:"vital-card",children:[LA("span",{class:"vital-label",children:"Interactions"},void 0,!1,void 0,this),LA("strong",{class:"vital-num",children:A.appInfo.interactions.length},void 0,!1,void 0,this),LA("span",{class:"vital-sub",children:B||"no channels"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("article",{class:`vital-card ${Q?"vital-card--ok":"vital-card--warm"}`,children:[LA("span",{class:"vital-label",children:"Semantic index"},void 0,!1,void 0,this),LA("strong",{class:"vital-num vital-num--text",children:Q?"Ready":"Pending"},void 0,!1,void 0,this),LA("span",{class:"vital-sub",children:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("article",{class:`vital-card${U?" vital-card--warm":""}`,children:[LA("span",{class:"vital-label",children:"Last write"},void 0,!1,void 0,this),LA("strong",{class:"vital-num vital-num--text",children:w?XGA(w.timestamp):"\u2014"},void 0,!1,void 0,this),LA("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 tq6({input:A}){let{role:Q,purpose:w,values:$}=A.character;if(!Q&&!w&&$.length===0)return null;return LA("aside",{class:"card identity-capsule",children:[LA("div",{class:"card-head",children:[LA("span",{class:"card-title",children:"Identity"},void 0,!1,void 0,this),LA("span",{class:"card-from",children:"identity"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("div",{class:"identity-capsule-body",children:[Q&&LA("span",{class:"identity-role",children:["\u201C",Q,"\u201D"]},void 0,!0,void 0,this),$.length>0&&LA("span",{class:"values",children:$.map((B)=>LA("span",{class:"value",children:B},B,!1,void 0,this))},void 0,!1,void 0,this),w&&LA("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 eq6({cards:A}){if(A.length===0)return LA("section",{class:"card overview-empty-digest",children:[LA("div",{class:"card-head",children:LA("span",{class:"card-title",children:"Group digests"},void 0,!1,void 0,this)},void 0,!1,void 0,this),LA("p",{class:"muted",children:"No plugin groups are visible yet."},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return LA("section",{class:"digests","aria-label":"Group digests",children:A.map((Q)=>LA("a",{class:"card digest-card",href:Q.href,children:[LA("div",{class:"digest-head",children:[LA("h4",{children:Q.label},void 0,!1,void 0,this),LA("span",{class:"digest-go",children:"open \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("dl",{class:"digest-lines",children:Q.lines.map((w)=>LA("div",{class:`digest-line digest-line--${w.tone??"plain"}`,children:[LA("dt",{children:w.label},void 0,!1,void 0,this),LA("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 Az6(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 XGA(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 JC2={created:{glyph:"\uFF0B",tone:""},updated:{glyph:"\u2713",tone:" ledger-glyph--ok"},deleted:{glyph:"\u2212",tone:" ledger-glyph--warn"}};function Qz6({events:A}){return LA("section",{class:"card activity-ledger",children:[LA("div",{class:"card-head",children:[LA("span",{class:"card-title",children:"Activity"},void 0,!1,void 0,this),LA("span",{class:"card-from",children:"entity events"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0?LA("p",{class:"muted",children:"No entity activity has been observed this session."},void 0,!1,void 0,this):LA("ol",{class:"ledger",children:A.map((Q)=>LA("li",{class:"ledger-entry",children:[LA("time",{class:"ledger-time",dateTime:Q.timestamp,children:XGA(Q.timestamp)},void 0,!1,void 0,this),LA("span",{class:`ledger-glyph${JC2[Q.action].tone}`,"aria-hidden":"true",children:JC2[Q.action].glyph},void 0,!1,void 0,this),LA("span",{class:"ledger-what",children:[LA("b",{children:Q.entityType},void 0,!1,void 0,this)," ",Q.action," \u2014"," ",LA("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 wz6(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 $z6(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 Bz6({status:A}){let Q=wz6(A),w=A.ready?A.degraded?"Degraded":"Ready":"Indexing";return LA("div",{class:"index-gauge",style:`--index-percent: ${Q}%`,children:[LA("div",{class:"index-gauge-ring","aria-hidden":"true",children:LA("span",{children:[Q,"%"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),LA("div",{class:"index-gauge-copy",children:[LA("strong",{children:w},void 0,!1,void 0,this),LA("span",{children:$z6(A)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Xz6({input:A}){let Q=BGA(A);return LA("section",{class:"card semantic-index-card",children:[LA("div",{class:"card-head",children:[LA("span",{class:"card-title",children:"Semantic index"},void 0,!1,void 0,this),LA("span",{class:"card-from",children:"entity-service"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.indexStatus?LA(Bz6,{status:A.indexStatus},void 0,!1,void 0,this):LA("dl",{class:"kv",children:LA("div",{class:"kv-row",children:[LA("dt",{children:"Semantic index"},void 0,!1,void 0,this),LA("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 Yz6({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 LA("section",{class:"card content-sync-card",children:[LA("div",{class:"card-head",children:[LA("span",{class:"card-title",children:"Content sync"},void 0,!1,void 0,this),LA("span",{class:"card-from",children:"directory-sync"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("dl",{class:"kv",children:[LA("div",{class:"kv-row",children:[LA("dt",{children:"Path"},void 0,!1,void 0,this),LA("dd",{children:A.syncPath},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("div",{class:"kv-row",children:[LA("dt",{children:"Files"},void 0,!1,void 0,this),LA("dd",{children:w?`${Q} \xB7 ${w}`:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("div",{class:"kv-row",children:[LA("dt",{children:"Watch"},void 0,!1,void 0,this),LA("dd",{children:A.watchEnabled?"Watching":A.isInitialized?"Manual":"Not initialized"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("div",{class:"kv-row",children:[LA("dt",{children:"Last sync"},void 0,!1,void 0,this),LA("dd",{children:A.lastSync?`last sync ${Az6(A.lastSync)}`:"\u2014"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),LA("div",{class:"pipeline-mini","aria-label":"Write pipeline",children:[LA("span",{class:`pipeline-step${A.isInitialized?" is-done":""}`,children:"entity db"},void 0,!1,void 0,this),LA("span",{class:"pipeline-track"},void 0,!1,void 0,this),LA("span",{class:`pipeline-step${(A.totalFiles??0)>0?" is-done":""}`,children:"exported"},void 0,!1,void 0,this),LA("span",{class:"pipeline-track"},void 0,!1,void 0,this),LA("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 Zz6={pending:"run",processing:"run",completed:"done",failed:"fail"},Hz6={pending:"pending",processing:"running",completed:"done",failed:"failed"};function Wz6({jobs:A}){return LA("section",{class:"card widget-card--wide job-queue-card",children:[LA("div",{class:"card-head",children:[LA("span",{class:"card-title",children:"Job queue"},void 0,!1,void 0,this),LA("span",{class:"card-from",children:"job-queue"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0?LA("p",{class:"muted",children:"No recent job progress observed."},void 0,!1,void 0,this):LA("table",{class:"jobs",children:[LA("thead",{children:LA("tr",{children:[LA("th",{children:"Job"},void 0,!1,void 0,this),LA("th",{children:"Type"},void 0,!1,void 0,this),LA("th",{children:"Updated"},void 0,!1,void 0,this),LA("th",{children:"Status"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),LA("tbody",{children:A.map((Q)=>LA("tr",{children:[LA("td",{class:"mono",children:Q.id.slice(0,8)},void 0,!1,void 0,this),LA("td",{children:Q.jobType??Q.kind},void 0,!1,void 0,this),LA("td",{class:"mono",children:XGA(Q.updatedAt)},void 0,!1,void 0,this),LA("td",{children:LA("span",{class:`status-pill status-pill--${Zz6[Q.status]}`,children:[Hz6[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 Kz6({input:A,tabs:Q,showOperatorGate:w}){let $=lq6(Q,A),B=A.activityLog??[];return LA("section",{id:"overview",class:"dashboard-tab-panel is-active","data-dashboard-tab-panel":!0,"aria-labelledby":"dashboard-tab-overview",children:[LA(aq6,{input:A},void 0,!1,void 0,this),LA(tq6,{input:A},void 0,!1,void 0,this),w&&A.operatorAccess&&LA(rq6,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),LA("div",{class:"overview-grid",children:[LA(eq6,{cards:$},void 0,!1,void 0,this),LA(Qz6,{events:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Uz6({tab:A,input:Q,now:w}){let $=[...A.widgets.primary,...A.widgets.secondary],B=A.group==="system",X=A.group==="knowledge",Y=A.widgets.sidebar.length>0||B;return LA("section",{id:A.id,class:"dashboard-tab-panel","data-dashboard-tab-panel":!0,"data-dashboard-group":A.group,children:[LA("header",{class:"tab-section-head",children:LA("h2",{children:A.label},void 0,!1,void 0,this)},void 0,!1,void 0,this),LA("div",{class:`layout tab-layout${Y?"":" tab-layout--main-only"}`,children:[LA("div",{class:"main-column",children:[X&&LA(KC2,{total:Q.appInfo.entities,entityCounts:Q.appInfo.entityCounts},void 0,!1,void 0,this),B&&LA(VC2,{children:[LA(Xz6,{input:Q},void 0,!1,void 0,this),Q.directorySyncStatus&&LA(Yz6,{status:Q.directorySyncStatus},void 0,!1,void 0,this),LA(Wz6,{jobs:Q.jobProgress??[]},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.map((Z)=>LA(QGA,{widget:Z},`${Z.widget.pluginId}:${Z.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this),Y&&LA("div",{class:"sidebar-column",children:[B&&LA(VC2,{children:[LA(UC2,{endpoints:Q.appInfo.endpoints,baseUrl:Q.baseUrl},void 0,!1,void 0,this),LA(qC2,{appInfo:Q.appInfo,now:w},void 0,!1,void 0,this),LA(GC2,{interactions:Q.appInfo.interactions,baseUrl:Q.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.widgets.sidebar.map((Z)=>LA(QGA,{widget:Z},`${Z.widget.pluginId}:${Z.widget.id}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Gz6({input:A}){let Q=iq6(A.widgets),w=A.operatorAccess&&!A.operatorAccess.isOperator&&A.operatorAccess.hiddenWidgetCount>0,$=A.dashboardPath??"/dashboard",B=new Date;return LA("html",{lang:"en","data-climate":"instrument",children:[LA("head",{children:[LA("meta",{charSet:"utf-8"},void 0,!1,void 0,this),LA("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0, viewport-fit=cover"},void 0,!1,void 0,this),LA("title",{children:A.title},void 0,!1,void 0,this),LA("link",{rel:"preconnect",href:"https://fonts.googleapis.com"},void 0,!1,void 0,this),LA("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:"anonymous"},void 0,!1,void 0,this),LA("link",{href:oQ0,rel:"stylesheet"},void 0,!1,void 0,this),A.themeCSS!==void 0&&LA("style",{"data-dashboard-theme":!0,dangerouslySetInnerHTML:{__html:A.themeCSS}},void 0,!1,void 0,this),LA("style",{"data-dashboard-styles":!0,dangerouslySetInnerHTML:{__html:ZC2}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("body",{children:[LA(oq6,{dashboardPath:$,surfaces:A.surfaces??[{id:"dashboard",label:"Dashboard",href:$,isActive:!0}],operatorAccess:A.operatorAccess},void 0,!1,void 0,this),LA("main",{class:"console","data-component":"dashboard:dashboard",children:[LA("div",{class:"frame",children:[LA(WC2,{title:A.title,tagline:A.profile.description},void 0,!1,void 0,this),LA(sq6,{tabs:Q},void 0,!1,void 0,this),LA("div",{class:"canvas",children:LA("div",{class:"dashboard-tab-panels",children:[LA(Kz6,{input:A,tabs:Q,showOperatorGate:Boolean(w)},void 0,!1,void 0,this),Q.map((X)=>LA(Uz6,{tab:X,input:A,now:B},X.id,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA(zC2,{title:A.title,appInfo:A.appInfo,baseUrl:A.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("script",{dangerouslySetInnerHTML:{__html:cC}},void 0,!1,void 0,this),LA("script",{dangerouslySetInnerHTML:{__html:pC}},void 0,!1,void 0,this),LA("script",{dangerouslySetInnerHTML:{__html:nq6}},void 0,!1,void 0,this),A.widgetScripts.map((X,Y)=>LA("script",{dangerouslySetInnerHTML:{__html:X}},`widget-script:${Y}`,!1,void 0,this))]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function IC2(A){return`<!doctype html>
|
|
10080
|
-
${uq6(LA(Gz6,{input:A},void 0,!1,void 0,this))}`}function Dz6(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function LC2(A){let Q=A.query.trim().toLowerCase(),w=[];if(A.cmsPath!==void 0&&A.entities.length>0){let B=A.cmsPath;w.push({id:"entities",label:"Entities",items:A.entities.map((X)=>({id:`${X.entityType}/${X.id}`,title:X.title,sub:X.entityType,href:`${B}#/${encodeURIComponent(X.entityType)}/${encodeURIComponent(X.id)}`,tag:"edit in cms"}))})}let $=Ub0([...new Set(A.groups)]).map((B)=>({group:B,label:Ai(B)})).filter(({group:B,label:X})=>Q===""||X.toLowerCase().includes(Q)||B.toLowerCase().includes(Q)).map(({group:B,label:X})=>({id:`tab/${B}`,title:X,sub:"tab",href:`${A.dashboardPath}#${Dz6(B)}`,tag:"dashboard"}));if($.length>0)w.push({id:"tabs",label:"Dashboard",items:$});return w}function NC2(A,Q){let w={},$=new Set;for(let[B,X]of Object.entries(A)){let Y=Q?.get(X.widget.pluginId,X.widget.id);if(w[B]={...X,...Y?.component?{component:Y.component}:{}},Y?.clientScript)$.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from($)}}var _C2={name:"@brains/dashboard",version:"0.2.0-alpha.180",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 zz6=H.object({version:H.string().default("1.0.0"),routePath:H.string().default("/dashboard"),themeCSS:H.string().optional()}),Jz6=H.object({id:H.string(),pluginId:H.string(),title:H.string(),description:H.string().optional(),group:H.string().min(1),priority:H.number().default(50),section:H.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:H.string(),visibility:H.enum(["public","trusted","anchor"]).default("public"),needsOperator:H.number().int().nonnegative().optional(),digest:H.array(H.object({label:H.string(),value:H.string(),tone:H.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:H.custom().optional(),clientScript:H.string().optional(),dataProvider:H.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:H.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!AGA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Vz6=H.object({pluginId:H.string(),widgetId:H.string().optional()}),Fz6=H.object({entityType:H.string(),entityId:H.string(),conversationId:H.string().optional()}),Iz6=H.object({id:H.string(),type:H.enum(["job","batch"]),status:H.enum(["pending","processing","completed","failed"]),message:H.string().optional(),progress:H.object({current:H.number(),total:H.number(),percentage:H.number()}).optional(),jobDetails:H.object({jobType:H.string(),priority:H.number(),retryCount:H.number()}).optional()}),Lz6=H.object({success:H.literal(!0),data:H.object({syncPath:H.string(),isInitialized:H.boolean(),watchEnabled:H.boolean(),lastSync:H.string().datetime().optional(),totalFiles:H.number().int().nonnegative().optional(),byEntityType:H.record(H.string(),H.number().int().nonnegative()).optional()})});function Nz6(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 YGA extends Rw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",_C2,A,zz6)}recordActivity(A,Q){let w=Fz6.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=Iz6.safeParse(A);if(!Q.success)return;let w=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,$={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=[$,...this.jobProgress.filter((B)=>B.id!==$.id||B.kind!==$.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:lA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=Lz6.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:lA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new Zb0(this.logger),this.datasource=new Hb0(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=Jz6.parse(Q.payload),$=Nz6(w);return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:Yb0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:lA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Vz6.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:lA(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 pX()?.getOperatorSession(A),$=Boolean(w),B=$?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((v)=>w4.hasPermission(B,v.visibility)),Z=X.length-Y.length,[W,K,U,G]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),D=Q.identity.get(),z=Q.identity.getProfile(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),I={...K,endpoints:K.endpoints.filter((v)=>w4.hasPermission(B,v.visibility)),interactions:K.interactions.filter((v)=>w4.hasPermission(B,v.visibility))},F=z.name||K.model||"Brain Dashboard",_=new URL(A.url),k=`${_.pathname}${_.search}`,b=encodeURIComponent(k),f=NC2(W.widgets,this.widgetRegistry),R={title:F,baseUrl:V,widgets:f.widgets,widgetScripts:f.widgetScripts,dashboardPath:this.config.routePath,surfaces:Uj(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:z,appInfo:I,activityLog:this.activityLog,jobProgress:this.jobProgress,...G!==void 0&&{indexStatus:G},...U!==void 0&&{directorySyncStatus:U},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:$,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${b}`,logoutUrl:`/logout?return_to=${b}`}};return new Response(IC2(R),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await pX()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let w=this.ctx;if(!w)return Response.json({groups:[]});let $=new URL(A.url).searchParams.get("q")?.trim()??"",B=[];if($.length>=2)try{B=(await w.entityService.search({query:$,options:{limit:6}})).map((W)=>({entityType:W.entity.entityType,id:W.entity.id,title:W.entity.title??W.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=Uj(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:LC2({query:$,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function XO(A={}){return new YGA(A)}b0();var _z6=H.enum(["public","trusted","anchor"]),bz6=H.object({label:H.string(),value:H.string(),tone:H.enum(["plain","good","warn"]).optional()}),kz6=H.object({id:H.string(),pluginId:H.string(),title:H.string(),description:H.string().optional(),group:H.string().min(1),priority:H.number(),section:H.enum(["primary","secondary","sidebar"]),rendererName:H.string(),visibility:_z6,needsOperator:H.number().int().nonnegative().optional(),digest:H.array(bz6).max(4).optional(),component:H.custom().optional()}),Pz6=H.object({widget:kz6,data:H.unknown()}),Mz6=H.object({widgets:H.record(H.string(),Pz6)});$A();b0();$A();b0();import{h as lz6}from"preact";$A();wH();R2();b0();var Gb0=H.enum(["generating","draft","queued","published","failed"]),jz6=H.enum(["generating","draft","queued","published","failed"]),Db0=H.object({subject:H.string(),status:Gb0,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional()}),bC2=H.object({subject:H.string(),status:Gb0,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional(),error:H.string().optional()}),Oz6=H.object({subject:H.string(),status:jz6,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional(),error:H.string().optional()}),Qi=aQ.extend({entityType:H.literal("newsletter"),metadata:Oz6});$A();class kC2 extends QQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Qi,frontmatterSchema:Db0})}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 PC2=new kC2;$A();$A();R2();b0();var fz6=H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional(),baseUrl:H.string().optional(),status:H.enum(["generating","draft","queued","published","failed"]).optional()}),xz6=H.looseObject({entityType:H.string().optional(),query:fz6.optional()});function MC2(A){try{let{content:Q}=DQ(A.content,Db0);return Q}catch{return A.content}}class ZGA extends H7{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=xz6.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=MC2(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:uZ(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:$}=this.parseQuery(A),B=w.entityService;if($.id)return this.fetchSingleNewsletter($.id,Q,B);let X=$.status,Y=X?{filter:{metadata:{status:X}}}:void 0,{items:Z,pagination:W}=await this.fetchList($,B,Y);return Q.parse(this.buildListResult(Z,W,$))}async fetchSingleNewsletter(A,Q,w){let $=await w.getEntity({entityType:this.config.entityType,id:A});if(!$)throw Error(`Newsletter not found: ${A}`);let B=await this.resolveNavigation($,w),X=[];if($.metadata.entityIds?.length){let W=$.metadata.sourceEntityType??"post";X=(await Promise.all($.metadata.entityIds.map(async(U)=>{let G=await w.getEntity({entityType:W,id:U});if(G){let D=G.metadata;return{id:U,title:D.title??U,url:`/${W}s/${D.slug??U}`}}return null}))).filter((U)=>U!==null)}let Y=MC2($),Z={id:$.id,subject:$.metadata.subject,status:$.metadata.status,content:Y,created:$.created,updated:$.updated,sentAt:$.metadata.sentAt,scheduledFor:$.metadata.scheduledFor,newsletter:$,prevNewsletter:B.prev?{id:B.prev.id,subject:B.prev.subject,url:B.prev.url}:null,nextNewsletter:B.next?{id:B.next.id,subject:B.next.subject,url:B.next.url}:null,sourceEntities:X.length>0?X:void 0};return Q.parse(Z)}}$A();R2();b0();var Rz6=H.object({prompt:H.string().optional().describe("AI generation prompt"),sourceEntityIds:H.array(H.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:H.enum(["post"]).optional().describe("Type of source entities"),content:H.string().optional().describe("Direct content (skip AI)"),subject:H.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:H.boolean().optional().describe("Create as queued (true) or draft (false)")});class HGA extends pY{constructor(A,Q){super(A,Q,{schema:Rz6,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:$,sourceEntityIds:B,sourceEntityType:X}=A,{content:Y,subject:Z}=A;if(Y){if(!Z)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(B&&B.length>0){let D=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let V=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let F=`Create an engaging newsletter that highlights these blog posts:
|
|
10080
|
+
${uq6(LA(Gz6,{input:A},void 0,!1,void 0,this))}`}function Dz6(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function LC2(A){let Q=A.query.trim().toLowerCase(),w=[];if(A.cmsPath!==void 0&&A.entities.length>0){let B=A.cmsPath;w.push({id:"entities",label:"Entities",items:A.entities.map((X)=>({id:`${X.entityType}/${X.id}`,title:X.title,sub:X.entityType,href:`${B}#/${encodeURIComponent(X.entityType)}/${encodeURIComponent(X.id)}`,tag:"edit in cms"}))})}let $=Ub0([...new Set(A.groups)]).map((B)=>({group:B,label:Ai(B)})).filter(({group:B,label:X})=>Q===""||X.toLowerCase().includes(Q)||B.toLowerCase().includes(Q)).map(({group:B,label:X})=>({id:`tab/${B}`,title:X,sub:"tab",href:`${A.dashboardPath}#${Dz6(B)}`,tag:"dashboard"}));if($.length>0)w.push({id:"tabs",label:"Dashboard",items:$});return w}function NC2(A,Q){let w={},$=new Set;for(let[B,X]of Object.entries(A)){let Y=Q?.get(X.widget.pluginId,X.widget.id);if(w[B]={...X,...Y?.component?{component:Y.component}:{}},Y?.clientScript)$.add(Y.clientScript)}return{widgets:w,widgetScripts:Array.from($)}}var _C2={name:"@brains/dashboard",version:"0.2.0-alpha.181",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 zz6=H.object({version:H.string().default("1.0.0"),routePath:H.string().default("/dashboard"),themeCSS:H.string().optional()}),Jz6=H.object({id:H.string(),pluginId:H.string(),title:H.string(),description:H.string().optional(),group:H.string().min(1),priority:H.number().default(50),section:H.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:H.string(),visibility:H.enum(["public","trusted","anchor"]).default("public"),needsOperator:H.number().int().nonnegative().optional(),digest:H.array(H.object({label:H.string(),value:H.string(),tone:H.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:H.custom().optional(),clientScript:H.string().optional(),dataProvider:H.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:H.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!AGA(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),Vz6=H.object({pluginId:H.string(),widgetId:H.string().optional()}),Fz6=H.object({entityType:H.string(),entityId:H.string(),conversationId:H.string().optional()}),Iz6=H.object({id:H.string(),type:H.enum(["job","batch"]),status:H.enum(["pending","processing","completed","failed"]),message:H.string().optional(),progress:H.object({current:H.number(),total:H.number(),percentage:H.number()}).optional(),jobDetails:H.object({jobType:H.string(),priority:H.number(),retryCount:H.number()}).optional()}),Lz6=H.object({success:H.literal(!0),data:H.object({syncPath:H.string(),isInitialized:H.boolean(),watchEnabled:H.boolean(),lastSync:H.string().datetime().optional(),totalFiles:H.number().int().nonnegative().optional(),byEntityType:H.record(H.string(),H.number().int().nonnegative()).optional()})});function Nz6(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 YGA extends Rw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",_C2,A,zz6)}recordActivity(A,Q){let w=Fz6.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=Iz6.safeParse(A);if(!Q.success)return;let w=Q.data.progress?`${Q.data.progress.current}/${Q.data.progress.total}`:void 0,$={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=[$,...this.jobProgress.filter((B)=>B.id!==$.id||B.kind!==$.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:lA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=Lz6.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:lA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new Zb0(this.logger),this.datasource=new Hb0(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=Jz6.parse(Q.payload),$=Nz6(w);return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:Yb0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:lA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=Vz6.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:lA(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 pX()?.getOperatorSession(A),$=Boolean(w),B=$?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((v)=>w4.hasPermission(B,v.visibility)),Z=X.length-Y.length,[W,K,U,G]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),D=Q.identity.get(),z=Q.identity.getProfile(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),I={...K,endpoints:K.endpoints.filter((v)=>w4.hasPermission(B,v.visibility)),interactions:K.interactions.filter((v)=>w4.hasPermission(B,v.visibility))},F=z.name||K.model||"Brain Dashboard",_=new URL(A.url),k=`${_.pathname}${_.search}`,b=encodeURIComponent(k),f=NC2(W.widgets,this.widgetRegistry),R={title:F,baseUrl:V,widgets:f.widgets,widgetScripts:f.widgetScripts,dashboardPath:this.config.routePath,surfaces:Uj(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:D,profile:z,appInfo:I,activityLog:this.activityLog,jobProgress:this.jobProgress,...G!==void 0&&{indexStatus:G},...U!==void 0&&{directorySyncStatus:U},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:$,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${b}`,logoutUrl:`/logout?return_to=${b}`}};return new Response(IC2(R),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await pX()?.getOperatorSession(A))return Response.json({error:"Operator session required"},{status:401});let w=this.ctx;if(!w)return Response.json({groups:[]});let $=new URL(A.url).searchParams.get("q")?.trim()??"",B=[];if($.length>=2)try{B=(await w.entityService.search({query:$,options:{limit:6}})).map((W)=>({entityType:W.entity.entityType,id:W.entity.id,title:W.entity.title??W.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=Uj(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:LC2({query:$,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function XO(A={}){return new YGA(A)}b0();var _z6=H.enum(["public","trusted","anchor"]),bz6=H.object({label:H.string(),value:H.string(),tone:H.enum(["plain","good","warn"]).optional()}),kz6=H.object({id:H.string(),pluginId:H.string(),title:H.string(),description:H.string().optional(),group:H.string().min(1),priority:H.number(),section:H.enum(["primary","secondary","sidebar"]),rendererName:H.string(),visibility:_z6,needsOperator:H.number().int().nonnegative().optional(),digest:H.array(bz6).max(4).optional(),component:H.custom().optional()}),Pz6=H.object({widget:kz6,data:H.unknown()}),Mz6=H.object({widgets:H.record(H.string(),Pz6)});$A();b0();$A();b0();import{h as lz6}from"preact";$A();wH();R2();b0();var Gb0=H.enum(["generating","draft","queued","published","failed"]),jz6=H.enum(["generating","draft","queued","published","failed"]),Db0=H.object({subject:H.string(),status:Gb0,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional()}),bC2=H.object({subject:H.string(),status:Gb0,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional(),error:H.string().optional()}),Oz6=H.object({subject:H.string(),status:jz6,entityIds:H.array(H.string()).optional(),scheduledFor:H.string().datetime().optional(),sentAt:H.string().datetime().optional(),buttondownId:H.string().optional(),sourceEntityType:H.string().optional(),error:H.string().optional()}),Qi=aQ.extend({entityType:H.literal("newsletter"),metadata:Oz6});$A();class kC2 extends QQ{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:Qi,frontmatterSchema:Db0})}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 PC2=new kC2;$A();$A();R2();b0();var fz6=H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional(),baseUrl:H.string().optional(),status:H.enum(["generating","draft","queued","published","failed"]).optional()}),xz6=H.looseObject({entityType:H.string().optional(),query:fz6.optional()});function MC2(A){try{let{content:Q}=DQ(A.content,Db0);return Q}catch{return A.content}}class ZGA extends H7{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=xz6.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=MC2(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:uZ(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:$}=this.parseQuery(A),B=w.entityService;if($.id)return this.fetchSingleNewsletter($.id,Q,B);let X=$.status,Y=X?{filter:{metadata:{status:X}}}:void 0,{items:Z,pagination:W}=await this.fetchList($,B,Y);return Q.parse(this.buildListResult(Z,W,$))}async fetchSingleNewsletter(A,Q,w){let $=await w.getEntity({entityType:this.config.entityType,id:A});if(!$)throw Error(`Newsletter not found: ${A}`);let B=await this.resolveNavigation($,w),X=[];if($.metadata.entityIds?.length){let W=$.metadata.sourceEntityType??"post";X=(await Promise.all($.metadata.entityIds.map(async(U)=>{let G=await w.getEntity({entityType:W,id:U});if(G){let D=G.metadata;return{id:U,title:D.title??U,url:`/${W}s/${D.slug??U}`}}return null}))).filter((U)=>U!==null)}let Y=MC2($),Z={id:$.id,subject:$.metadata.subject,status:$.metadata.status,content:Y,created:$.created,updated:$.updated,sentAt:$.metadata.sentAt,scheduledFor:$.metadata.scheduledFor,newsletter:$,prevNewsletter:B.prev?{id:B.prev.id,subject:B.prev.subject,url:B.prev.url}:null,nextNewsletter:B.next?{id:B.next.id,subject:B.next.subject,url:B.next.url}:null,sourceEntities:X.length>0?X:void 0};return Q.parse(Z)}}$A();R2();b0();var Rz6=H.object({prompt:H.string().optional().describe("AI generation prompt"),sourceEntityIds:H.array(H.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:H.enum(["post"]).optional().describe("Type of source entities"),content:H.string().optional().describe("Direct content (skip AI)"),subject:H.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:H.boolean().optional().describe("Create as queued (true) or draft (false)")});class HGA extends pY{constructor(A,Q){super(A,Q,{schema:Rz6,jobTypeName:"newsletter:generation",entityType:"newsletter"})}async generate(A,Q){let w=A.addToQueue??!1,{prompt:$,sourceEntityIds:B,sourceEntityType:X}=A,{content:Y,subject:Z}=A;if(Y){if(!Z)this.failEarly("Subject is required when providing content directly");await this.reportProgress(Q,{progress:50,message:"Using provided content"})}else if(B&&B.length>0){let D=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let V=(await Promise.all(B.map((b)=>this.context.entityService.getEntity({entityType:D,id:b})))).filter((b)=>b!=null);if(V.length===0)this.failEarly(`No source entities found for IDs: ${B.join(", ")}`);await this.reportProgress(Q,{progress:30,message:`Generating newsletter from ${V.length} posts`});let F=`Create an engaging newsletter that highlights these blog posts:
|
|
10081
10081
|
|
|
10082
10082
|
${V.map((b)=>`## ${b.metadata.title}
|
|
10083
10083
|
|
|
@@ -10146,17 +10146,17 @@ Newsletter-specific guidelines:
|
|
|
10146
10146
|
- "Reply and let me know..."
|
|
10147
10147
|
- "Until next time..."
|
|
10148
10148
|
|
|
10149
|
-
The goal is to build a relationship with readers through valuable, authentic content.`});b0();$A();import{jsxDEV as vH,Fragment as yz6}from"preact/jsx-dev-runtime";var Cz6=H.enum(["generating","draft","queued","published","failed"]),hz6=H.object({id:H.string(),subject:H.string(),status:Cz6,excerpt:H.string(),created:H.string(),sentAt:H.string().optional(),url:H.string()}),Ez6=H.object({newsletters:H.array(hz6),totalCount:H.number(),pagination:sH0.nullable()}),gz6=({newsletters:A,totalCount:Q,pageTitle:w,pagination:$,baseUrl:B="/newsletters"})=>{let X=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return vH(yz6,{children:[vH(Nw,{title:X,description:Y},void 0,!1,void 0,this),vH("div",{className:"newsletter-list bg-theme",children:vH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[vH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?vH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):vH("div",{className:"space-y-4",children:A.map((Z)=>vH(W$,{href:Z.url,children:[vH(GX,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),vH(sX,{children:vH("div",{className:"flex items-center gap-3",children:[vH(SW,{status:Z.status},void 0,!1,void 0,this),vH("span",{className:"text-sm text-theme-muted",children:A9(Z.sentAt??Z.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z.excerpt&&vH("p",{className:"text-theme-muted line-clamp-2",children:Z.excerpt},void 0,!1,void 0,this)]},Z.id,!0,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&vH(F_,{currentPage:$.currentPage,totalPages:$.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)},OC2=$2({name:"newsletter-list",description:"Newsletter list page template",schema:Ez6,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:gz6}});b0();$A();import{jsxDEV as K5,Fragment as cz6}from"preact/jsx-dev-runtime";var Tz6=H.enum(["generating","draft","queued","published","failed"]),Sz6=H.object({id:H.string(),title:H.string(),url:H.string()}),fC2=H.object({id:H.string(),subject:H.string(),url:H.string()}),mz6=H.object({id:H.string(),subject:H.string(),status:Tz6,content:H.string(),created:H.string(),updated:H.string(),sentAt:H.string().optional(),scheduledFor:H.string().optional(),sourceEntities:H.array(Sz6).optional(),prevNewsletter:fC2.nullable().optional(),nextNewsletter:fC2.nullable().optional()}),uz6=({subject:A,status:Q,content:w,created:$,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:W})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],U=B??$,G=B?"Sent":"Created";return K5(cz6,{children:[K5(Nw,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),K5("section",{className:"newsletter-detail-section",children:K5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:K5("div",{className:"max-w-3xl mx-auto",children:[K5(QF,{items:K},void 0,!1,void 0,this),K5("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),K5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[K5(SW,{status:Q},void 0,!1,void 0,this),K5("span",{children:[G,": ",A9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&K5("span",{children:["Scheduled for: ",A9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&K5(W$,{variant:"compact",className:"mb-8",children:[K5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),K5("ul",{className:"space-y-1",children:Y.map((D)=>K5("li",{children:K5("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K5(L4,{markdown:w},void 0,!1,void 0,this),(Z??W)&&K5("nav",{className:"mt-12 pt-8 border-t border-theme",children:K5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?K5(W$,{href:Z.url,variant:"compact",children:[K5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),K5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Z.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):K5("div",{},void 0,!1,void 0,this),W&&K5(W$,{href:W.url,variant:"compact",className:"md:text-right",children:[K5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),K5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:W.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)},xC2=$2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:mz6,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:uz6}});var qb0={name:"@brains/newsletter",version:"0.2.0-alpha.
|
|
10149
|
+
The goal is to build a relationship with readers through valuable, authentic content.`});b0();$A();import{jsxDEV as vH,Fragment as yz6}from"preact/jsx-dev-runtime";var Cz6=H.enum(["generating","draft","queued","published","failed"]),hz6=H.object({id:H.string(),subject:H.string(),status:Cz6,excerpt:H.string(),created:H.string(),sentAt:H.string().optional(),url:H.string()}),Ez6=H.object({newsletters:H.array(hz6),totalCount:H.number(),pagination:sH0.nullable()}),gz6=({newsletters:A,totalCount:Q,pageTitle:w,pagination:$,baseUrl:B="/newsletters"})=>{let X=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return vH(yz6,{children:[vH(Nw,{title:X,description:Y},void 0,!1,void 0,this),vH("div",{className:"newsletter-list bg-theme",children:vH("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[vH("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?vH("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):vH("div",{className:"space-y-4",children:A.map((Z)=>vH(W$,{href:Z.url,children:[vH(GX,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),vH(sX,{children:vH("div",{className:"flex items-center gap-3",children:[vH(SW,{status:Z.status},void 0,!1,void 0,this),vH("span",{className:"text-sm text-theme-muted",children:A9(Z.sentAt??Z.created,{style:"long"})},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Z.excerpt&&vH("p",{className:"text-theme-muted line-clamp-2",children:Z.excerpt},void 0,!1,void 0,this)]},Z.id,!0,void 0,this))},void 0,!1,void 0,this),$&&$.totalPages>1&&vH(F_,{currentPage:$.currentPage,totalPages:$.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)},OC2=$2({name:"newsletter-list",description:"Newsletter list page template",schema:Ez6,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:gz6}});b0();$A();import{jsxDEV as K5,Fragment as cz6}from"preact/jsx-dev-runtime";var Tz6=H.enum(["generating","draft","queued","published","failed"]),Sz6=H.object({id:H.string(),title:H.string(),url:H.string()}),fC2=H.object({id:H.string(),subject:H.string(),url:H.string()}),mz6=H.object({id:H.string(),subject:H.string(),status:Tz6,content:H.string(),created:H.string(),updated:H.string(),sentAt:H.string().optional(),scheduledFor:H.string().optional(),sourceEntities:H.array(Sz6).optional(),prevNewsletter:fC2.nullable().optional(),nextNewsletter:fC2.nullable().optional()}),uz6=({subject:A,status:Q,content:w,created:$,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:W})=>{let K=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],U=B??$,G=B?"Sent":"Created";return K5(cz6,{children:[K5(Nw,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),K5("section",{className:"newsletter-detail-section",children:K5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:K5("div",{className:"max-w-3xl mx-auto",children:[K5(QF,{items:K},void 0,!1,void 0,this),K5("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),K5("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[K5(SW,{status:Q},void 0,!1,void 0,this),K5("span",{children:[G,": ",A9(U,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&K5("span",{children:["Scheduled for: ",A9(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&K5(W$,{variant:"compact",className:"mb-8",children:[K5("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),K5("ul",{className:"space-y-1",children:Y.map((D)=>K5("li",{children:K5("a",{href:D.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:D.title},void 0,!1,void 0,this)},D.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K5(L4,{markdown:w},void 0,!1,void 0,this),(Z??W)&&K5("nav",{className:"mt-12 pt-8 border-t border-theme",children:K5("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?K5(W$,{href:Z.url,variant:"compact",children:[K5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),K5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Z.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this):K5("div",{},void 0,!1,void 0,this),W&&K5(W$,{href:W.url,variant:"compact",className:"md:text-right",children:[K5("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),K5("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:W.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)},xC2=$2({name:"newsletter-detail",description:"Individual newsletter detail template",schema:mz6,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:uz6}});var qb0={name:"@brains/newsletter",version:"0.2.0-alpha.181",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 dz6=H.looseObject({}),iz6=H.object({prompt:H.string().optional(),content:H.string().optional()});class zb0 extends jw{entityType="newsletter";schema=Qi;adapter=PC2;constructor(A={}){super("newsletter",qb0,A,dz6)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new HGA(this.logger,A)}getTemplates(){return{generation:jC2,"newsletter-list":OC2,"newsletter-detail":xC2}}getDataSources(){return[new ZGA(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:()=>lz6(aXA,{variant:"inline"})}});return{success:!0}}),this.logger.debug("Newsletter plugin registered")}deferPublishRegistration(A){let Q={name:"internal",publish:async(w,$)=>{let B=typeof $.subject==="string"?$.subject:"",X=await A.messaging.send({type:"buttondown:send",payload:{entityId:"",subject:B,content:w}});return{id:!("noop"in X)&&X.data?.emailId?X.data.emailId:"internal"}}};A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"publish:register",payload:{entityType:"newsletter",provider:Q,config:{publishResultIdField:"buttondownId",publishTimestampField:"sentAt"}}}),{success:!0}})}subscribeToGenerateExecute(A){A.messaging.subscribe("generate:execute",async(Q)=>{if(Q.payload.entityType!=="newsletter")return{success:!0};try{let 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(($)=>$.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:lA(w)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let w=iz6.parse(Q),$=w.content?`Create an engaging newsletter based on this content:
|
|
10150
10150
|
|
|
10151
10151
|
${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function Jb0(A={}){return new zb0(A)}$A();b0();b0();var rz6="https://api.buttondown.email/v1",oz6=H.enum(["unactivated","regular","unsubscribed","already_subscribed"]),sz6=H.enum(["draft","about_to_send","scheduled","sent"]),WGA=H.looseObject({id:H.string(),email:H.string(),subscriber_type:oz6,metadata:H.record(H.string(),H.string()).optional()}),RC2=H.looseObject({id:H.string(),subject:H.string(),body:H.string().optional(),status:sz6,publish_date:H.string().optional()}),az6=H.looseObject({results:H.array(WGA),count:H.number()}),tz6=H.looseObject({detail:H.string().optional(),message:H.string().optional(),code:H.string().optional()});class KGA extends Error{status;code;constructor(A,Q,w){super(A);this.name="ButtondownApiError",this.status=Q,this.code=w}}class XE{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let w=`${rz6}${A}`;this.logger.debug("Buttondown API request",{endpoint:A,method:Q.method??"GET"});let $=await fetch(w,{...Q,headers:{Authorization:`Token ${this.config.apiKey}`,"Content-Type":"application/json",...Q.headers}});if(!$.ok){let B=await $.json().catch(()=>({})),X=tz6.safeParse(B),Y=X.success?X.data.detail??X.data.message??`HTTP ${$.status}`:`HTTP ${$.status}`,Z=X.success?X.data.code:void 0;throw this.logger.error("Buttondown API error",{endpoint:A,status:$.status,code:Z,error:Y}),new KGA(`Buttondown API error: ${Y}`,$.status,Z)}return $.json()}async createSubscriber(A){let Q={email_address:A.email,type:this.config.doubleOptIn?"unactivated":"regular"};if(A.name)Q.metadata={name:A.name};if(A.tags&&A.tags.length>0)Q.tags=A.tags;this.logger.info("Creating subscriber",{email:A.email});try{return WGA.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch(w){if(w instanceof KGA&&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 WGA.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(),$=w?`/subscribers?${w}`:"/subscribers";return az6.parse(await this.request($))}async createEmail(A){let Q={subject:A.subject,body:A.body,status:A.status??"draft"};if(A.publish_date)Q.publish_date=A.publish_date;return this.logger.info("Creating email",{subject:A.subject,status:A.status??"draft"}),RC2.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return RC2.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}$A();b0();var vC2=H.string().email({pattern:H.regexes.html5Email}),ez6=H.object({email:vC2.describe("Email address to subscribe"),name:H.string().optional().describe("Subscriber name (optional)"),tags:H.array(H.string()).optional().describe("Tags to apply to subscriber (optional)")}),AJ6=H.object({email:vC2.describe("Email address to unsubscribe")}),QJ6=H.object({type:H.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:H.number().optional().describe("Maximum number of results")});function CC2(A,Q,w){let $=new XE(Q,w);return[j$(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",ez6,async(B)=>{try{let X=await $.createSubscriber({email:B.email,...B.name&&{name:B.name},...B.tags&&{tags:B.tags}}),Y=X.subscriber_type==="already_subscribed";return Z7({subscriberId:X.id,email:X.email,status:X.subscriber_type,message:Y?"already_subscribed":"subscribed"},Y?`${B.email} is already subscribed`:`Subscribed ${B.email} successfully`)}catch(X){return TX(lA(X))}}),j$(A,"unsubscribe","Unsubscribe an email address from the newsletter.",AJ6,async(B)=>{try{return await $.unsubscribe(B.email),Z7({email:B.email},`Unsubscribed ${B.email} successfully`)}catch(X){return TX(lA(X))}}),j$(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",QJ6,async(B)=>{try{let X=await $.listSubscribers({...B.type&&{type:B.type},...B.limit&&{limit:B.limit}});return Z7({subscribers:X.results.map((Y)=>({id:Y.id,email:Y.email,status:Y.subscriber_type})),count:X.count},`Found ${X.count} subscribers`)}catch(X){return TX(lA(X))}})]}async function hC2(A,Q,w,$){if(A.entityType!=="post")return{success:!0,skipped:!0,reason:"Only post entity types trigger auto-send"};let B=await w.getEntity({entityType:"post",id:A.entityId});if(!B)return{success:!1,error:`Post ${A.entityId} not found`};$.info("Auto-sending newsletter for published post",{postId:B.id,title:B.metadata.title});try{let X=await Q.createEmail({subject:B.metadata.title,body:B.content,status:"about_to_send"});return $.info("Newsletter sent for post",{postId:B.id,emailId:X.id}),{success:!0,emailId:X.id}}catch(X){let Y=lA(X);return $.error("Failed to send newsletter for post",{postId:B.id,error:Y}),{success:!1,error:Y}}}var wJ6=H.object({apiKey:H.string().optional().describe("Buttondown API key"),doubleOptIn:H.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:H.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class Vb0 extends Rw{constructor(A={}){super("buttondown",qb0,A,wJ6)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new XE({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($){return this.logger.error("Buttondown send failed",{error:lA($)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{let $=await hC2(w.payload,Q,A.entityService,this.logger);if(!$.success)return this.logger.error("Buttondown auto-send failed",{entityId:w.payload.entityId,error:$.error}),{success:!1,error:$.error};return{success:!0}}),this.logger.info("Buttondown auto-send on publish enabled")}}async getTools(){if(!this.config.apiKey)return[];return CC2(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 Fb0(A={}){return new Vb0(A)}var $J6=H.object({apiKey:H.string().optional().describe("Buttondown API key"),doubleOptIn:H.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:H.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function EC2(A={}){let Q=$J6.safeParse(A);if(!Q.success)throw new NI("newsletter",Q.error.issues.map(($)=>({path:$.path.map(String).join("."),code:$.code,message:$.message})));let w=Q.data;return[Jb0({}),Fb0({...w.apiKey!==void 0&&{apiKey:w.apiKey},...w.doubleOptIn!==void 0&&{doubleOptIn:w.doubleOptIn},...w.autoSendOnPublish!==void 0&&{autoSendOnPublish:w.autoSendOnPublish}})]}$A();b0();import{existsSync as VJ6,mkdirSync as FJ6,writeFileSync as IJ6}from"fs";import{join as S_}from"path";b0();var UGA=H.object({baseFolder:H.string().default("_obsidian")});function GGA(A){return typeof A==="object"&&A!==null}function r$0(A){if(!GGA(A))return;let Q=A.def;return GGA(Q)?Q:void 0}function gC2(A){let Q=r$0(A)?.type;return typeof Q==="string"?Q:void 0}function BJ6(A){return typeof A==="function"?A():A}function XJ6(A){let Q=A,w=!0,$=void 0,B=!1,X=!0;while(X){X=!1;let Z=r$0(Q),W=gC2(Q);if(W==="optional"||W==="nullable"){w=!1,Q=Z?.innerType,X=!0;continue}if(W==="default")w=!1,B=!0,$=BJ6(Z?.defaultValue),Q=Z?.innerType,X=!0}let Y={inner:Q,required:w};if(B)Y.defaultValue=$;return Y}function YJ6(A){let w=r$0(A)?.entries;if(!GGA(w))return;let $=Object.values(w);if(!$.every((B)=>typeof B==="string"))return;return $}function ZJ6(A){let Q=r$0(A),w=Q?.values;if(Array.isArray(w))return w[0];return Q?.value}function yC2(A){let Q=gC2(A);if(Q==="enum"){let w=YJ6(A);return w?{type:"enum",enumValues:w}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:ZJ6(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=r$0(A);return yC2(w?.out)}return{type:"unknown"}}function TC2(A){let Q=[];for(let[w,$]of Object.entries(A.shape)){let{inner:B,required:X,defaultValue:Y}=XJ6($),Z=yC2(B),W={name:w,type:Z.type,required:X},K=Y!==void 0?Y:Z.defaultValue;if(K!==void 0)W.defaultValue=K;if(Z.enumValues)W.enumValues=Z.enumValues;Q.push(W)}return Q}function HJ6(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 SC2(A,Q,w=""){let $=["---"];for(let B of Q){let X=HJ6(B,A);if(X==="")$.push(`${B.name}:`);else $.push(`${B.name}: ${X}`)}if($.push("---"),$.push(""),w)$.push(w);else $.push("<!-- Write your content here -->"),$.push("");return $.join(`
|
|
10152
10152
|
`)}xm();var WJ6={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function KJ6(A){let Q={name:A.name,id:A.name,type:WJ6[A.type]};if(A.type==="enum"&&A.enumValues){let w={};A.enumValues.forEach(($,B)=>{w[String(B)]=$}),Q.options=w}return Q}function mC2(A,Q){let w={filesPaths:A,fields:Q.map(KJ6)};return`---
|
|
10153
10153
|
${fm(w)}---
|
|
10154
|
-
`}R2();xm();var UJ6=new Set(["entityType"]),GJ6={base:"Notes"},DJ6=new Set(["note"]);function qJ6(A){let Q=["file.name"];for(let w of A)if(!UJ6.has(w.name))Q.push(w.name);return Q}function zJ6(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function uC2(A,Q){let w=GJ6[A]??QPA(A),$=zJ6(Q),B=qJ6(Q),X=[{type:"table",name:`All ${w}`,order:B}];if($)X.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:B});let Z={filters:{and:[DJ6.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${w}.base`,content:fm(Z),hasStatus:$}}function cC2(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return fm(w)}function pC2(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$.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 fm(w)}var lC2={name:"@brains/obsidian-vault",version:"0.2.0-alpha.
|
|
10154
|
+
`}R2();xm();var UJ6=new Set(["entityType"]),GJ6={base:"Notes"},DJ6=new Set(["note"]);function qJ6(A){let Q=["file.name"];for(let w of A)if(!UJ6.has(w.name))Q.push(w.name);return Q}function zJ6(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function uC2(A,Q){let w=GJ6[A]??QPA(A),$=zJ6(Q),B=qJ6(Q),X=[{type:"table",name:`All ${w}`,order:B}];if($)X.push({type:"table",name:"By Status",groupBy:{property:"status",direction:"ASC"},order:B});let Z={filters:{and:[DJ6.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${w}.base`,content:fm(Z),hasStatus:$}}function cC2(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$}")`),w={filters:{and:[Q.length===1?Q[0]:{or:Q}]},views:[{type:"table",name:"Settings",order:["file.name","file.folder"]}]};return fm(w)}function pC2(A){if(A.length===0)return null;let Q=A.map(($)=>`file.inFolder("${$.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 fm(w)}var lC2={name:"@brains/obsidian-vault",version:"0.2.0-alpha.181",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 LJ6={mkdir:FJ6,writeFile:IJ6,existsFile:VJ6},NJ6=H.object({entityTypes:H.array(H.string()).optional().describe("Entity types to generate templates for (default: all)")});class DGA extends Rw{deps;constructor(A={},Q={}){super("obsidian-vault",lC2,A,UGA);this.deps={...LJ6,...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[j$(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",NJ6,async(Q)=>{return this.sync(A,Q.entityTypes)},{sideEffects:"external"})]}async sync(A,Q){try{let w=A.entityService.getEntityTypes(),$=Q?w.filter((F)=>Q.includes(F)):w,B=S_(A.dataDir,this.config.baseFolder),X=S_(B,"templates"),Y=S_(B,"fileClasses"),Z=S_(B,"bases");this.deps.mkdir(X,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(Z,{recursive:!0});let W=[],K=[],U=[],G=[],D=[],z=[];for(let F of $){let _=A.entities.getEffectiveFrontmatterSchema(F);if(!_){this.logger.debug(`Skipping ${F}: no frontmatter schema`),K.push(F);continue}let k=TC2(_),b=A.entities.getAdapter(F),f=b?.isSingleton===!0,R=mC2(F,k);if(this.deps.writeFile(S_(Y,`${F}.md`),R),U.push(F),f){D.push(F),this.logger.debug(`Generated fileClass (singleton): ${F}`);continue}let v=b?.getBodyTemplate()??"",M=SC2(F,k,v);this.deps.writeFile(S_(X,`${F}.md`),M),W.push(F);let y=uC2(F,k),S=S_(Z,y.filename);if(!this.deps.existsFile(S))this.deps.writeFile(S,y.content),G.push(F),this.logger.debug(`Generated base: ${y.filename}`);if(y.hasStatus)z.push({entityType:F,fields:k});this.logger.debug(`Generated template + fileClass: ${F}`)}let V=cC2(D);if(V){let F=S_(Z,"Settings.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,V),G.push("Settings"),this.logger.debug("Generated Settings.base")}let I=pC2(z);if(I){let F=S_(Z,"Pipeline.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,I),G.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${W.length} templates, ${U.length} fileClasses, ${G.length} bases (${K.length} skipped)`),Z7({generated:W,skipped:K,fileClasses:U,bases:G})}catch(w){return this.logger.error("Failed to sync",{error:w}),TX(w instanceof Error?w.message:"Unknown error")}}}function qGA(A={},Q){return new DGA(A,Q)}Se();$A();b0();var dC2={name:"@brains/notifications",version:"0.2.0-alpha.181",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/notification-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};Se();var bJ6=H.looseObject({defaultRecipient:nK0.optional()});class iC2 extends Rw{constructor(A={}){super("notifications",dC2,A,bJ6)}async onRegister(A){A.messaging.subscribe(RR,async(Q)=>{let w=Vr0.parse(Q.payload),$=w.recipient??this.config.defaultRecipient;if(!$)return A.logger.warn("Notification has no recipient"),{success:!1,error:"Notification recipient missing"};let B={to:$.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},X=await A.messaging.send({type:xF0,payload:B});if(!("success"in X)||!X.success||!X.data)return{success:!1,error:"Notification delivery failed"};let Y=X.data;if(Y.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:Y.id?{status:"sent",deliveryId:Y.id}:{status:"sent"}}})}}function Ib0(A={}){return new iC2(A)}g$();$A();$A();R2();z9();$A();b0();var Lb0=H.enum(["draft","active","archived"]),Nb0=H.enum(["anchor","trusted","public"]),_b0=H.enum(["agent-confirmed","manual"]),kJ6=H.enum(["draft","active","archived"]),PJ6=H.enum(["anchor","trusted","public"]),MJ6=H.enum(["agent-confirmed","manual"]),fF=H.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,H.string().min(1).optional()),m_=H.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,H.string().min(1).optional()),zGA=H.object({event:H.string().min(1),target:H.string().min(1),operatorAction:H.boolean().optional(),label:m_,description:m_,operatorDescription:m_}),JGA=H.object({id:H.string().min(1),title:H.string().min(1),prompt:m_,requiredDetails:H.array(H.string().min(1)).default([]),instructions:H.array(H.string().min(1)).default([]),doneWhen:H.array(H.string().min(1)).default([]),transitions:H.array(zGA).default([])}),bb0=H.object({purpose:H.string().min(1),operatingRules:H.array(H.string().min(1)).default([]),initialState:H.string().min(1),states:H.array(JGA).min(1),finalStates:H.array(H.string().min(1)).min(1),nextPrompts:H.array(H.string().min(1)).default([])}),wi=H.object({title:H.string(),status:Lb0.default("active"),audience:Nb0.default("anchor"),trigger:fF.optional(),lifecycle:fF.optional(),once:H.boolean().optional(),starterText:fF.optional(),description:fF.optional(),starterPrompt:fF.optional(),completionMode:_b0.default("agent-confirmed")}),nC2=H.object({title:H.string(),status:Lb0,audience:Nb0,trigger:fF.optional(),lifecycle:fF.optional(),once:H.boolean().optional(),starterText:fF.optional(),description:fF.optional(),starterPrompt:fF.optional(),completionMode:_b0}),jJ6=H.object({title:H.string(),status:kJ6,audience:PJ6,trigger:m_.optional(),lifecycle:m_.optional(),once:H.boolean().optional(),starterText:m_.optional(),description:m_.optional(),starterPrompt:m_.optional(),completionMode:MJ6}),$i=aQ.extend({entityType:H.literal("playbook"),metadata:jJ6});class kb0 extends R6{constructor(){super(bb0,{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:VGA,parser:FGA},{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:OJ6,parser:fJ6},{key:"label",label:"Label",type:"custom",formatter:VGA,parser:FGA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:VGA,parser:FGA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var o$0=new kb0;function VGA(A){return typeof A==="string"?A:""}function FGA(A){let Q=A.trim();return Q.length>0?Q:void 0}function OJ6(A){return typeof A==="boolean"?String(A):""}function fJ6(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function IGA(A){let Q=[],w=new Set,$=new Set;for(let B of A.states){if(w.has(B.id))$.add(B.id);w.add(B.id)}if(!w.has(A.initialState))Q.push(`Playbook initial state '${A.initialState}' is not defined.`);for(let B of $)Q.push(`Duplicate playbook state id '${B}'.`);for(let B of A.finalStates)if(!w.has(B))Q.push(`Playbook final state '${B}' is not defined.`);for(let B of A.states)for(let X of B.transitions)if(!w.has(X.target))Q.push(`Playbook transition '${B.id}' -> '${X.target}' targets an undefined state.`);for(let B of xJ6(A,w))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function Bi(A){let Q=IGA(A);if(!Q.valid)throw Error(Q.errors.join(`
|
|
10155
10155
|
`))}function xJ6(A,Q){if(!Q.has(A.initialState))return[];let w=new Set,$=[A.initialState];while($.length>0){let B=$.shift();if(!B||w.has(B))continue;w.add(B);let X=A.states.find((Y)=>Y.id===B);if(!X)continue;for(let Y of X.transitions)if(Q.has(Y.target)&&!w.has(Y.target))$.push(Y.target)}return A.states.map((B)=>B.id).filter((B)=>!w.has(B))}class Mb0 extends QQ{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:$i,frontmatterSchema:wi})}createPlaybookContent(A,Q){return this.buildMarkdown(o$0.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,wi),w=this.extractBody(A).trim(),$=RJ6(w)?vJ6(w):o$0.parse(w);return Bi($),{frontmatter:wi.parse(Q),body:$,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 YE=new Mb0;function RJ6(A){return/^##\s+Steps\s*$/im.test(A)}function vJ6(A){let Q=CJ6(LGA(A,"Steps"));if(Q.length===0)throw Error("Playbook must declare at least one step.");let w=Q.map(($,B)=>{let X=B===Q.length-1;if(!X&&$.doneWhen.length===0&&$.choices.length===0&&!$.skip)throw Error(`Playbook step '${$.title}' must declare Done when, Choices, or Skip.`);return{id:$.id,title:$.title,...$.prompt?{prompt:$.prompt}:{},requiredDetails:$.requiredDetails,instructions:$.instructions,doneWhen:$.doneWhen,transitions:[...$.doneWhen.length>0&&!X?[{event:"NEXT",target:Q[B+1]?.id??$.id}]:[],...$.choices.map((Y,Z)=>({event:`CHOICE_${Z+1}`,target:F1(Y.target),operatorAction:!0,label:Y.label})),...$.skip?[{event:"SKIP",target:F1($.skip.target),operatorAction:!0,label:$.skip.label}]:[]]}});return{purpose:hJ6(A,"Purpose"),operatingRules:rC2(A,"Operating Rules"),initialState:Q[0]?.id??"",states:w,finalStates:[Q.at(-1)?.id??""],nextPrompts:rC2(A,"Next Prompts")}}function CJ6(A){let Q=[],w;for(let $ of A.split(/\r?\n/)){let B=/^###\s+(.+?)\s*$/.exec($);if(B){w={title:B[1]??"",content:[]},Q.push(w);continue}w?.content.push($)}return Q.map(($)=>{let B=$.content.join(`
|
|
10156
10156
|
`);return{title:$.title,id:F1($.title),...oC2(B,"Say")?{prompt:oC2(B,"Say")}:{},requiredDetails:Pb0(B,"Required details"),instructions:Pb0(B,"To do"),doneWhen:Pb0(B,"Done when"),choices:EJ6(B,"Choices"),...sC2(B)?{skip:sC2(B)}:{}}})}function LGA(A,Q){let w=A.split(/\r?\n/),$=w.findIndex((X)=>X.trim().toLowerCase()===`## ${Q.toLowerCase()}`);if($===-1)return"";let B=[];for(let X of w.slice($+1)){if(/^##\s+/.test(X))break;B.push(X)}return B.join(`
|
|
10157
10157
|
`).trim()}function hJ6(A,Q){return LGA(A,Q).split(/\r?\n/).map((w)=>w.trim()).filter((w)=>w.length>0&&!w.startsWith("#")).join(`
|
|
10158
10158
|
`).trim()}function rC2(A,Q){return aC2(LGA(A,Q))}function oC2(A,Q){return new RegExp(`^${yJ6(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function Pb0(A,Q){let w=A.split(/\r?\n/),$=w.findIndex((X)=>X.trim().toLowerCase()===`${Q.toLowerCase()}:`);if($===-1)return[];let B=[];for(let X of w.slice($+1)){let Y=X.trim();if(Y.length===0)continue;if(/^[A-Za-z][A-Za-z ]+:/.test(Y)||/^#{1,6}\s+/.test(Y))break;B.push(X)}return aC2(B.join(`
|
|
10159
|
-
`))}function EJ6(A,Q){return Pb0(A,Q).map(gJ6)}function gJ6(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 sC2(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 aC2(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function yJ6(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}b0();var jb0=H.object({}).catchall(H.unknown()).transform(()=>({}));var Ob0={name:"@brains/playbooks",version:"0.2.0-alpha.
|
|
10159
|
+
`))}function EJ6(A,Q){return Pb0(A,Q).map(gJ6)}function gJ6(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 sC2(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 aC2(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function yJ6(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}b0();var jb0=H.object({}).catchall(H.unknown()).transform(()=>({}));var Ob0={name:"@brains/playbooks",version:"0.2.0-alpha.181",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 SJ6="playbook";class NGA extends jw{entityType=SJ6;schema=$i;adapter=YE;constructor(A={}){super("playbook",Ob0,A,jb0)}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 _GA(A={}){return new NGA(A)}g$();$A();b0();wH();he();function fb0(A,Q){return A.length===Q.length&&A.every((w,$)=>w===Q[$])}function bGA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function xb0(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&fb0(w.goal,A.doneWhen)&&w.met)}function mJ6(A,Q,w){return Z2.createMachine({id:A,initial:Q.initialState,states:Object.fromEntries(Q.states.map(($)=>{let B=Q.finalStates.includes($.id);return[$.id,{...B?{type:"final"}:{},...B?{}:{on:Object.fromEntries($.transitions.map((X)=>[X.event,{target:X.target,...bGA($,X.event)?{guard:()=>xb0($,w)}:{}}]))}}]}))})}function kGA(A,Q){let w=mJ6(Q.playbookId,A,Q);return Z2.createActor(w,{snapshot:w.resolveState({value:Q.currentState})})}function uJ6(A,Q,w){let $=kGA(Q,A);$.start();let B=$.getSnapshot().can({type:w});return $.stop(),B}function Xi(A,Q,w){return w.transitions.filter(($)=>uJ6(A,Q,$.event))}function s$0(A,Q,w){let $=new Set(Xi(A,Q,w).map((B)=>`${B.event}\x00${B.target}`));return w.transitions.filter((B)=>!$.has(`${B.event}\x00${B.target}`))}function tC2(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}function ZE(A,Q){return A.states.find((w)=>w.id===Q)}function HE(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function eC2(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find(($)=>$.stateId===Q.id&&fb0($.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}function Ah2(A,Q,w){let $=Xi(A,Q,w),B=$.filter((W)=>W.operatorAction!==!0),X=$.filter((W)=>W.operatorAction===!0),Y=s$0(A,Q,w),Z=A.gateVerdicts.find((W)=>W.stateId===w.id&&fb0(W.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((W)=>`- ${W}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((W)=>`- ${W}`):["- none"],"Goal status:",Z?`- ${Z.met?"Met":"Not yet met"}: ${Z.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...B.length>0?B.map((W)=>HE(W)):["- none"],"Available operator actions:",...X.length>0?X.map((W)=>HE(W)):["- none"],"Blocked events:",...Y.length>0?Y.map((W)=>HE(W)):["- none"]].join(`
|
|
10160
10160
|
`)}function Qh2(A){let{run:Q,body:w,state:$,playbookTitle:B}=A,X=Xi(Q,w,$),Y=X.filter((F)=>F.operatorAction!==!0),Z=X.filter((F)=>F.operatorAction===!0),W=s$0(Q,w,$),K=Y.map((F)=>HE(F)).join(`
|
|
10161
10161
|
`),U=Z.map((F)=>HE(F)).join(`
|
|
10162
10162
|
`),G=W.map((F)=>HE(F)).join(`
|
|
@@ -10230,9 +10230,9 @@ ${Object.entries(A).map(([w,$])=>`- ${w}: playbookId=${$.playbookId}, trigger=${
|
|
|
10230
10230
|
${A.guidance}`:B}}function Dh2(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:wV6(Q.data)}))}}function wV6(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function $V6(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 BV6(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function qh2(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function zh2(A,Q){let w=A.filter(Q),$=w.filter((B)=>B.status==="active"||B.status==="offered");return xGA($)??xGA(w)}function xGA(A){return[...A].sort((Q,w)=>(w.completedAt??w.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function XV6(A){return{async evaluate(Q){let w=Q.goal.join(`
|
|
10231
10231
|
`),$=await A.entityService.search({query:w,options:{limit:8,excludeTypes:["playbook"],visibilityScope:N5("anchor")}}),B=YV6(Q,$),{verdict:X}=await A.judge({instruction:"Decide whether the playbook goal is satisfied by the supplied current-run runtime evidence and KB excerpts. Current-run runtime evidence is authoritative for playbook completion; use KB excerpts as supporting context, not to override clear runtime evidence from this run. Return met=true only when the outcome clearly holds. If evidence is missing or ambiguous, return met=false with a short reason.",material:B,schema:aJ6});return X}}}function YV6(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,$)=>ZV6($+1,w)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map((w,$)=>HV6($+1,w)):["No relevant KB excerpts found."]].join(`
|
|
10232
10232
|
`)}function ZV6(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${Vh2(Q.data)}`}function HV6(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${Fh2(Q.entity.content,1200)}`,`Metadata: ${Vh2(Q.entity.metadata)}`].join(`
|
|
10233
|
-
`)}function Vh2(A){try{return Fh2(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function Fh2(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var WV6={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function vGA(A={},Q={}){return new RGA(A,Q)}g$();$A();b0();import{readFile as UV6}from"fs/promises";import{join as GV6}from"path";var Ih2={name:"@brains/rover-onboarding",version:"0.2.0-alpha.180",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 DV6=H.object({enabled:H.boolean().default(!1)}).strict(),Lh2=[{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 Nh2 extends Rw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",Ih2,A,DV6)}async onReady(A){if(!this.config.enabled)return;for(let Q of Lh2)await this.seedPlaybookIfMissing(A,Q);for(let Q of Lh2){if(!Q.starter)continue;await A.messaging.send({type:rg,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let $=await UV6(GV6(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:$}})}}function _h2(A={}){return new Nh2(A)}$A();b0();b0();$A();var CGA=H.enum(["new","planned","in-progress","done","declined"]),hGA=H.enum(["low","medium","high","critical"]),qV6=H.enum(["new","planned","in-progress","done","declined"]),zV6=H.enum(["low","medium","high","critical"]),a$0=H.object({title:H.string(),status:CGA,priority:hGA.default("medium"),requested:H.number().int().default(1),declinedReason:H.string().optional()}),JV6=H.object({title:H.string(),status:CGA,priority:hGA,requested:H.number().int(),slug:H.string()}),VV6=H.object({title:H.string(),status:qV6,priority:zV6,requested:H.number().int(),slug:H.string()}),t$0=aQ.extend({entityType:H.literal("wish"),metadata:VV6});b0();var EGA=H.object({}).catchall(H.unknown()).transform(()=>({}));$A();R2();class e$0 extends QQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:t$0,frontmatterSchema:a$0})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,a$0);return{frontmatter:a$0.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=F1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var bh2=new e$0;R2();R2();async function kh2(A,Q){let w=`${Q.title}: ${Q.description}`,B=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if(B&&B.score>=A.similarityThreshold)return B.entity;let X=F1(Q.title);return A.getEntity({entityType:"wish",id:X})}class hb0{logger;context;adapter=new e$0;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let $=A.title??A.prompt??"Untitled wish",B=A.content??A.prompt??"",X=await kh2({search:(K)=>this.context.entityService.search(K),getEntity:(K)=>this.context.entityService.getEntity(K),similarityThreshold:0.85},{title:$,description:B});if(X){let{frontmatter:K,description:U}=this.adapter.parseWishContent(X.content),G=K.requested+1,D=this.adapter.createWishContent({...K,requested:G},U);return await this.context.entityService.updateEntity({entity:{...X,content:D,metadata:{...X.metadata,requested:G}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:G}),{success:!0,entityId:X.id,existed:!0,requested:G}}let Y=F1($),Z=A.options?.priority??"medium",W=this.adapter.createWishContent({title:$,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:W,metadata:{title:$,status:"new",priority:Z,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:$}),{success:!0,entityId:Y,existed:!1,requested:1}}}var Ph2={critical:0,high:1,medium:2,low:3};function Mh2(A){A.sort((Q,w)=>{let $=w.metadata.requested-Q.metadata.requested;if($!==0)return $;return Ph2[Q.metadata.priority]-Ph2[w.metadata.priority]})}var jh2={name:"@brains/wishlist",version:"0.2.0-alpha.180",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 IV6=H.object({items:H.array(H.object({name:H.string(),count:H.number()}))}),LV6="wish";class Oh2 extends jw{entityType=LV6;schema=t$0;adapter=bh2;constructor(A={}){super("wishlist",jh2,A,EGA)}async interceptCreate(A,Q,w){let $=await new hb0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!$.success)return{kind:"handled",result:{success:!1,error:$.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...$.entityId?{entityId:$.entityId}:{},status:$.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({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:$}=IV6.parse(w),B=$[0];return{digest:B?[{label:"Top wish",value:`${B.name} \xB7 \xD7${B.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return Mh2(w),{items:w.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}}),{success:!0}});let Q=new hb0(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 NV6(A={}){return new Oh2(A)}var Eb0=NV6;$A();$A();b0();var A80=H.object({title:H.string(),target:H.string()}),fh2=H.object({title:H.string(),target:H.string(),slug:H.string().optional()}),Q80=aQ.extend({entityType:H.literal("prompt"),metadata:fh2});$A();R2();class gGA extends QQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:Q80,frontmatterSchema:A80})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,A80);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,A80),w=F1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var yGA=new gGA;var xh2={name:"@brains/prompt",version:"0.2.0-alpha.180",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 bV6="prompt";class TGA extends jw{entityType=bV6;schema=Q80;adapter=yGA;constructor(){super("prompt",xh2,{},yX)}getEntityTypeConfig(){return{embeddable:!1}}}function KE(){return new TGA}$A();b0();b0();class gb0{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 $=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!$.ok)throw Error(`Unsplash API error: ${$.status} ${$.statusText}`);let B=PV6.parse(await $.json());return{photos:B.results.map(MV6),total:B.total,totalPages:B.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var kV6=H.looseObject({id:H.string(),description:H.string().nullable(),alt_description:H.string().nullable(),urls:H.looseObject({raw:H.url(),full:H.url(),regular:H.url(),small:H.url(),thumb:H.url()}),links:H.looseObject({html:H.url(),download_location:H.url()}),user:H.looseObject({name:H.string(),links:H.looseObject({html:H.url()})}),width:H.number().int().nonnegative(),height:H.number().int().nonnegative()}),PV6=H.looseObject({total:H.number().int().nonnegative(),total_pages:H.number().int().nonnegative(),results:H.array(kV6)});function MV6(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}}b0();async function yb0(A,Q,w,$){let B=await A.getEntity({entityType:Q,id:w});if(!B)return!1;return await A.updateEntity({entity:{...B,metadata:{...B.metadata,coverImageId:$}}}),!0}var jV6={query:H.string().describe("Search terms for stock photos"),perPage:H.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:H.number().min(1).default(1).describe("Page number")},OV6={photoId:H.string().describe("Photo ID from search results"),downloadLocation:H.url().describe("Download tracking URL (required by provider ToS)"),photographerName:H.string().describe("Photographer name for attribution"),photographerUrl:H.url().describe("Photographer profile URL for attribution"),sourceUrl:H.url().describe("Photo page URL on provider"),imageUrl:H.url().describe("Image URL to download"),title:H.string().optional().describe("Image entity title"),alt:H.string().optional().describe("Alt text for the image"),targetEntityType:H.string().optional().describe("Entity type to set cover image on"),targetEntityId:H.string().optional().describe("Entity ID to set cover image on")},fV6=H.object({query:H.string(),perPage:H.number().min(1).max(30).default(10),page:H.number().min(1).default(1)}),xV6=H.object({photoId:H.string(),downloadLocation:H.url(),photographerName:H.string(),photographerUrl:H.url(),sourceUrl:H.url(),imageUrl:H.url(),title:H.string().optional(),alt:H.string().optional(),targetEntityType:H.string().optional(),targetEntityId:H.string().optional()});function Rh2(A,Q){return[RV6(A,Q),vV6(A,Q)]}function RV6(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:jV6,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let $=fV6.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos($.data.query,{page:$.data.page,perPage:$.data.perPage})}}catch(B){return{success:!1,error:B instanceof Error?B.message:"Search failed"}}}}}function vV6(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:OV6,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let $=xV6.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:W,imageUrl:K,title:U,alt:G,targetEntityType:D,targetEntityId:z}=$.data,V={photographerName:Y,photographerUrl:Z,sourceUrl:W},I=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(I[0]){let k={imageEntityId:I[0].id,alreadyExisted:!0,attribution:V};if(D&&z)k.coverSet=await yb0(Q.entityService,D,z,I[0].id);return{success:!0,data:k}}let F=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:W,imageUrl:K,...U!==void 0?{title:U}:{},...G!==void 0?{alt:G}:{},...D!==void 0?{targetEntityType:D}:{},...z!==void 0?{targetEntityId:z}:{}}}),_={imageEntityId:B,alreadyExisted:!1,attribution:V,jobId:F,status:"generating"};if(D&&z)_.coverSet=!1;return{success:!0,data:_}}}}$A();b0();rY();var CV6=H.object({photoId:H.string(),downloadLocation:H.url(),photographerName:H.string(),photographerUrl:H.url(),sourceUrl:H.url(),imageUrl:H.url(),title:H.string().optional(),alt:H.string().optional(),targetEntityType:H.string().optional(),targetEntityId:H.string().optional()});class SGA extends p6{deps;constructor(A,Q){super(A,{schema:CV6,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 $=await this.deps.fetchImage(A.imageUrl),B=A.title??`Stock photo ${A.photoId}`,X=nK.createImageEntity({dataUrl:$,title:B,alt:A.alt??B});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...X,metadata:{...X.metadata,sourceUrl:A.imageUrl}}}),Z={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(Z.coverSet=await yb0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!Z.coverSet)Z.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),Z}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}rY();var vh2={name:"@brains/stock-photo",version:"0.2.0-alpha.180",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 EV6=H.object({provider:H.enum(["unsplash"]).default("unsplash"),apiKey:H.string().optional().describe("Stock photo provider API key")});class mGA extends Rw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",vh2,A,EV6);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=Rh2(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??z3,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new SGA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??z3}))}createProvider(){return new gb0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function uGA(A={},Q={}){return new mGA(A,Q)}$A();b0();$A();$A();b0();var Ch2=H.enum(["ai","foundation","work"]),hh2=H.object({suffix:Ch2,title:H.string(),body:H.string(),linkLabel:H.string(),linkHref:H.string()}),w80=H.object({eyebrow:H.string(),headline:H.string(),cards:H.array(hh2).min(1)}),cGA=H.object({title:H.string(),slug:H.string(),status:H.enum(["draft","published"])}),gV6=H.object({title:H.string(),slug:H.string(),status:H.enum(["draft","published"])}),$80=aQ.extend({entityType:H.literal("ecosystem-section"),metadata:gV6});class Eh2 extends QQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:$80,frontmatterSchema:cGA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var pGA=new Eh2;b0();function yV6(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function lGA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function B80(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function Tb0(A){let Q=yV6(A),$=lGA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return w80.parse({eyebrow:lGA(Q,"Eyebrow"),headline:lGA(Q,"Headline"),cards:$.map((B)=>({suffix:B80(B,"Suffix"),title:B80(B,"Title"),body:B80(B,"Body"),linkLabel:B80(B,"Link Label"),linkHref:B80(B,"Link Href")}))})}function gh2(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(`
|
|
10233
|
+
`)}function Vh2(A){try{return Fh2(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function Fh2(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var WV6={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function vGA(A={},Q={}){return new RGA(A,Q)}g$();$A();b0();import{readFile as UV6}from"fs/promises";import{join as GV6}from"path";var Ih2={name:"@brains/rover-onboarding",version:"0.2.0-alpha.181",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 DV6=H.object({enabled:H.boolean().default(!1)}).strict(),Lh2=[{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 Nh2 extends Rw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",Ih2,A,DV6)}async onReady(A){if(!this.config.enabled)return;for(let Q of Lh2)await this.seedPlaybookIfMissing(A,Q);for(let Q of Lh2){if(!Q.starter)continue;await A.messaging.send({type:rg,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let $=await UV6(GV6(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:$}})}}function _h2(A={}){return new Nh2(A)}$A();b0();b0();$A();var CGA=H.enum(["new","planned","in-progress","done","declined"]),hGA=H.enum(["low","medium","high","critical"]),qV6=H.enum(["new","planned","in-progress","done","declined"]),zV6=H.enum(["low","medium","high","critical"]),a$0=H.object({title:H.string(),status:CGA,priority:hGA.default("medium"),requested:H.number().int().default(1),declinedReason:H.string().optional()}),JV6=H.object({title:H.string(),status:CGA,priority:hGA,requested:H.number().int(),slug:H.string()}),VV6=H.object({title:H.string(),status:qV6,priority:zV6,requested:H.number().int(),slug:H.string()}),t$0=aQ.extend({entityType:H.literal("wish"),metadata:VV6});b0();var EGA=H.object({}).catchall(H.unknown()).transform(()=>({}));$A();R2();class e$0 extends QQ{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:t$0,frontmatterSchema:a$0})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,a$0);return{frontmatter:a$0.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=F1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var bh2=new e$0;R2();R2();async function kh2(A,Q){let w=`${Q.title}: ${Q.description}`,B=(await A.search({query:w,options:{types:["wish"],limit:1}}))[0];if(B&&B.score>=A.similarityThreshold)return B.entity;let X=F1(Q.title);return A.getEntity({entityType:"wish",id:X})}class hb0{logger;context;adapter=new e$0;constructor(A,Q){this.logger=A,this.context=Q}async process(A,Q,w){let $=A.title??A.prompt??"Untitled wish",B=A.content??A.prompt??"",X=await kh2({search:(K)=>this.context.entityService.search(K),getEntity:(K)=>this.context.entityService.getEntity(K),similarityThreshold:0.85},{title:$,description:B});if(X){let{frontmatter:K,description:U}=this.adapter.parseWishContent(X.content),G=K.requested+1,D=this.adapter.createWishContent({...K,requested:G},U);return await this.context.entityService.updateEntity({entity:{...X,content:D,metadata:{...X.metadata,requested:G}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:G}),{success:!0,entityId:X.id,existed:!0,requested:G}}let Y=F1($),Z=A.options?.priority??"medium",W=this.adapter.createWishContent({title:$,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:W,metadata:{title:$,status:"new",priority:Z,requested:1,slug:Y}}}),this.logger.info("Created new wish",{id:Y,title:$}),{success:!0,entityId:Y,existed:!1,requested:1}}}var Ph2={critical:0,high:1,medium:2,low:3};function Mh2(A){A.sort((Q,w)=>{let $=w.metadata.requested-Q.metadata.requested;if($!==0)return $;return Ph2[Q.metadata.priority]-Ph2[w.metadata.priority]})}var jh2={name:"@brains/wishlist",version:"0.2.0-alpha.181",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 IV6=H.object({items:H.array(H.object({name:H.string(),count:H.number()}))}),LV6="wish";class Oh2 extends jw{entityType=LV6;schema=t$0;adapter=bh2;constructor(A={}){super("wishlist",jh2,A,EGA)}async interceptCreate(A,Q,w){let $=await new hb0(this.logger,w).process({...A.title?{title:A.title}:{},...A.prompt?{prompt:A.prompt}:{},...A.content?{content:A.content}:{}},`wish-create-${Date.now()}`,{});if(!$.success)return{kind:"handled",result:{success:!1,error:$.error??"Failed to create wish"}};return{kind:"handled",result:{success:!0,data:{...$.entityId?{entityId:$.entityId}:{},status:$.existed?"updated":"created"}}}}async onRegister(A){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({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:$}=IV6.parse(w),B=$[0];return{digest:B?[{label:"Top wish",value:`${B.name} \xB7 \xD7${B.count}`}]:[{label:"Wishes",value:"none yet"}]}},dataProvider:async()=>{let w=await A.entityService.listEntities({entityType:"wish",options:{limit:10}});return Mh2(w),{items:w.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}}),{success:!0}});let Q=new hb0(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 NV6(A={}){return new Oh2(A)}var Eb0=NV6;$A();$A();b0();var A80=H.object({title:H.string(),target:H.string()}),fh2=H.object({title:H.string(),target:H.string(),slug:H.string().optional()}),Q80=aQ.extend({entityType:H.literal("prompt"),metadata:fh2});$A();R2();class gGA extends QQ{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:Q80,frontmatterSchema:A80})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,A80);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,A80),w=F1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var yGA=new gGA;var xh2={name:"@brains/prompt",version:"0.2.0-alpha.181",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 bV6="prompt";class TGA extends jw{entityType=bV6;schema=Q80;adapter=yGA;constructor(){super("prompt",xh2,{},yX)}getEntityTypeConfig(){return{embeddable:!1}}}function KE(){return new TGA}$A();b0();b0();class gb0{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 $=await this.fetchFn(w.toString(),{headers:{Authorization:`Client-ID ${this.apiKey}`}});if(!$.ok)throw Error(`Unsplash API error: ${$.status} ${$.statusText}`);let B=PV6.parse(await $.json());return{photos:B.results.map(MV6),total:B.total,totalPages:B.total_pages,page:Q.page}}async triggerDownload(A){try{await this.fetchFn(A,{headers:{Authorization:`Client-ID ${this.apiKey}`}})}catch{}}}var kV6=H.looseObject({id:H.string(),description:H.string().nullable(),alt_description:H.string().nullable(),urls:H.looseObject({raw:H.url(),full:H.url(),regular:H.url(),small:H.url(),thumb:H.url()}),links:H.looseObject({html:H.url(),download_location:H.url()}),user:H.looseObject({name:H.string(),links:H.looseObject({html:H.url()})}),width:H.number().int().nonnegative(),height:H.number().int().nonnegative()}),PV6=H.looseObject({total:H.number().int().nonnegative(),total_pages:H.number().int().nonnegative(),results:H.array(kV6)});function MV6(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}}b0();async function yb0(A,Q,w,$){let B=await A.getEntity({entityType:Q,id:w});if(!B)return!1;return await A.updateEntity({entity:{...B,metadata:{...B.metadata,coverImageId:$}}}),!0}var jV6={query:H.string().describe("Search terms for stock photos"),perPage:H.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:H.number().min(1).default(1).describe("Page number")},OV6={photoId:H.string().describe("Photo ID from search results"),downloadLocation:H.url().describe("Download tracking URL (required by provider ToS)"),photographerName:H.string().describe("Photographer name for attribution"),photographerUrl:H.url().describe("Photographer profile URL for attribution"),sourceUrl:H.url().describe("Photo page URL on provider"),imageUrl:H.url().describe("Image URL to download"),title:H.string().optional().describe("Image entity title"),alt:H.string().optional().describe("Alt text for the image"),targetEntityType:H.string().optional().describe("Entity type to set cover image on"),targetEntityId:H.string().optional().describe("Entity ID to set cover image on")},fV6=H.object({query:H.string(),perPage:H.number().min(1).max(30).default(10),page:H.number().min(1).default(1)}),xV6=H.object({photoId:H.string(),downloadLocation:H.url(),photographerName:H.string(),photographerUrl:H.url(),sourceUrl:H.url(),imageUrl:H.url(),title:H.string().optional(),alt:H.string().optional(),targetEntityType:H.string().optional(),targetEntityId:H.string().optional()});function Rh2(A,Q){return[RV6(A,Q),vV6(A,Q)]}function RV6(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:jV6,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let $=fV6.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};try{return{success:!0,data:await Q.provider.searchPhotos($.data.query,{page:$.data.page,perPage:$.data.perPage})}}catch(B){return{success:!1,error:B instanceof Error?B.message:"Search failed"}}}}}function vV6(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:OV6,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let $=xV6.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:W,imageUrl:K,title:U,alt:G,targetEntityType:D,targetEntityId:z}=$.data,V={photographerName:Y,photographerUrl:Z,sourceUrl:W},I=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:K}}}});if(I[0]){let k={imageEntityId:I[0].id,alreadyExisted:!0,attribution:V};if(D&&z)k.coverSet=await yb0(Q.entityService,D,z,I[0].id);return{success:!0,data:k}}let F=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:W,imageUrl:K,...U!==void 0?{title:U}:{},...G!==void 0?{alt:G}:{},...D!==void 0?{targetEntityType:D}:{},...z!==void 0?{targetEntityId:z}:{}}}),_={imageEntityId:B,alreadyExisted:!1,attribution:V,jobId:F,status:"generating"};if(D&&z)_.coverSet=!1;return{success:!0,data:_}}}}$A();b0();rY();var CV6=H.object({photoId:H.string(),downloadLocation:H.url(),photographerName:H.string(),photographerUrl:H.url(),sourceUrl:H.url(),imageUrl:H.url(),title:H.string().optional(),alt:H.string().optional(),targetEntityType:H.string().optional(),targetEntityId:H.string().optional()});class SGA extends p6{deps;constructor(A,Q){super(A,{schema:CV6,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 $=await this.deps.fetchImage(A.imageUrl),B=A.title??`Stock photo ${A.photoId}`,X=nK.createImageEntity({dataUrl:$,title:B,alt:A.alt??B});await this.reportProgress(w,{progress:75,message:"Saving stock photo"});let{entityId:Y}=await this.deps.entityService.createEntity({entity:{id:A.photoId,...X,metadata:{...X.metadata,sourceUrl:A.imageUrl}}}),Z={imageEntityId:Y,alreadyExisted:!1};if(A.targetEntityType&&A.targetEntityId){if(Z.coverSet=await yb0(this.deps.entityService,A.targetEntityType,A.targetEntityId,Y),!Z.coverSet)Z.warning=`Target entity ${A.targetEntityType}:${A.targetEntityId} not found; cover image not set`}return await this.reportProgress(w,{progress:100,message:"Stock photo selected"}),Z}summarizeDataForLog(A){return{photoId:A.photoId,hasTarget:A.targetEntityType!==void 0}}}rY();var vh2={name:"@brains/stock-photo",version:"0.2.0-alpha.181",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 EV6=H.object({provider:H.enum(["unsplash"]).default("unsplash"),apiKey:H.string().optional().describe("Stock photo provider API key")});class mGA extends Rw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",vh2,A,EV6);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=Rh2(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??z3,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new SGA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??z3}))}createProvider(){return new gb0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function uGA(A={},Q={}){return new mGA(A,Q)}$A();b0();$A();$A();b0();var Ch2=H.enum(["ai","foundation","work"]),hh2=H.object({suffix:Ch2,title:H.string(),body:H.string(),linkLabel:H.string(),linkHref:H.string()}),w80=H.object({eyebrow:H.string(),headline:H.string(),cards:H.array(hh2).min(1)}),cGA=H.object({title:H.string(),slug:H.string(),status:H.enum(["draft","published"])}),gV6=H.object({title:H.string(),slug:H.string(),status:H.enum(["draft","published"])}),$80=aQ.extend({entityType:H.literal("ecosystem-section"),metadata:gV6});class Eh2 extends QQ{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:$80,frontmatterSchema:cGA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var pGA=new Eh2;b0();function yV6(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function lGA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function B80(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function Tb0(A){let Q=yV6(A),$=lGA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return w80.parse({eyebrow:lGA(Q,"Eyebrow"),headline:lGA(Q,"Headline"),cards:$.map((B)=>({suffix:B80(B,"Suffix"),title:B80(B,"Title"),body:B80(B,"Body"),linkLabel:B80(B,"Link Label"),linkHref:B80(B,"Link Href")}))})}function gh2(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(`
|
|
10234
10234
|
`)}var TV6=H.looseObject({query:H.object({id:H.string().optional()}).optional()});class Sb0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,w){let B=TV6.parse(A??{}).query?.id??"rizom-ecosystem",X=await w.entityService.getEntity({entityType:"ecosystem-section",id:B});if(!X)throw Error(`Ecosystem section not found: ${B}`);return Q.parse(Tb0(X.content))}}import{jsxDEV as uV6}from"preact/jsx-dev-runtime";var SV6="px-6 md:px-10 xl:px-20",mV6=`${SV6} relative z-[1]`,yh2=({id:A,className:Q,children:w})=>uV6("section",{id:A,className:l2(mV6,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as mb0}from"preact/jsx-dev-runtime";var cV6=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),Th2=({name:A="rizom",brandSuffix:Q,className:w,dotClassName:$,suffixClassName:B})=>{let X=cV6.get(Q);return mb0("span",{className:l2("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",w),children:[mb0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),mb0("span",{className:l2(X??"text-accent",$),children:"."},void 0,!1,void 0,this),mb0("span",{className:l2("italic font-normal text-theme-muted",B),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Fragment as dGA}from"preact";import{jsxDEV as X80}from"preact/jsx-dev-runtime";var pV6=/(\*[^*]+\*)/;function Sh2(A,Q){let w=A.split(`
|
|
10235
|
-
`);return X80(dGA,{children:w.map(($,B)=>X80(dGA,{children:[B>0&&X80("br",{},void 0,!1,void 0,this),$.split(pV6).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return X80("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return X80(dGA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as dW,Fragment as AF6}from"preact/jsx-dev-runtime";var lV6="italic text-accent font-normal",dV6="You are here",iV6={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},nV6={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},rV6={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},oV6="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",sV6="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",aV6="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",tV6="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",eV6=({card:A})=>{let Q=A.linkLabel===dV6,w=A.linkHref.trim().length===0,$=dW(AF6,{children:[dW(Th2,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),dW("span",{className:`${oV6} ${iV6[A.suffix]}`,children:A.title},void 0,!1,void 0,this),dW("p",{className:sV6,children:A.body},void 0,!1,void 0,this),Q?dW("span",{className:tV6,children:A.linkLabel},void 0,!1,void 0,this):dW("span",{className:aV6,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B=`flex flex-col gap-[14px] border-t pt-7 ${Q?nV6[A.suffix]:"border-white/10"}`;return Q||w?dW("div",{className:B,children:$},void 0,!1,void 0,this):dW("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${rV6[A.suffix]}`,children:$},void 0,!1,void 0,this)},mh2=({eyebrow:A,headline:Q,cards:w})=>dW(yh2,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[dW("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[dW("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),dW("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:Sh2(Q,lV6)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),dW("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(($)=>dW(eV6,{card:$},$.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);$A();var iGA=$2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:w80,formatter:{parse:Tb0,format:gh2},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:mh2}});var uh2={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.
|
|
10235
|
+
`);return X80(dGA,{children:w.map(($,B)=>X80(dGA,{children:[B>0&&X80("br",{},void 0,!1,void 0,this),$.split(pV6).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return X80("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return X80(dGA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as dW,Fragment as AF6}from"preact/jsx-dev-runtime";var lV6="italic text-accent font-normal",dV6="You are here",iV6={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},nV6={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},rV6={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},oV6="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",sV6="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",aV6="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",tV6="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",eV6=({card:A})=>{let Q=A.linkLabel===dV6,w=A.linkHref.trim().length===0,$=dW(AF6,{children:[dW(Th2,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),dW("span",{className:`${oV6} ${iV6[A.suffix]}`,children:A.title},void 0,!1,void 0,this),dW("p",{className:sV6,children:A.body},void 0,!1,void 0,this),Q?dW("span",{className:tV6,children:A.linkLabel},void 0,!1,void 0,this):dW("span",{className:aV6,children:A.linkLabel},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B=`flex flex-col gap-[14px] border-t pt-7 ${Q?nV6[A.suffix]:"border-white/10"}`;return Q||w?dW("div",{className:B,children:$},void 0,!1,void 0,this):dW("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${rV6[A.suffix]}`,children:$},void 0,!1,void 0,this)},mh2=({eyebrow:A,headline:Q,cards:w})=>dW(yh2,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[dW("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[dW("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),dW("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:Sh2(Q,lV6)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),dW("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(($)=>dW(eV6,{card:$},$.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);$A();var iGA=$2({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:w80,formatter:{parse:Tb0,format:gh2},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:mh2}});var uh2={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.181",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 wF6=H.object({}).catchall(H.unknown()).transform(()=>({})),$F6="ecosystem-section";class nGA extends jw{entityType=$F6;schema=$80;adapter=pGA;constructor(A={}){super("rizom-ecosystem",uh2,A,wF6)}getTemplates(){return{ecosystem:iGA}}getDataSources(){return[new Sb0]}}function UE(A={}){return new nGA(A)}b0();$A();$A();R2();b0();z9();b0();$A();var o$="agent",ch2="agent-discovery";var ph2="agent-network",lh2="AgentNetworkWidget",dh2="agent-proximity",ih2="AgentProximityWidget",Y80="agent-discovery:entities",ub0="agent-discovery:proximity-map",rGA="proximity-map",oGA="agent-list",sGA="agent-detail",w9="skill",nh2="skill",cb0="skill-derivation",rh2="skill:project",oh2="skill-derivation",sh2="skill:skill-derivation",ah2="skills";var pb0=H.object({name:H.string(),description:H.string(),tags:H.array(H.string())}),YO=H.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),th2=H.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),BF6=H.enum(["professional","team","collective"]),Lz=H.object({name:H.string(),kind:BF6,organization:H.string().optional(),brainName:H.string().describe("Name of the brain instance"),url:H.string().url().describe("Brain endpoint URL"),did:H.string().optional().describe("Decentralized identifier (public)"),repoDid:H.string().optional().describe("ATProto repo DID"),brainDid:H.string().optional().describe("ATProto brain DID"),anchorDid:H.string().optional().describe("ATProto anchor DID"),cardUri:H.string().optional().describe("ATProto brain card URI"),cardCid:H.string().optional().describe("ATProto brain card CID"),a2aEndpoint:H.string().url().optional().describe("A2A endpoint URL"),status:YO,discoveredAt:H.string().datetime().describe("When this agent was first discovered"),introducedBy:H.array(H.string()).optional().describe("Agent ids of the peers whose directories reported this agent"),hops:H.number().int().min(2).optional().describe("Discovery order: 2 = sighted through a first-order peer")}),eh2=H.object({name:H.string(),url:H.string().url(),status:YO,discoveredAt:H.string().datetime().optional(),slug:H.string(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.string().url().optional()}),XF6=H.object({name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),brainName:H.string(),url:H.string().url(),did:H.string().optional(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.string().url().optional(),status:th2,discoveredAt:H.string().datetime(),introducedBy:H.array(H.string()).optional(),hops:H.number().int().min(2).optional()}),YF6=H.object({name:H.string(),url:H.string().url(),status:th2,discoveredAt:H.string().datetime().optional(),slug:H.string(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.string().url().optional()}),Z80=n5.extend({entityType:H.literal(o$),metadata:eh2}),ZF6=aQ.extend({entityType:H.literal(o$),metadata:YF6}),H80=ZF6.extend({frontmatter:XF6,about:H.string(),skills:H.array(pb0),notes:H.string()}),HF6=H80.extend({url:H.string().optional(),typeLabel:H.string().optional()}),WF6=H80.extend({url:H.string(),typeLabel:H.string()});b0();var KF6=H.array(pb0);function AE2(A){let Q=KF6.safeParse(A);if(!Q.success||Q.data.length===0)return"";return Q.data.map((w)=>{let $=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${$}`}).join(`
|
|
10236
10236
|
`)}function QE2(A){if(!A.trim())return[];let Q=[];for(let w of A.split(`
|
|
10237
10237
|
`)){let $=w.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!$)continue;let B=$[1]??"",X=$[2]??"",Y=$[3],Z=Y?Y.split(",").map((W)=>W.trim()).filter(Boolean):[];Q.push({name:B,description:X,tags:Z})}return Q}var UF6=H.object({name:H.string(),description:H.string(),tags:H.array(H.string())}),GF6=H.object({about:H.string(),skills:H.array(UF6),notes:H.string()}),wE2=new R6(GF6,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:AE2,parser:QE2},{key:"notes",label:"Notes",type:"string"}]});class R7 extends QQ{constructor(){super({entityType:o$,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:Z80,frontmatterSchema:Lz,publishedStatuses:["approved"]})}fromMarkdown(A){let Q=this.parseFrontMatter(A,Lz),w=Hy(Q.url);return{content:A,entityType:o$,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:YO.parse(A.status),discoveredAt:A.discoveredAt,...A.introducedBy?.length&&{introducedBy:A.introducedBy},...A.hops!==void 0&&{hops:A.hops}},w=wE2.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=wE2.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,Lz),body:this.parseAgentContent(A.content)}}}$A();b0();var DF6=new R7,$E2=H.enum(["discovered","approved","archived"]),qF6=H.looseObject({id:H.string().optional(),limit:H.number().optional(),page:H.number().optional(),pageSize:H.number().optional(),baseUrl:H.string().optional(),status:$E2.optional()}),zF6=H.looseObject({entityType:H.string().optional(),query:qF6.optional()});function JF6(A){let Q=DQ(A.content,Lz),w=DF6.parseAgentContent(A.content);return H80.parse({...A,frontmatter:Q.metadata,about:w.about,skills:w.skills,notes:w.notes})}class lb0 extends H7{id=Y80;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:o$,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return JF6(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=zF6.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,w){let $=$E2.safeParse(w.status);return{agents:A,pagination:Q,baseUrl:w.baseUrl,selectedStatus:$.success?$.data:"all"}}async fetch(A,Q,w){let{query:$}=this.parseQuery(A);if($.id)return super.fetch(A,Q,w);let{items:B,pagination:X}=await this.fetchList($,w.entityService,$.status?{filter:{metadata:{status:$.status}}}:void 0);return Q.parse(this.buildListResult(B,X,$))}}var VF6=180*(3-Math.sqrt(5));function aGA(A){return Math.max(0,Math.min(1,A))}function tGA(A,Q){let[w,$]=A;if(Math.hypot(w,$)<=0.000000000001)return Q*VF6%360;return(Math.atan2($,w)*180/Math.PI%360+360)%360}function BE2(A,Q){let w=new Map(A.map((Y)=>[Y.id,Y])),$=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;$.get(Y.source.entityId)?.add(Y.target.entityId),$.get(Y.target.entityId)?.add(Y.source.entityId)}let B=new Set,X=[];for(let Y of Array.from(w.keys()).sort()){if(B.has(Y))continue;let Z=[],W=[Y];B.add(Y);while(W.length>0){let K=W.pop();if(!K)continue;Z.push(K);for(let U of Array.from($.get(K)??[]).sort()){if(B.has(U))continue;B.add(U),W.push(U)}}if(Z.length>=2)X.push(Z.sort())}return X.map((Y)=>({label:FF6(Y,w),memberIds:Y,links:Y.flatMap((Z)=>Array.from($.get(Z)??[]).filter((W)=>Z.localeCompare(W)<0).sort().map((W)=>({sourceId:Z,targetId:W})))})).sort((Y,Z)=>{let W=Y.memberIds.some((G)=>(w.get(G)?.tags.length??0)>0),K=Z.memberIds.some((G)=>(w.get(G)?.tags.length??0)>0);if(W!==K)return W?-1:1;let U=Y.label.localeCompare(Z.label);return U!==0?U:(Y.memberIds[0]??"").localeCompare(Z.memberIds[0]??"")})}function FF6(A,Q){let w=new Map;for(let B of A){let X=Q.get(B);for(let Y of new Set(X?.tags??[]))w.set(Y,(w.get(Y)??0)+1)}let $=Array.from(w.entries()).sort((B,X)=>{let Y=X[1]-B[1];return Y!==0?Y:B[0].localeCompare(X[0])})[0]?.[0];return $?`${$} \xB7 ${A.length}`:`unknown \xB7 ${A.length}`}b0();var IF6=Lz.shape.kind,LF6=H.object({kind:H.enum(["identity","centroid"])}),NF6=H.object({id:H.string(),name:H.string(),kind:IF6,status:YO,tags:H.array(H.string()),distance:H.number().min(0).max(1),bearing:H.number().min(0).lt(360)}),_F6=H.object({sourceId:H.string(),targetId:H.string()}),bF6=H.object({label:H.string(),memberIds:H.array(H.string()).min(2),links:H.array(_F6).min(1)}),kF6=H.object({min:H.number().min(0),max:H.number().min(0)}),XE2=H.object({kicker:H.string().optional(),headingLead:H.string().optional(),headingAccent:H.string().optional(),lede:H.string().optional(),ctaLabel:H.string().optional(),ctaHref:H.string().optional()}),PF6=H.object({id:H.string(),name:H.string(),viaIds:H.array(H.string()).min(1),tags:H.array(H.string()),distance:H.number().min(0).max(1),bearing:H.number().min(0).lt(360)}),u_=H.object({center:LF6,nodes:H.array(NF6),clusters:H.array(bF6),sightings:H.array(PF6),distanceRange:kF6,pendingCount:H.number().int().min(0),kicker:H.string().optional(),headingLead:H.string().optional(),headingAccent:H.string().optional(),lede:H.string().optional(),ctaLabel:H.string().optional(),ctaHref:H.string().optional()});var MF6=new R7;function YE2(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function xF(A){let Q=new Set,w=[];for(let $ of A){let B=YE2($);if(!B||Q.has(B))continue;Q.add(B),w.push(B)}return w}function jF6(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function ZE2(A,Q={}){let w=Q.minCount??1,$=Q.topN??12,B=Q.visibilityScope??"public",X=new Map,[Y,Z]=await Promise.all([A.entityService.listEntities({entityType:w9,options:{filter:{visibilityScope:B}}}),A.entityService.listEntities({entityType:o$,options:{filter:{visibilityScope:B}}})]),W=(K)=>{for(let U of xF(K))X.set(U,(X.get(U)??0)+1)};for(let K of Y)W(K.metadata.tags);for(let K of Z){let U=MF6.parseAgentContent(K.content);W(U.skills.flatMap((G)=>G.tags))}return Array.from(X.entries()).map(([K,U])=>({tag:K,count:U})).filter((K)=>K.count>=w).sort(jF6).slice(0,$)}function HE2(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(`
|
|
10238
10238
|
`)}var OF6={entityId:"brain-character",entityType:"brain-character"},fF6=0.25,xF6=0.5,RF6=new R7;function WE2(A){return A.status==="discovered"&&(A.introducedBy?.length??0)>0}async function db0(A){let[Q,w]=await Promise.all([A.entityService.listEntities({entityType:o$}),A.semantic.project({types:[o$],origin:OF6,maxNeighborDistance:fF6})]),$=new Map(w.points.map((D)=>[D.entityId,D])),B=Q.slice().sort((D,z)=>D.id.localeCompare(z.id)).map((D)=>({agent:D,...RF6.parseEntity(D)})),X=B.filter((D)=>!WE2(D.frontmatter)),Y=B.filter((D)=>WE2(D.frontmatter)),Z=[];for(let{agent:D,frontmatter:z,body:V}of X){let I=$.get(D.id);if(!I)continue;Z.push({id:D.id,name:z.name,kind:z.kind,status:z.status,tags:KE2(V.skills),distance:aGA(I.distanceToOrigin),bearing:tGA(I.coordinates,Z.length)})}let W=Z.filter((D)=>D.status!=="archived"),K=new Set(W.map((D)=>D.id)),U=Math.max(xF6,...W.map((D)=>D.distance)),G=[];for(let{agent:D,frontmatter:z,body:V}of Y){let I=$.get(D.id);if(!I)continue;let F=aGA(I.distanceToOrigin);if(F>U)continue;let _=(z.introducedBy??[]).filter((k)=>K.has(k));if(_.length===0)continue;G.push({id:D.id,name:z.name,viaIds:_,tags:KE2(V.skills),distance:F,bearing:tGA(I.coordinates,G.length)})}return u_.parse({center:{kind:w.origin.kind==="entity"?"identity":"centroid"},nodes:Z,clusters:BE2(W,w.neighbors),sightings:G,distanceRange:w.distanceRange,pendingCount:Math.max(0,X.length-Z.length)})}function KE2(A){return xF(A.flatMap((Q)=>Q.tags))}class ib0{id=ub0;name="Agent Proximity Map DataSource";description="Builds a public semantic proximity map for saved agents";async fetch(A,Q,w){let $=await db0({entityService:w.entityService,semantic:{project:(B)=>w.entityService.projectSemanticSpace(B)}});return Q.parse($)}}$A();b0();g$();$A();async function Zi(A,Q,w){let B=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let X=await Q(B,w?{signal:w}:void 0);if(!X.ok)return null;let Y=await X.json();return ft(Y)}catch{if(w?.aborted)throw w.reason;return null}}function c_(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""}R2();var vF6=new R7;function Hi(A,Q={}){let w=A.anchor?.name??A.brainName,$=A.anchor?.kind??"professional",B=[];if(A.anchor?.description)B.push(A.anchor.description);if(A.description)B.push(A.description);let X=Q.status??"discovered",Y=new Date().toISOString();return{content:vF6.createAgentContent({name:w,kind:$,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:X,discoveredAt:Y,...Q.provenance&&{introducedBy:Q.provenance.introducedBy,hops:Q.provenance.hops},about:B.join(`
|
|
@@ -10392,8 +10392,8 @@ ${A.guidance}`:B}}function Dh2(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10392
10392
|
var anchorRect = anchor.getBoundingClientRect();
|
|
10393
10393
|
var left = anchorRect.right - mapRect.left + 12;
|
|
10394
10394
|
var top = anchorRect.top - mapRect.top - 8;
|
|
10395
|
-
tooltip.style.left = Math.min(left, mapRect.width - tooltip.offsetWidth - 12) + "px";
|
|
10396
|
-
tooltip.style.top = Math.max(12, top) + "px";
|
|
10395
|
+
tooltip.style.left = Math.max(12, Math.min(left, mapRect.width - tooltip.offsetWidth - 12)) + "px";
|
|
10396
|
+
tooltip.style.top = Math.max(12, Math.min(top, mapRect.height - tooltip.offsetHeight - 12)) + "px";
|
|
10397
10397
|
}
|
|
10398
10398
|
|
|
10399
10399
|
function focusCluster(clusterId) {
|
|
@@ -10476,8 +10476,26 @@ ${A.guidance}`:B}}function Dh2(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10476
10476
|
element.addEventListener("mouseleave", reset);
|
|
10477
10477
|
element.addEventListener("focus", activate);
|
|
10478
10478
|
element.addEventListener("blur", reset);
|
|
10479
|
+
// Touch fires neither mouseenter nor (reliably) focus on SVG
|
|
10480
|
+
// elements \u2014 a tap activates directly.
|
|
10481
|
+
element.addEventListener("click", function (event) {
|
|
10482
|
+
event.stopPropagation();
|
|
10483
|
+
activate();
|
|
10484
|
+
});
|
|
10479
10485
|
}
|
|
10480
10486
|
|
|
10487
|
+
// A tap on the map ground dismisses whatever a previous tap lit up
|
|
10488
|
+
// (touch has no mouseleave, and blur never fires if focus never did).
|
|
10489
|
+
map.addEventListener("click", function (event) {
|
|
10490
|
+
if (
|
|
10491
|
+
!event.target.closest(
|
|
10492
|
+
"[data-proximity-node], [data-proximity-cluster-id], [data-proximity-sighting]"
|
|
10493
|
+
)
|
|
10494
|
+
) {
|
|
10495
|
+
reset();
|
|
10496
|
+
}
|
|
10497
|
+
});
|
|
10498
|
+
|
|
10481
10499
|
nodes.forEach(function (node) {
|
|
10482
10500
|
bind(node, function () { activateNode(node); });
|
|
10483
10501
|
});
|
|
@@ -10493,7 +10511,7 @@ ${A.guidance}`:B}}function Dh2(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10493
10511
|
});
|
|
10494
10512
|
});
|
|
10495
10513
|
})();`;import{jsxDEV as Q2,Fragment as $I6}from"preact/jsx-dev-runtime";var VE2=1000,K80=520,O4=520,CH=260,dF6=220,iF6=`${O4-340} 0 680 ${K80}`;function ob0(A){let Q=A>>>0;return()=>{Q|=0,Q=Q+1831565813|0;let w=Math.imul(Q^Q>>>15,1|Q);return w=w+Math.imul(w^w>>>7,61|w)^w,((w^w>>>14)>>>0)/4294967296}}function sb0(A,Q){return Math.min(1,Math.max(0,A/Q))*dF6}function nF6(A){let Q=A<=0.4?0.1:A<=1?0.2:0.5,w=[];for(let $=Q;$<A;$+=Q)w.push(Number($.toFixed(2)));return w}function IE2(A,Q,w){let $=Q*Math.PI/180,B=sb0(A,w);return{x:O4+Math.cos($)*B,y:CH-Math.sin($)*B}}function rF6(A,Q){let w=A.x-O4,$=A.y-CH,B=Math.max(1,Math.hypot(w,$)),X=-$/B,Y=w/B,Z=(Q()-0.5)*B*0.42,W=(Q()-0.5)*B*0.3,K={x:O4+w*0.34+X*Z,y:CH+$*0.34+Y*Z},U={x:O4+w*0.7+X*W,y:CH+$*0.7+Y*W},G=0.46+Q()*0.22,D={x:O4+w*G,y:CH+$*G},z=Math.atan2($,w)+(Q()-0.5)*2.1,V=14+Q()*22,I={x:D.x+Math.cos(z)*V,y:D.y+Math.sin(z)*V};return{path:`M ${O4} ${CH} C ${K.x} ${K.y}, ${U.x} ${U.y}, ${A.x} ${A.y}`,rootlet:`M ${D.x} ${D.y} Q ${(D.x+I.x)/2+(Q()-0.5)*8} ${(D.y+I.y)/2+(Q()-0.5)*8}, ${I.x} ${I.y}`}}function FE2(A){let Q=A.slice().sort((W,K)=>{let U=W.preferredY-K.preferredY;return U!==0?U:W.id.localeCompare(K.id)}),w=56,$=K80-58,B=15,X=[];for(let W of Q)X.push(Math.max(W.preferredY,(X[X.length-1]??-1/0)+15));let Y=Math.max(0,(X[X.length-1]??0)-$);for(let W=0;W<X.length;W+=1)X[W]=(X[W]??0)-Y;for(let W=X.length-2;W>=0;W-=1)X[W]=Math.min(X[W]??0,(X[W+1]??$)-15);let Z=Math.max(0,56-(X[0]??56));return new Map(Q.map((W,K)=>[W.id,(X[K]??0)+Z]))}function oF6(A,Q){let w=ob0(133),$=A.map((Y)=>({node:Y,point:IE2(Y.distance,Y.bearing,Q)})),B=FE2($.filter(({point:Y})=>Y.x<O4).map(({node:Y,point:Z})=>({id:Y.id,preferredY:Z.y+3}))),X=FE2($.filter(({point:Y})=>Y.x>=O4).map(({node:Y,point:Z})=>({id:Y.id,preferredY:Z.y+3})));return $.map(({node:Y,point:Z})=>{let W=rF6(Z,w),K=Z.x>=O4;return{node:Y,point:Z,...W,labelX:Z.x+(K?12:-12),labelY:(K?X:B).get(Y.id)??Z.y+3,labelAnchor:K?"start":"end"}})}function sF6(A,Q){let w=A.memberIds.flatMap((X)=>{let Y=Q.get(X);return Y?[Y]:[]});if(w.length<2)return null;let $={x:w.reduce((X,Y)=>X+Y.x,0)/w.length,y:w.reduce((X,Y)=>X+Y.y,0)/w.length},B=Math.max(...w.map((X)=>Math.hypot(X.x-$.x,X.y-$.y)))+26;return{center:$,radius:B}}function aF6(A,Q,w){let $=(A.x+Q.x)/2+(w()-0.5)*34,B=(A.y+Q.y)/2+(w()-0.5)*34;return`M ${A.x} ${A.y} Q ${$} ${B}, ${Q.x} ${Q.y}`}function tF6({node:A,point:Q,blurRef:w}){let $=A.status==="archived",B=A.status==="discovered";if($)return Q2("circle",{class:"proximity-archived-remnant",cx:Q.x,cy:Q.y,r:"1.4",fill:"var(--console-text-faint)",opacity:"0.18"},void 0,!1,void 0,this);let X=(K,U,G,D)=>B?Q2("circle",{cx:K,cy:U,r:G+0.8,fill:"none",stroke:"var(--console-warn)",strokeWidth:"1.1",strokeDasharray:"2.4 2"},D,!1,void 0,this):Q2("g",{children:[Q2("circle",{class:"proximity-bulb-glow",cx:K,cy:U,r:G*3.2,fill:"var(--console-accent)",opacity:"0.13",filter:w},void 0,!1,void 0,this),Q2("circle",{cx:K,cy:U,r:G,fill:"var(--console-accent)"},void 0,!1,void 0,this),Q2("circle",{cx:K,cy:U,r:G*0.42,fill:"var(--console-text)",opacity:"0.9"},void 0,!1,void 0,this)]},D,!0,void 0,this);if(A.kind==="professional")return X(Q.x,Q.y,3.4,"professional");let Y=A.kind==="team"?[90,210,330]:[18,90,162,234,306],Z=A.kind==="team"?4.6:6.4,W=A.kind==="team"?2.1:1.7;return Q2("g",{children:Y.map((K)=>{let U=K*Math.PI/180;return X(Q.x+Math.cos(U)*Z,Q.y-Math.sin(U)*Z,W,String(K))})},void 0,!1,void 0,this)}function eF6({data:A}){return Q2("div",{class:"proximity-empty","data-proximity-map-empty":!0,children:[Q2("p",{class:"muted",children:"No indexed agents yet."},void 0,!1,void 0,this),A.center.kind==="centroid"&&Q2("p",{class:"muted",children:"Identity not indexed yet \u2014 waiting for embeddings."},void 0,!1,void 0,this),A.pendingCount>0&&Q2("p",{class:"muted",children:[A.pendingCount," pending indexing"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var AI6=28,QI6=6,ab0=8,w3A=14,LE2=232;function wI6(A){let Q=ab0*(A-w3A)/(LE2-w3A);return`animation:proximityRippleShimmer ${ab0}s linear infinite;animation-delay:${Q.toFixed(2)}s`}function tb0({data:A,surface:Q="dashboard"}){if(A.nodes.length===0)return Q2(eF6,{data:A},void 0,!1,void 0,this);let w=`proximity-blur-${Q}`,$=`proximity-mist-${Q}`,B=`url(#${w})`,X=Math.max(...A.nodes.map((k)=>k.distance),...A.sightings.map((k)=>k.distance)),Y=Math.max(A.distanceRange.max,X,0.1),Z=nF6(Y),W=oF6(A.nodes,Y),K=new Map(W.map(({node:k,point:b})=>[k.id,b])),U=new Map(A.nodes.map((k)=>[k.id,k.name])),G=new Map;A.clusters.forEach((k,b)=>{for(let f of k.memberIds)G.set(f,`cluster-${b}`)});let D=ob0(7331),z=ob0(4242),V=A.nodes.filter((k)=>k.status!=="archived"),I=A.sightings.flatMap((k)=>{let b=k.viaIds.flatMap((f)=>{let R=K.get(f);return R?[{viaId:f,from:R}]:[]});if(b.length===0)return[];return[{sighting:k,point:IE2(k.distance,k.bearing,Y),viaPoints:b}]}),F=W.filter(({node:k})=>k.status==="approved").slice(0,QI6),_=V.length>AI6;return Q2("div",{class:`proximity-field proximity-field--${Q}${_?" proximity-field--dense":""}`,"data-proximity-map":!0,children:[Q2("svg",{viewBox:Q==="site"?iF6:`0 0 ${VE2} ${K80}`,width:"100%",height:"auto",role:"img","aria-label":"Semantic proximity of saved agents to this brain",children:[Q2("defs",{children:[Q2("filter",{id:w,x:"-60%",y:"-60%",width:"220%",height:"220%",children:Q2("feGaussianBlur",{stdDeviation:"2.6"},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q2("radialGradient",{id:$,children:[Q2("stop",{offset:"0%","stop-color":"var(--console-secondary)","stop-opacity":"0.3"},void 0,!1,void 0,this),Q2("stop",{offset:"70%","stop-color":"var(--console-secondary)","stop-opacity":"0.11"},void 0,!1,void 0,this),Q2("stop",{offset:"100%","stop-color":"var(--console-secondary)","stop-opacity":"0"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z.map((k)=>Q2("g",{"data-proximity-ring":String(k),children:[Q2("circle",{cx:O4,cy:CH,r:sb0(k,Y),fill:"none",stroke:"var(--console-rule)",strokeWidth:"1"},void 0,!1,void 0,this),Q2("text",{class:"proximity-strata-label",x:O4+4,y:CH-sb0(k,Y)-5,children:k.toFixed(1)},void 0,!1,void 0,this)]},k,!0,void 0,this)),A.clusters.map((k,b)=>{let f=sF6(k,K);if(!f)return null;let R=k.links.flatMap((M)=>{let y=K.get(M.sourceId),S=K.get(M.targetId);return y&&S?[aF6(y,S,D)]:[]}),v=f.center.y<CH;return Q2("g",{"data-proximity-cluster":k.label,"data-proximity-cluster-id":`cluster-${b}`,"data-proximity-cluster-label":k.label,"data-proximity-cluster-members":k.memberIds.length,tabIndex:0,children:[Q2("circle",{class:"proximity-cluster-mist",cx:f.center.x,cy:f.center.y,r:f.radius,fill:`url(#${$})`},void 0,!1,void 0,this),Q2("g",{class:"proximity-cluster-weave",children:R.map((M,y)=>Q2("g",{children:[Q2("path",{d:M,fill:"none",stroke:"var(--console-secondary)",strokeOpacity:"0.22",strokeWidth:"2.6",filter:B},void 0,!1,void 0,this),Q2("path",{d:M,fill:"none",stroke:"var(--console-secondary)",strokeOpacity:"0.5",strokeWidth:"0.9"},void 0,!1,void 0,this)]},y,!0,void 0,this))},void 0,!1,void 0,this),Q2("text",{class:"proximity-cluster-label",x:f.center.x,y:Math.max(24,Math.min(K80-24,v?f.center.y-f.radius-10:f.center.y+f.radius+20)),textAnchor:"middle",children:k.label},void 0,!1,void 0,this)]},k.label,!0,void 0,this)}),W.map(({node:k,path:b,rootlet:f})=>{let R=k.status==="archived",v=k.status==="discovered",M=R?"var(--console-text-faint)":"var(--console-accent)";return Q2("g",{children:[Q2("path",{id:k.status==="approved"?`proximity-thread-${Q}-${k.id}`:void 0,d:b,fill:"none",stroke:M,strokeOpacity:R?0.012:v?0.08:0.14,strokeWidth:"3.4",filter:R?void 0:B},void 0,!1,void 0,this),Q2("path",{d:b,fill:"none",stroke:M,strokeOpacity:R?0.045:v?0.16:0.3,strokeWidth:R?0.65:1,strokeDasharray:R?"1 8":v?"3 5":void 0,strokeLinecap:"round"},void 0,!1,void 0,this),Q2("path",{d:f,fill:"none",stroke:M,strokeOpacity:R?0.012:v?0.06:0.12,strokeWidth:"0.6"},void 0,!1,void 0,this)]},`thread:${k.id}`,!0,void 0,this)}),F.map(({node:k},b)=>Q2("g",{class:"proximity-pulse","aria-hidden":"true",children:[Q2("circle",{r:"3.2",fill:"var(--console-accent)",opacity:"0.3",children:Q2("animateMotion",{dur:`${5+b%3*1.6}s`,begin:`${b*1.9}s`,repeatCount:"indefinite",children:Q2("mpath",{href:`#proximity-thread-${Q}-${k.id}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q2("circle",{r:"1.3",fill:"var(--console-text)",opacity:"0.9",children:Q2("animateMotion",{dur:`${5+b%3*1.6}s`,begin:`${b*1.9}s`,repeatCount:"indefinite",children:Q2("mpath",{href:`#proximity-thread-${Q}-${k.id}`},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},`pulse:${k.id}`,!0,void 0,this)),Q2("g",{class:"proximity-ripple","aria-hidden":"true",children:[{width:5,opacity:"0.1;0.07;0",blurred:!0},{width:1.1,opacity:"0.38;0.22;0",blurred:!1}].map((k)=>Q2("circle",{cx:O4,cy:CH,fill:"none",stroke:"var(--console-accent)",strokeWidth:k.width,filter:k.blurred?B:void 0,children:[Q2("animate",{attributeName:"r",values:`${w3A};${LE2}`,dur:`${ab0}s`,repeatCount:"indefinite",calcMode:"spline",keyTimes:"0;1",keySplines:"0.2 0 0.4 1"},void 0,!1,void 0,this),Q2("animate",{attributeName:"stroke-opacity",values:k.opacity,keyTimes:"0;0.6;1",dur:`${ab0}s`,repeatCount:"indefinite"},void 0,!1,void 0,this)]},k.width,!0,void 0,this))},void 0,!1,void 0,this),Q2("g",{"data-proximity-center":A.center.kind,children:[Q2("circle",{class:"proximity-center-halo",cx:O4,cy:CH,r:"26",fill:"var(--console-accent)",opacity:"0.1",filter:B},void 0,!1,void 0,this),Q2("circle",{cx:O4,cy:CH,r:"11",fill:"var(--console-accent)",opacity:"0.28",filter:B},void 0,!1,void 0,this),Q2("circle",{cx:O4,cy:CH,r:"4.6",fill:"var(--console-accent)"},void 0,!1,void 0,this),Q2("circle",{cx:O4,cy:CH,r:"2",fill:"var(--console-text)"},void 0,!1,void 0,this),Q2("text",{class:"proximity-you-label",x:O4,y:CH+30,children:"you"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),W.map(({node:k,point:b,labelX:f,labelY:R,labelAnchor:v})=>{let M=G.get(k.id),y=k.status==="archived"?void 0:wI6(sb0(k.distance,Y));return Q2("g",{class:"proximity-agent",style:y,"data-proximity-node":k.id,"data-proximity-node-cluster":M,"data-proximity-name":k.name,"data-proximity-kind":k.kind,"data-proximity-status":k.status,"data-proximity-distance":k.distance.toFixed(2),"data-proximity-tags":k.tags.join(", "),tabIndex:0,children:[Q2("title",{children:`${k.name} \xB7 distance ${k.distance.toFixed(2)}${k.status==="discovered"?" \xB7 pending review":k.status==="archived"?" \xB7 archived":""}`},void 0,!1,void 0,this),M&&Q2("circle",{cx:b.x,cy:b.y,r:"15",fill:"var(--console-secondary)",opacity:"0.2",filter:B},void 0,!1,void 0,this),Q2(tF6,{node:k,point:b,blurRef:B},void 0,!1,void 0,this),Math.abs(R-b.y)>7&&Q2("path",{class:"proximity-label-leader",d:`M ${b.x+(v==="start"?6:-6)} ${b.y} L ${f+(v==="start"?-3:3)} ${R-3}`,fill:"none",stroke:"var(--console-rule-strong)",strokeWidth:"0.7"},void 0,!1,void 0,this),Q2("text",{class:"proximity-node-label",x:f,y:R,textAnchor:v,children:k.name.toLowerCase()},void 0,!1,void 0,this)]},k.id,!0,void 0,this)}),I.map(({sighting:k,point:b,viaPoints:f})=>{let R=k.viaIds.map((M)=>U.get(M)??M).join(" \xB7 "),v=b.x>=O4;return Q2("g",{class:"proximity-sighting","data-proximity-sighting":k.id,"data-proximity-name":k.name,"data-proximity-via":R,"data-proximity-via-ids":k.viaIds.join(" "),"data-proximity-distance":k.distance.toFixed(2),"data-proximity-tags":k.tags.join(", "),tabIndex:0,children:[Q2("title",{children:`${k.name} \xB7 second order \xB7 via ${R} \xB7 distance ${k.distance.toFixed(2)}`},void 0,!1,void 0,this),f.map(({viaId:M,from:y})=>{let S=b.x-y.x,l=b.y-y.y,o=Math.max(1,Math.hypot(S,l)),Z0=(z()-0.5)*o*0.5,d={x:y.x+S*0.5+-l/o*Z0,y:y.y+l*0.5+S/o*Z0},j=`M ${y.x} ${y.y} Q ${d.x} ${d.y}, ${b.x} ${b.y}`;return Q2("g",{class:"proximity-sighting-thread",children:[Q2("path",{d:j,fill:"none",stroke:"var(--console-accent)",strokeOpacity:"0.09",strokeWidth:"2.4",filter:B},void 0,!1,void 0,this),Q2("path",{d:j,fill:"none",stroke:"var(--console-accent)",strokeOpacity:"0.2",strokeWidth:"0.8"},void 0,!1,void 0,this)]},M,!0,void 0,this)}),Q2("circle",{cx:b.x,cy:b.y,r:"7.8",fill:"var(--console-accent)",opacity:"0.07",filter:B},void 0,!1,void 0,this),Q2("circle",{cx:b.x,cy:b.y,r:"3",fill:"var(--console-accent)",opacity:"0.5"},void 0,!1,void 0,this),Q2("text",{class:"proximity-node-label","fill-opacity":"0.55",x:b.x+(v?11:-11),y:b.y+3,textAnchor:v?"start":"end",children:k.name.toLowerCase()},void 0,!1,void 0,this)]},`sighting:${k.id}`,!0,void 0,this)}),Array.from({length:9},(k,b)=>{let f=ob0(900+b);return Q2("circle",{class:"proximity-spore",cx:46+f()*(VE2-92),cy:42+f()*(K80-84),r:0.7+f()*0.9,fill:f()<0.6?"var(--console-secondary)":"var(--console-accent)",opacity:"0.26",style:`animation-delay:-${(f()*11).toFixed(1)}s`},b,!1,void 0,this)})]},void 0,!0,void 0,this),Q==="dashboard"&&Q2($I6,{children:[Q2("div",{class:"proximity-hud proximity-hud-count","aria-hidden":"true",children:[Q2("div",{class:"proximity-count-number",children:V.length},void 0,!1,void 0,this),Q2("div",{class:"proximity-count-label",children:"agents in reach"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q2("div",{class:"proximity-hud proximity-hud-foot",children:[Q2("div",{class:"proximity-legend","aria-label":"Agent kinds",children:[Q2("span",{children:"\u25CF professional"},void 0,!1,void 0,this),Q2("span",{children:"\u2234 team"},void 0,!1,void 0,this),Q2("span",{children:"\u25CC collective"},void 0,!1,void 0,this),Q2("span",{children:"\xB7 archived trace"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.pendingCount>0&&Q2("p",{class:"proximity-pending-note",children:[Q2("b",{children:A.pendingCount},void 0,!1,void 0,this)," pending indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&Q2("p",{class:"proximity-pending-note",children:[Q2("b",{children:"Identity not indexed"},void 0,!1,void 0,this)," \xB7 centroid fallback"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Q2("div",{class:"proximity-tooltip","data-proximity-tooltip":!0,hidden:!0},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $3A({data:A}){let Q=u_.safeParse(A);if(!Q.success)return Q2("p",{class:"muted",children:"Nothing to show yet."},void 0,!1,void 0,this);return Q2(tb0,{data:Q.data},void 0,!1,void 0,this)}var BI6=H.object({counts:H.object({agents:H.number(),skills:H.number()})});function NE2(A,Q){A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:ph2,pluginId:Q,title:"Agent Network",group:"network",section:"secondary",priority:15,rendererName:lh2,component:Q3A,clientScript:rb0,dataProvider:async()=>JE2(A),digestProvider:(w)=>{let{counts:$}=BI6.parse(w);return{digest:[{label:"Agents",value:String($.agents)},{label:"Skills",value:String($.skills)}]}}}}),await A.messaging.send({type:"dashboard:register-widget",payload:{id:dh2,pluginId:Q,title:"Agent Proximity",group:"network",section:"primary",priority:35,rendererName:ih2,component:$3A,clientScript:Wi,dataProvider:async()=>db0(A),digestProvider:(w)=>{let $=u_.parse(w);return{digest:[{label:"Agents",value:String($.nodes.length)},{label:"Clusters",value:String($.clusters.length)},{label:"Pending",value:String($.pendingCount)}]}}}}),{success:!0}})}R2();var _E2=new R7;function XI6(A){return A.skills.map((Q)=>({name:Q.name,description:Q.description,tags:Q.tags??[]}))}function YI6(A){return new URL(A).hostname}function ZI6(A){return[`ATProto card: ${A.uri}`,`ATProto card CID: ${A.cid}`,`ATProto repo DID: ${A.repoDid}`].join(`
|
|
10496
|
-
`)}function HI6(A){let Q=A.record.brain.did,w=A.record.anchor.did;return{agentId:A.agent.id,name:A.agent.metadata.name,url:A.agent.metadata.url,status:A.agent.metadata.status,repoDid:A.repoDid,...Q&&{brainDid:Q},...w&&{anchorDid:w},cardUri:A.uri,cardCid:A.cid}}async function WI6(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function KI6(A,Q,w=new Date().toISOString()){let{record:$}=Q,B=YI6($.siteUrl),X=await A.entityService.getEntity({entityType:"agent",id:B}),Y=X?_E2.parseEntity(X):void 0,Z=$.brain.did,W=$.anchor.did,K=XI6($),U=X?.metadata.status??"discovered",G=X?.metadata.url??$.siteUrl,D=X?.metadata.slug??Hy(G),z=X?.metadata.name??$.anchor.name,V=Y?.frontmatter.kind??$.anchor.kind,I=X?.metadata.discoveredAt??w,F=$.brain.purpose.length>0?$.brain.purpose:Y?.body.about??"",_=K.length>0?K:Y?.body.skills??[],k={...X?.metadata??{},name:z,url:G,status:U,discoveredAt:I,slug:D,repoDid:Q.repoDid,...Z&&{brainDid:Z},...W&&{anchorDid:W},cardUri:Q.uri,cardCid:Q.cid},b=_E2.createAgentContent({name:z,kind:V,...Y?.frontmatter.organization&&{organization:Y.frontmatter.organization},brainName:$.brain.name,url:G,...Z&&{did:Z,brainDid:Z},...W&&{anchorDid:W},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...Y?.frontmatter.a2aEndpoint&&{a2aEndpoint:Y.frontmatter.a2aEndpoint},status:U,discoveredAt:I,about:F,skills:_,notes:ZI6({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(X){let R={...X,content:b,metadata:k,updated:w};return await A.entityService.updateEntity({entity:R}),{agent:R,created:!1}}let f={id:B,entityType:"agent",content:b,metadata:k,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:f}),{agent:f,created:!0}}function bE2(A){A.messaging.subscribe(eQ0,async(Q)=>{let w=q9A.parse(Q.payload),$=await KI6(A,w),B=HI6({agent:$.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await WI6(A,$.created?G9A:D9A,B),{success:!0,data:B}})}function kE2(){return["Agent entities are saved peer contacts. List them with system_list on entityType agent.","For an expertise match or recommendation, immediately run one system_search scoped to entityType agent using the requested topic. Suggest only clear matches, naming the contact and exact callable id/domain with brief supporting evidence. Prefer approved contacts; label discovered contacts as unverified; never recommend archived contacts. If none qualifies, say \u201CI couldn't find a clear match in your saved agent network for <topic>\u201D rather than suggesting a generic role. A short affirmative reply to an offer to search means run that search using the prior topic.","Route contact changes by intent: agent_connect verifies and saves a new domain/URL as an approved outbound contact; system_update changes the lifecycle status of an existing contact; agent_set_trust_level is the only tool for granting or revoking inbound A2A trust. Revocation uses level public and needs no key fingerprint or preliminary entity lookup.","If agent_call cannot reach an unsaved exact domain, offer to connect it; a short affirmative follow-up should call agent_connect for that domain. Only approved contacts can be called.","To call a contact named by person, anchor, or display name, first resolve it with one system_search scoped to entityType agent, then call agent_call with the returned entity id/domain\u2014not the display, anchor, or brain name. Skip search only when the user supplied an exact domain-like id."].join(" ")}y8();b0();import{jsxDEV as PE2}from"preact/jsx-dev-runtime";function eb0(A){try{return new URL(A).hostname}catch{return A}}var Ak0=({name:A,className:Q=""})=>{let w=A.charAt(0).toUpperCase(),$=0;for(let X=0;X<A.length;X++)$=A.charCodeAt(X)+(($<<5)-$);let B=Math.abs($)%360;return PE2("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${B}, 55%, 45%)`},children:w},void 0,!1,void 0,this)},Qk0=({kind:A,size:Q="md"})=>{let $={professional:"bg-status-success text-status-success",team:"bg-status-info text-status-info",collective:"bg-brand/10 text-brand"}[A]??"bg-status-neutral text-status-neutral";return PE2("span",{className:`inline-flex items-center rounded-full font-medium ${Q==="sm"?"px-2 py-0.5 text-xs":"px-2.5 py-0.5 text-[13px]"} ${$}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as x2,Fragment as DI6}from"preact/jsx-dev-runtime";var UI6=({skills:A})=>{if(A.length===0)return null;return x2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>x2("span",{className:"text-[11px] px-2 py-0.5 bg-theme-subtle rounded-md text-theme-muted",children:Q.name},Q.name,!1,void 0,this))},void 0,!1,void 0,this)};function GI6(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function ME2(A,Q,w){let $=new URLSearchParams({status:Q});if(w>1)$.set("page",String(w));return`${A}?${$.toString()}`}var wk0=({agent:A})=>{let{frontmatter:Q,about:w,skills:$,url:B}=A,X=Q.status==="approved",Y=Q.status==="archived";return x2("a",{href:B,className:`flex items-start gap-5 p-6 rounded-xl border border-theme bg-theme-subtle hover:shadow-lg transition-shadow ${X?"":Y?"opacity-40":"opacity-70"}`,children:[x2(Ak0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),x2("div",{className:"flex-1 min-w-0",children:[x2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[x2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),x2(Qk0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&x2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&x2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),X&&x2(UI6,{skills:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col items-end gap-1 flex-shrink-0 text-right",children:[x2("span",{className:"text-xs text-theme-muted",children:eb0(Q.url)},void 0,!1,void 0,this),x2("span",{className:"text-[11px] text-theme-muted opacity-60",children:X?`Discovered ${GI6(Q.discoveredAt)}`:Y?"Archived \xB7 cannot be called":"Discovered \xB7 approve before calling"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},jE2=({agents:A,pageTitle:Q,pagination:w,baseUrl:$="/agents",selectedStatus:B})=>{let X=Q??"Agent Directory",Y=w?.totalItems??A.length,Z=A.filter((V)=>V.frontmatter.status==="approved"),W=A.filter((V)=>V.frontmatter.status==="discovered"),K=A.filter((V)=>V.frontmatter.status==="archived"),U=Z.length,G=W.length,D=K.length,z=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return x2(DI6,{children:[x2(Nw,{title:X,description:z},void 0,!1,void 0,this),x2("div",{className:"agent-list bg-theme",children:x2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[x2("div",{className:"mb-8 pb-6 border-b border-theme",children:[x2("h1",{className:"text-4xl font-bold text-heading mb-2",children:X},void 0,!1,void 0,this),x2("p",{className:"text-theme-muted mb-4",children:z},void 0,!1,void 0,this),x2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[U," approved"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[G," discovered"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted opacity-60",children:[D," archived"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-wrap gap-2 text-sm",children:[x2("a",{href:$,className:`px-3 py-1 rounded-full border transition-colors ${B==="all"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"All"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=approved`,className:`px-3 py-1 rounded-full border transition-colors ${B==="approved"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Approved"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=discovered`,className:`px-3 py-1 rounded-full border transition-colors ${B==="discovered"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Discovered"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=archived`,className:`px-3 py-1 rounded-full border transition-colors ${B==="archived"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Archived"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),B==="all"&&Z.length>0&&x2("section",{className:"mb-10",children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:Z.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:Z.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B==="all"&&W.length>0&&x2("section",{children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("div",{children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),x2("p",{className:"text-sm text-theme-muted",children:"Review and approve these before calling them."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:W.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:W.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B==="all"&&K.length>0&&x2("section",{className:"mt-10 opacity-60",children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("div",{children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Archived brains"},void 0,!1,void 0,this),x2("p",{className:"text-sm text-theme-muted",children:"Retained as history and unavailable for calling."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:K.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:K.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B!=="all"&&A.length>0&&x2("section",{children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("h2",{className:"text-lg font-semibold text-heading",children:B==="approved"?"Approved brains":B==="archived"?"Archived brains":"Discovered brains"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:A.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&x2("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),w&&w.totalPages>1&&B==="all"&&x2("div",{className:"mt-12",children:x2(F_,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&w.totalPages>1&&B!=="all"&&x2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?x2("a",{href:ME2($,B,w.currentPage-1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"\u2190 Prev"},void 0,!1,void 0,this):x2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"\u2190 Prev"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?x2("a",{href:ME2($,B,w.currentPage+1),className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"Next \u2192"},void 0,!1,void 0,this):x2("span",{className:"px-3 py-2 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"Next \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as i2,Fragment as VI6}from"preact/jsx-dev-runtime";function qI6(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var U80=({children:A})=>i2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),zI6=({skill:A})=>i2("div",{className:"flex items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[i2("div",{className:"flex-1",children:[i2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),i2("div",{className:"text-[13px] text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.tags.length>0&&i2("div",{className:"flex gap-1 flex-shrink-0",children:A.tags.map((Q)=>i2("span",{className:"text-[11px] px-2 py-0.5 bg-theme rounded-md text-theme-muted",children:Q},Q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),JI6=({label:A,value:Q,valueClassName:w})=>i2("div",{className:"flex justify-between text-[13px]",children:[i2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),i2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),OE2=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:$,about:B,skills:X,notes:Y}=A,Z=eb0($.url),W=$.status==="approved",K=$.status==="archived";return i2(VI6,{children:[i2(Nw,{title:$.name,description:B||`Agent profile for ${$.name}`},void 0,!1,void 0,this),i2("article",{className:"agent-detail",children:i2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[i2("a",{href:"/agents",className:"text-sm text-theme-muted hover:text-brand transition-colors mb-6 inline-block",children:"\u2190 Back to Directory"},void 0,!1,void 0,this),i2("div",{className:"flex items-start gap-6 mb-8",children:[i2(Ak0,{name:$.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),i2("div",{children:[i2("div",{className:"flex items-center gap-3 mb-1",children:[i2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:$.name},void 0,!1,void 0,this),i2(Qk0,{kind:$.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"text-base text-theme-muted mb-2",children:$.brainName},void 0,!1,void 0,this),i2("div",{className:"flex items-center gap-3 text-theme-muted",children:[$.organization&&i2("span",{className:"text-[15px]",children:$.organization},void 0,!1,void 0,this),$.organization&&i2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),i2("span",{className:"text-sm",children:["Discovered ",qI6($.discoveredAt)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!W&&i2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[i2("div",{className:"text-sm font-semibold text-heading mb-1",children:K?"Archived contact":"Saved for review"},void 0,!1,void 0,this),i2("p",{className:"text-sm text-theme-muted",children:K?"This brain is retained as history and cannot be called unless it is approved again.":"This brain is discovered but not approved yet, so it cannot be called until you approve it."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"flex flex-col md:flex-row gap-12",children:[i2("div",{className:"flex-[2] min-w-0",children:[B&&i2("section",{className:"mb-8",children:[i2(U80,{children:"About"},void 0,!1,void 0,this),i2("p",{className:"text-[15px] text-theme leading-relaxed",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X.length>0&&i2("section",{className:"mb-8",children:[i2(U80,{children:"Skills"},void 0,!1,void 0,this),i2("div",{className:"flex flex-col gap-2.5",children:X.map((U)=>i2(zI6,{skill:U},U.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&i2("section",{className:"mb-8",children:[i2(U80,{children:"Notes"},void 0,!1,void 0,this),i2("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("aside",{className:"flex-1 md:pl-8 md:border-l border-theme-muted/20",children:[i2("section",{className:"mb-8",children:[i2(U80,{children:"Brain"},void 0,!1,void 0,this),i2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[i2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:$.brainName},void 0,!1,void 0,this),$.did&&i2("div",{className:"text-xs text-theme-muted font-mono",children:$.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("section",{className:"mb-8",children:[i2(U80,{children:"Connection"},void 0,!1,void 0,this),i2("div",{className:"flex flex-col gap-3",children:[i2("div",{children:[i2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),i2("div",{className:"text-xs text-heading font-mono",children:$.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2(JI6,{label:"Status",value:$.status==="approved"?"Approved":$.status==="archived"?"Archived":"Discovered",valueClassName:$.status==="approved"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("a",{href:$.url.replace(/\/a2a\/?$/,""),target:"_blank",rel:"noopener noreferrer",className:"flex items-center justify-center px-5 py-3 bg-theme-dark text-theme-inverse rounded-lg text-sm font-medium hover:opacity-90 transition-opacity",children:["Visit ",Z," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&i2("nav",{className:"mt-12 pt-6 border-t border-theme flex flex-col gap-3 md:flex-row md:items-center md:justify-between",children:[i2("div",{className:"min-h-[1px]",children:Q&&i2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[i2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),i2("span",{className:"text-heading font-medium",children:Q.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),i2("div",{className:"min-h-[1px] md:text-right",children:w&&i2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[i2("span",{children:"Next \u2192"},void 0,!1,void 0,this),i2("span",{className:"text-heading font-medium",children:w.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};z9();import{jsxDEV as C$}from"preact/jsx-dev-runtime";var FI6=`
|
|
10514
|
+
`)}function HI6(A){let Q=A.record.brain.did,w=A.record.anchor.did;return{agentId:A.agent.id,name:A.agent.metadata.name,url:A.agent.metadata.url,status:A.agent.metadata.status,repoDid:A.repoDid,...Q&&{brainDid:Q},...w&&{anchorDid:w},cardUri:A.uri,cardCid:A.cid}}async function WI6(A,Q,w){await A.messaging.send({type:Q,payload:w,broadcast:!0})}async function KI6(A,Q,w=new Date().toISOString()){let{record:$}=Q,B=YI6($.siteUrl),X=await A.entityService.getEntity({entityType:"agent",id:B}),Y=X?_E2.parseEntity(X):void 0,Z=$.brain.did,W=$.anchor.did,K=XI6($),U=X?.metadata.status??"discovered",G=X?.metadata.url??$.siteUrl,D=X?.metadata.slug??Hy(G),z=X?.metadata.name??$.anchor.name,V=Y?.frontmatter.kind??$.anchor.kind,I=X?.metadata.discoveredAt??w,F=$.brain.purpose.length>0?$.brain.purpose:Y?.body.about??"",_=K.length>0?K:Y?.body.skills??[],k={...X?.metadata??{},name:z,url:G,status:U,discoveredAt:I,slug:D,repoDid:Q.repoDid,...Z&&{brainDid:Z},...W&&{anchorDid:W},cardUri:Q.uri,cardCid:Q.cid},b=_E2.createAgentContent({name:z,kind:V,...Y?.frontmatter.organization&&{organization:Y.frontmatter.organization},brainName:$.brain.name,url:G,...Z&&{did:Z,brainDid:Z},...W&&{anchorDid:W},repoDid:Q.repoDid,cardUri:Q.uri,cardCid:Q.cid,...Y?.frontmatter.a2aEndpoint&&{a2aEndpoint:Y.frontmatter.a2aEndpoint},status:U,discoveredAt:I,about:F,skills:_,notes:ZI6({repoDid:Q.repoDid,uri:Q.uri,cid:Q.cid})});if(X){let R={...X,content:b,metadata:k,updated:w};return await A.entityService.updateEntity({entity:R}),{agent:R,created:!1}}let f={id:B,entityType:"agent",content:b,metadata:k,contentHash:"",visibility:"public",created:w,updated:w};return await A.entityService.createEntity({entity:f}),{agent:f,created:!0}}function bE2(A){A.messaging.subscribe(eQ0,async(Q)=>{let w=q9A.parse(Q.payload),$=await KI6(A,w),B=HI6({agent:$.agent,repoDid:w.repoDid,uri:w.uri,cid:w.cid,record:w.record});return await WI6(A,$.created?G9A:D9A,B),{success:!0,data:B}})}function kE2(){return["Agent entities are saved peer contacts. List them with system_list on entityType agent.","For an expertise match or recommendation, immediately run one system_search scoped to entityType agent using the requested topic. Suggest only clear matches, naming the contact and exact callable id/domain with brief supporting evidence. Prefer approved contacts; label discovered contacts as unverified; never recommend archived contacts. If none qualifies, say \u201CI couldn't find a clear match in your saved agent network for <topic>\u201D rather than suggesting a generic role. A short affirmative reply to an offer to search means run that search using the prior topic.","Route contact changes by intent: agent_connect verifies and saves a new domain/URL as an approved outbound contact; system_update changes the lifecycle status of an existing contact; agent_set_trust_level is the only tool for granting or revoking inbound A2A trust. Revocation uses level public and needs no key fingerprint or preliminary entity lookup.","If agent_call cannot reach an unsaved exact domain, offer to connect it; a short affirmative follow-up should call agent_connect for that domain. Only approved contacts can be called.","To call a contact named by person, anchor, or display name, first resolve it with one system_search scoped to entityType agent, then call agent_call with the returned entity id/domain\u2014not the display, anchor, or brain name. Skip search only when the user supplied an exact domain-like id."].join(" ")}y8();b0();import{jsxDEV as PE2}from"preact/jsx-dev-runtime";function eb0(A){try{return new URL(A).hostname}catch{return A}}var Ak0=({name:A,className:Q=""})=>{let w=A.charAt(0).toUpperCase(),$=0;for(let X=0;X<A.length;X++)$=A.charCodeAt(X)+(($<<5)-$);let B=Math.abs($)%360;return PE2("div",{className:`flex items-center justify-center rounded-full text-white font-bold flex-shrink-0 ${Q}`,style:{backgroundColor:`hsl(${B}, 55%, 45%)`},children:w},void 0,!1,void 0,this)},Qk0=({kind:A,size:Q="md"})=>{let $={professional:"bg-status-success text-status-success",team:"bg-status-info text-status-info",collective:"bg-brand/10 text-brand"}[A]??"bg-status-neutral text-status-neutral";return PE2("span",{className:`inline-flex items-center rounded-full font-medium ${Q==="sm"?"px-2 py-0.5 text-xs":"px-2.5 py-0.5 text-[13px]"} ${$}`,children:A},void 0,!1,void 0,this)};import{jsxDEV as x2,Fragment as DI6}from"preact/jsx-dev-runtime";var UI6=({skills:A})=>{if(A.length===0)return null;return x2("div",{className:"flex gap-1.5 flex-wrap mt-2",children:A.map((Q)=>x2("span",{className:"text-[11px] px-2 py-0.5 bg-theme-subtle rounded-md text-theme-muted",children:Q.name},Q.name,!1,void 0,this))},void 0,!1,void 0,this)};function GI6(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric"})}function ME2(A,Q,w){let $=new URLSearchParams({status:Q});if(w>1)$.set("page",String(w));return`${A}?${$.toString()}`}var wk0=({agent:A})=>{let{frontmatter:Q,about:w,skills:$,url:B}=A,X=Q.status==="approved",Y=Q.status==="archived";return x2("a",{href:B,className:`flex flex-wrap items-start gap-4 rounded-xl border border-theme bg-theme-subtle p-4 transition-shadow hover:shadow-lg sm:gap-5 sm:p-6 ${X?"":Y?"opacity-40":"opacity-70"}`,children:[x2(Ak0,{name:Q.name,className:"w-12 h-12 text-lg"},void 0,!1,void 0,this),x2("div",{className:"flex-1 min-w-0",children:[x2("div",{className:"flex items-center gap-2 mb-1 flex-wrap",children:[x2("span",{className:"text-lg font-semibold text-heading",children:Q.name},void 0,!1,void 0,this),x2(Qk0,{kind:Q.kind,size:"sm"},void 0,!1,void 0,this),Q.organization&&x2("span",{className:"text-xs text-theme-muted",children:["\xB7 ",Q.organization]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"text-sm text-theme-muted mb-1",children:Q.brainName},void 0,!1,void 0,this),w&&x2("p",{className:"text-sm text-theme-muted line-clamp-2 mb-0",children:w},void 0,!1,void 0,this),X&&x2(UI6,{skills:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex w-full flex-row flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5 sm:w-auto sm:shrink-0 sm:flex-col sm:items-end sm:gap-1 sm:text-right",children:[x2("span",{className:"text-xs text-theme-muted",children:eb0(Q.url)},void 0,!1,void 0,this),x2("span",{className:"text-[11px] text-theme-muted opacity-60",children:X?`Discovered ${GI6(Q.discoveredAt)}`:Y?"Archived \xB7 cannot be called":"Discovered \xB7 approve before calling"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},jE2=({agents:A,pageTitle:Q,pagination:w,baseUrl:$="/agents",selectedStatus:B})=>{let X=Q??"Agent Directory",Y=w?.totalItems??A.length,Z=A.filter((V)=>V.frontmatter.status==="approved"),W=A.filter((V)=>V.frontmatter.status==="discovered"),K=A.filter((V)=>V.frontmatter.status==="archived"),U=Z.length,G=W.length,D=K.length,z=`Your network of ${Y} ${Y===1?"brain":"brains"} and their anchors`;return x2(DI6,{children:[x2(Nw,{title:X,description:z},void 0,!1,void 0,this),x2("div",{className:"agent-list bg-theme",children:x2("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[x2("div",{className:"mb-8 pb-6 border-b border-theme",children:[x2("h1",{className:"text-4xl font-bold text-heading mb-2",children:X},void 0,!1,void 0,this),x2("p",{className:"text-theme-muted mb-4",children:z},void 0,!1,void 0,this),x2("div",{className:"flex flex-wrap gap-2 text-sm mb-4",children:[x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-heading",children:[Y," total"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-status-success",children:[U," approved"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted",children:[G," discovered"]},void 0,!0,void 0,this),x2("span",{className:"px-3 py-1 rounded-full bg-theme-subtle text-theme-muted opacity-60",children:[D," archived"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-wrap gap-2 text-sm",children:[x2("a",{href:$,className:`px-3 py-1 rounded-full border transition-colors ${B==="all"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"All"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=approved`,className:`px-3 py-1 rounded-full border transition-colors ${B==="approved"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Approved"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=discovered`,className:`px-3 py-1 rounded-full border transition-colors ${B==="discovered"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Discovered"},void 0,!1,void 0,this),x2("a",{href:`${$}?status=archived`,className:`px-3 py-1 rounded-full border transition-colors ${B==="archived"?"border-theme text-heading bg-theme-subtle":"border-theme text-theme-muted hover:text-heading"}`,children:"Archived"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),B==="all"&&Z.length>0&&x2("section",{className:"mb-10",children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Approved brains"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:Z.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:Z.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B==="all"&&W.length>0&&x2("section",{children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("div",{children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Discovered brains"},void 0,!1,void 0,this),x2("p",{className:"text-sm text-theme-muted",children:"Review and approve these before calling them."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:W.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:W.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B==="all"&&K.length>0&&x2("section",{className:"mt-10 opacity-60",children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("div",{children:[x2("h2",{className:"text-lg font-semibold text-heading",children:"Archived brains"},void 0,!1,void 0,this),x2("p",{className:"text-sm text-theme-muted",children:"Retained as history and unavailable for calling."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:K.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:K.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),B!=="all"&&A.length>0&&x2("section",{children:[x2("div",{className:"flex items-center justify-between mb-4",children:[x2("h2",{className:"text-lg font-semibold text-heading",children:B==="approved"?"Approved brains":B==="archived"?"Archived brains":"Discovered brains"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:A.length},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x2("div",{className:"flex flex-col gap-4",children:A.map((V)=>x2(wk0,{agent:V},V.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length===0&&x2("p",{className:"text-center text-theme-muted py-16",children:"No agents in your directory yet."},void 0,!1,void 0,this),w&&w.totalPages>1&&B==="all"&&x2("div",{className:"mt-12",children:x2(F_,{currentPage:w.currentPage,totalPages:w.totalPages,baseUrl:$},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&w.totalPages>1&&B!=="all"&&x2("nav",{"aria-label":"Pagination",className:"flex items-center justify-center gap-3 mt-12",children:[w.hasPrevPage?x2("a",{href:ME2($,B,w.currentPage-1),className:"px-4 py-2.5 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"\u2190 Prev"},void 0,!1,void 0,this):x2("span",{className:"px-4 py-2.5 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"\u2190 Prev"},void 0,!1,void 0,this),x2("span",{className:"text-sm text-theme-muted",children:["Page ",w.currentPage," of ",w.totalPages]},void 0,!0,void 0,this),w.hasNextPage?x2("a",{href:ME2($,B,w.currentPage+1),className:"px-4 py-2.5 rounded-md border border-theme text-sm text-theme-muted hover:text-heading transition-colors",children:"Next \u2192"},void 0,!1,void 0,this):x2("span",{className:"px-4 py-2.5 rounded-md border border-theme text-sm text-theme-muted opacity-50",children:"Next \u2192"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as i2,Fragment as VI6}from"preact/jsx-dev-runtime";function qI6(A){return new Date(A).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}var U80=({children:A})=>i2("h2",{className:"text-sm font-semibold text-theme-muted uppercase tracking-wide mb-3",children:A},void 0,!1,void 0,this),zI6=({skill:A})=>i2("div",{className:"flex flex-wrap items-start gap-3 px-4 py-3 bg-theme-subtle rounded-lg",children:[i2("div",{className:"flex-1 min-w-[16rem]",children:[i2("div",{className:"text-sm font-semibold text-heading",children:A.name},void 0,!1,void 0,this),i2("div",{className:"text-[13px] text-theme-muted",children:A.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.tags.length>0&&i2("div",{className:"flex flex-wrap gap-1",children:A.tags.map((Q)=>i2("span",{className:"text-[11px] px-2 py-0.5 bg-theme rounded-md text-theme-muted",children:Q},Q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),JI6=({label:A,value:Q,valueClassName:w})=>i2("div",{className:"flex justify-between text-[13px]",children:[i2("span",{className:"text-theme-muted",children:A},void 0,!1,void 0,this),i2("span",{className:w??"text-heading",children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this),OE2=({agent:A,prevAgent:Q,nextAgent:w})=>{let{frontmatter:$,about:B,skills:X,notes:Y}=A,Z=eb0($.url),W=$.status==="approved",K=$.status==="archived";return i2(VI6,{children:[i2(Nw,{title:$.name,description:B||`Agent profile for ${$.name}`},void 0,!1,void 0,this),i2("article",{className:"agent-detail",children:i2("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:[i2("a",{href:"/agents",className:"text-sm text-theme-muted hover:text-brand transition-colors mb-6 inline-block",children:"\u2190 Back to Directory"},void 0,!1,void 0,this),i2("div",{className:"flex flex-col items-start gap-4 mb-8 sm:flex-row sm:gap-6",children:[i2(Ak0,{name:$.name,className:"w-[72px] h-[72px] text-3xl"},void 0,!1,void 0,this),i2("div",{children:[i2("div",{className:"flex flex-wrap items-center gap-3 mb-1",children:[i2("h1",{className:"text-3xl md:text-4xl font-bold text-heading",children:$.name},void 0,!1,void 0,this),i2(Qk0,{kind:$.kind},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"text-base text-theme-muted mb-2",children:$.brainName},void 0,!1,void 0,this),i2("div",{className:"flex items-center gap-3 text-theme-muted",children:[$.organization&&i2("span",{className:"text-[15px]",children:$.organization},void 0,!1,void 0,this),$.organization&&i2("span",{className:"text-theme-muted opacity-40",children:"\xB7"},void 0,!1,void 0,this),i2("span",{className:"text-sm",children:["Discovered ",qI6($.discoveredAt)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"border-b border-theme mb-8"},void 0,!1,void 0,this),!W&&i2("div",{className:"mb-8 rounded-xl border border-theme bg-theme-subtle px-5 py-4",children:[i2("div",{className:"text-sm font-semibold text-heading mb-1",children:K?"Archived contact":"Saved for review"},void 0,!1,void 0,this),i2("p",{className:"text-sm text-theme-muted",children:K?"This brain is retained as history and cannot be called unless it is approved again.":"This brain is discovered but not approved yet, so it cannot be called until you approve it."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("div",{className:"flex flex-col md:flex-row gap-12",children:[i2("div",{className:"flex-[2] min-w-0",children:[B&&i2("section",{className:"mb-8",children:[i2(U80,{children:"About"},void 0,!1,void 0,this),i2("p",{className:"text-[15px] text-theme leading-relaxed",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this),X.length>0&&i2("section",{className:"mb-8",children:[i2(U80,{children:"Skills"},void 0,!1,void 0,this),i2("div",{className:"flex flex-col gap-2.5",children:X.map((U)=>i2(zI6,{skill:U},U.name,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y&&i2("section",{className:"mb-8",children:[i2(U80,{children:"Notes"},void 0,!1,void 0,this),i2("p",{className:"text-[15px] text-theme leading-relaxed",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("aside",{className:"flex-1 border-t border-theme-muted/20 pt-8 md:border-t-0 md:pt-0 md:pl-8 md:border-l",children:[i2("section",{className:"mb-8",children:[i2(U80,{children:"Brain"},void 0,!1,void 0,this),i2("div",{className:"p-4 bg-theme-subtle rounded-xl",children:[i2("div",{className:"text-[15px] font-semibold text-heading mb-1",children:$.brainName},void 0,!1,void 0,this),$.did&&i2("div",{className:"text-xs text-theme-muted font-mono",children:$.did},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("section",{className:"mb-8",children:[i2(U80,{children:"Connection"},void 0,!1,void 0,this),i2("div",{className:"flex flex-col gap-3",children:[i2("div",{children:[i2("div",{className:"text-[13px] text-theme-muted mb-0.5",children:"Endpoint"},void 0,!1,void 0,this),i2("div",{className:"text-xs text-heading font-mono break-all",children:$.url},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2(JI6,{label:"Status",value:$.status==="approved"?"Approved":$.status==="archived"?"Archived":"Discovered",valueClassName:$.status==="approved"?"text-status-success font-medium":"text-theme-muted"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),i2("a",{href:$.url.replace(/\/a2a\/?$/,""),target:"_blank",rel:"noopener noreferrer",className:"flex items-center justify-center px-5 py-3 bg-theme-dark text-theme-inverse rounded-lg text-sm font-medium hover:opacity-90 transition-opacity",children:["Visit ",Z," \u2197"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),(Q??w)&&i2("nav",{className:"mt-12 pt-6 border-t border-theme flex flex-col gap-3 md:flex-row md:items-center md:justify-between",children:[i2("div",{className:"min-h-[1px]",children:Q&&i2("a",{href:Q.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[i2("span",{children:"\u2190 Previous"},void 0,!1,void 0,this),i2("span",{className:"text-heading font-medium",children:Q.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),i2("div",{className:"min-h-[1px] md:text-right",children:w&&i2("a",{href:w.url,className:"inline-flex flex-col text-sm text-theme-muted hover:text-heading transition-colors",children:[i2("span",{children:"Next \u2192"},void 0,!1,void 0,this),i2("span",{className:"text-heading font-medium",children:w.frontmatter.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};z9();import{jsxDEV as C$}from"preact/jsx-dev-runtime";var FI6=`
|
|
10497
10515
|
.agent-proximity-site {
|
|
10498
10516
|
--console-accent: var(--color-accent, var(--color-brand, #b45309));
|
|
10499
10517
|
--console-secondary: var(--color-secondary, #7653a6);
|
|
@@ -10796,7 +10814,7 @@ ${A.guidance}`:B}}function Dh2(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10796
10814
|
/* the shimmer delay is inlined per node, so the override needs force */
|
|
10797
10815
|
.agent-proximity-site .proximity-agent { animation: none !important; }
|
|
10798
10816
|
}
|
|
10799
|
-
`,Ki={kicker:"Agent network",headingLead:"The rhizome grows",headingAccent:"beneath this brain",lede:"Every agent this brain has met, mapped by how close its work runs to ours \u2014 distance measured in meaning, not geography. Threads thicken where practices touch; where several lights gather, a constellation forms.",ctaLabel:"Meet the agents",ctaHref:"/agents"};function B3A(A){let Q=A.nodes.filter((K)=>K.status!=="archived").length,w=A.nodes.length-Q,$=A.kicker??Ki.kicker,B=A.headingLead??Ki.headingLead,X=A.headingAccent??Ki.headingAccent,Y=A.lede??Ki.lede,Z=A.ctaLabel??Ki.ctaLabel,W=A.ctaHref??Ki.ctaHref;return C$("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[C$("style",{children:FI6},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__grid",children:[C$("div",{class:"agent-proximity-site__copy",children:[C$("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),C$("h2",{class:"agent-proximity-site__heading",children:[B," ",C$("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),C$("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),C$("a",{class:"agent-proximity-site__cta",href:W,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&C$("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&C$("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),C$("div",{class:"agent-proximity-site__map",children:C$(tb0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[C$("span",{children:[C$("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),C$("span",{children:[C$("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),C$("span",{children:[C$("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),C$("span",{children:[C$("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 II6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),LI6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),NI6=H.object({name:H.string(),description:H.string(),tags:H.array(H.string())}),X3A=H.enum(["discovered","approved","archived"]),_I6=H.enum(["professional","team","collective"]),bI6=H.object({name:H.string(),kind:_I6,organization:H.string().optional(),brainName:H.string(),url:H.url(),did:H.string().optional(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.url().optional(),status:X3A,discoveredAt:H.string()}),kI6=H.object({name:H.string(),url:H.url(),status:X3A,discoveredAt:H.string().optional(),slug:H.string(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.url().optional()}),$k0=H.object({id:H.string(),entityType:H.literal(o$),content:H.string(),created:H.string(),updated:H.string(),visibility:II6,metadata:kI6,contentHash:H.string(),frontmatter:bI6,about:H.string(),skills:H.array(NI6),notes:H.string(),url:H.string().optional(),typeLabel:H.string().optional()}),PI6=H.object({agents:H.array($k0),pageTitle:H.string().optional(),pagination:LI6.nullable(),baseUrl:H.string().optional(),selectedStatus:H.union([H.literal("all"),X3A])}),fE2="/scripts/agent-proximity-map.js",MI6=new R6(XE2,{title:"Network",mappings:[{key:"kicker",label:"Kicker",type:"string"},{key:"headingLead",label:"Heading Lead",type:"string"},{key:"headingAccent",label:"Heading Accent",type:"string"},{key:"lede",label:"Lede",type:"string"},{key:"ctaLabel",label:"Cta Label",type:"string"},{key:"ctaHref",label:"Cta Href",type:"string"}]});function xE2(){return{[rGA]:$2({name:rGA,description:"Semantic agent proximity map site section",schema:u_,dataSourceId:ub0,overlayFormatter:MI6,requiredPermission:"public",runtimeScripts:[{src:fE2,defer:!0}],staticAssets:{[fE2]:Wi},layout:{component:B3A}}),[oGA]:$2({name:oGA,description:"Agent directory list page template",schema:PI6,dataSourceId:Y80,requiredPermission:"public",layout:{component:jE2}}),[sGA]:$2({name:sGA,description:"Individual agent profile template",schema:H.object({agent:$k0,prevAgent:$k0.nullable(),nextAgent:$k0.nullable()}),dataSourceId:Y80,requiredPermission:"public",layout:{component:OE2}})}}var Ui={name:"@brains/agent-discovery",version:"0.2.0-alpha.180",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 OI6=new R7;class Y3A extends jw{entityType=o$;schema=Z80;adapter=OI6;constructor(){super(ch2,Ui,{},yX)}createGenerationHandler(A){return new eGA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return xE2()}getDataSources(){return[new lb0(this.logger.child("AgentDataSource")),new ib0]}async onRegister(A){bE2(A),NE2(A,this.id)}async getInstructions(){return kE2()}}function Z3A(){return new Y3A}$A();wH();b0();$4();b0();var RE2=H.object({source:H.object({kind:H.literal("url"),url:H.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:H.boolean().optional(),confirmationToken:H.string().optional()}),fI6=new R7;function xI6(A){let Q=c_(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function RI6(A,Q){return(c_(Q)||A).toLowerCase()}async function vI6(A){let{context:Q,entityId:w,card:$}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:o$,id:w}),Y=Hi($,{status:"approved"}),W={...fI6.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:$.url};if(X){let U={...X,content:Y.content,metadata:W,updated:B};return await Q.entityService.updateEntity({entity:U}),{entity:U,created:!1}}let K={id:w,entityType:o$,content:Y.content,metadata:W,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function vE2(A,Q=globalThis.fetch){let $=new SK;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:RE2.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=RE2.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((U)=>`${U.path.join(".")}: ${U.message}`).join(", ")}`};let Z=Y.data,W=xI6(Z.source.url);if(!W)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(o$,"create",X)}catch(U){return{success:!1,error:U instanceof Error?U.message:String(U)}}if(Z.confirmed){let U=Z.confirmationToken,G=$.validate(U,Z);if(G.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await Zi(W.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${W.domain}.`,code:"not_an_agent"};let z=RI6(W.domain,D.url),{entity:V,created:I}=await vI6({context:A,entityId:z,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:I,a2aEndpoint:D.url,skills:D.skills.map((F)=>({name:F.name,description:F.description,tags:F.tags}))}}}let K=$.create((U)=>({source:Z.source,confirmed:!0,confirmationToken:U}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${W.domain}?`,preview:`This will fetch and validate ${W.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:K}}}}b0();var CE2=H.object({}),CI6=H.object({agents:H.array(H.object({name:H.string(),url:H.string()}))}),H3A=new R7;async function hI6(A,Q,w){let $=`https://${A}/.well-known/agent-directory.json`;try{let B=await Q($,w?{signal:w}:void 0);if(!B.ok)return null;let X=CI6.safeParse(await B.json());return X.success?X.data:null}catch{if(w?.aborted)throw w.reason;return null}}async function W3A(A,Q=globalThis.fetch,w){let $=await A.entityService.listEntities({entityType:o$}),B=$.filter((F)=>F.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let F of B){w?.throwIfAborted();let _=await hI6(F.id,Q,w);if(!_){Z+=1;continue}for(let k of _.agents){let b=c_(k.url).toLowerCase();if(!b||b===X||b===F.id)continue;let f=Y.get(b)??new Set;f.add(F.id),Y.set(b,f)}}let W=new Map($.map((F)=>[F.id,F])),K=new Date().toISOString(),U=[],G=new Set,D=0,z=0,V=0,I=0;for(let[F,_]of Y){w?.throwIfAborted();let k=W.get(F);if(k){let{frontmatter:v,body:M}=H3A.parseEntity(k),y=v.introducedBy??[];if(v.status!=="discovered"||y.length===0){V+=1;continue}let S=[...y,...[..._].filter((l)=>!y.includes(l))];if(S.length===y.length)continue;await A.entityService.updateEntity({entity:{...k,content:H3A.createAgentContent({...v,introducedBy:S,about:M.about,skills:M.skills,notes:M.notes}),updated:K}}),z+=1;continue}let b=await Zi(F,Q,w);if(!b){I+=1;continue}let f=Hi(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),R=H3A.fromMarkdown(f.content);await A.entityService.createEntity({entity:{id:F,entityType:o$,content:f.content,metadata:{...R.metadata,...f.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(F);for(let v of _)G.add(v)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:z,alreadyKnown:V,unverified:I,createdDomains:U,introducingPeers:[...G],observedAt:K}}function hE2(A,Q=globalThis.fetch){return{name:"agent_scan_directories",description:"Walk each approved agent's public directory at /.well-known/agent-directory.json and record second-order sightings: agents your peers list that you are not connected to. A sighting is saved as a discovered agent with provenance (which peers introduced it, hop count) and data from its own verified Agent Card. Re-scanning is idempotent: connected agents are skipped and repeat sightings only merge new introducers. Never approves anything; promotion stays with agent_connect.",inputSchema:CE2.shape,visibility:"trusted",sideEffects:"external",handler:async(w,$)=>{let B=CE2.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(o$,"create",$)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await W3A(A,Q,$.signal);return{success:!0,data:{peersScanned:X.peersScanned,unreachablePeers:X.unreachablePeers,created:X.created,updated:X.updated,alreadyKnown:X.alreadyKnown,unverified:X.unverified}}}}}$4();b0();var EI6=H.enum(["public","trusted"]),EE2=H.object({agent:H.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:EI6.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),keyFingerprint:H.string().optional()}),gI6=H.object({keys:H.array(H.unknown())}),yI6=H.object({kty:H.literal("OKP"),crv:H.literal("Ed25519"),x:H.string(),kid:H.string().optional(),alg:H.literal("EdDSA").optional()}).passthrough();function gE2(A){return(c_(A)||A.trim()).toLowerCase()}async function TI6(A,Q){let w=gE2(Q),$=await A.entityService.getEntity({entityType:o$,id:w});if(!$)return null;let B=gE2($.metadata.a2aEndpoint??$.metadata.url);if(!B)return null;return{domain:B}}async function SI6(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let $=gI6.safeParse(await w.json());if(!$.success)return null;let B=$.data.keys.map((X)=>yI6.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return X9A(B.data)}catch{return null}}function yE2(A,Q=globalThis.fetch){let $=new SK;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:EE2.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=EE2.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=pX();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await TI6(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let W=X.data;if(W.confirmed){let D=$.validate(W.confirmationToken,W);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(W.level==="trusted"){if(!W.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let z=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:W.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:z.grantedLevel,keyFingerprint:z.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let K=W.level==="trusted"?await SI6(Z.domain,Q):void 0;if(W.level==="trusted"&&!K)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let U=$.create((D)=>({agent:Z.domain,level:W.level,confirmed:!0,confirmationToken:D,...K?{keyFingerprint:K}:{}})),G=W.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:G?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:G?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${K}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${Z.domain}. The directory contact remains saved for outbound calls.`,args:U}}}}var mI6=H.object({}).strict();class K3A extends Rw{fetchFn;constructor(A){super("agent",Ui,{},mI6);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",run:async({signal:Q})=>{let w=await W3A(A,this.fetchFn,Q);if(w.created===0)return{};let $=[...w.createdDomains].sort(),B=[...w.introducingPeers].sort(),X=`${w.created} agent${w.created===1?"":"s"}`;return{alerts:[{dedupeKey:`sightings:${mw(`${w.observedAt}\x00${$.join("\x00")}`)}`,title:"New agent sightings",body:`${X} sighted through ${B.join(", ")}`}]}}})}async getTools(){return[vE2(this.getContext(),this.fetchFn),hE2(this.getContext(),this.fetchFn),yE2(this.getContext(),this.fetchFn)]}}function U3A(){return new K3A}$A();$A();b0();var GE=H.object({name:H.string(),description:H.string(),tags:H.array(H.string()),examples:H.array(H.string())}),TE2=GE,G80=n5.extend({entityType:H.literal(w9),metadata:TE2});$A();class Gi extends QQ{constructor(){super({entityType:w9,purpose:"A capability advertised by a remote agent.",schema:G80,frontmatterSchema:GE})}fromMarkdown(A){let Q=this.parseFrontMatter(A,GE);return{content:A,entityType:w9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}$A();b0();var uI6=H.object({skills:H.array(GE).max(8)}),SE2=$2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:uI6,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10817
|
+
`,Ki={kicker:"Agent network",headingLead:"The rhizome grows",headingAccent:"beneath this brain",lede:"Every agent this brain has met, mapped by how close its work runs to ours \u2014 distance measured in meaning, not geography. Threads thicken where practices touch; where several lights gather, a constellation forms.",ctaLabel:"Meet the agents",ctaHref:"/agents"};function B3A(A){let Q=A.nodes.filter((K)=>K.status!=="archived").length,w=A.nodes.length-Q,$=A.kicker??Ki.kicker,B=A.headingLead??Ki.headingLead,X=A.headingAccent??Ki.headingAccent,Y=A.lede??Ki.lede,Z=A.ctaLabel??Ki.ctaLabel,W=A.ctaHref??Ki.ctaHref;return C$("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[C$("style",{children:FI6},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__grid",children:[C$("div",{class:"agent-proximity-site__copy",children:[C$("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),C$("h2",{class:"agent-proximity-site__heading",children:[B," ",C$("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),C$("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{children:[C$("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),C$("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),C$("a",{class:"agent-proximity-site__cta",href:W,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&C$("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&C$("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),C$("div",{class:"agent-proximity-site__map",children:C$(tb0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),C$("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[C$("span",{children:[C$("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),C$("span",{children:[C$("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),C$("span",{children:[C$("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),C$("span",{children:[C$("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 II6=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),LI6=H.object({currentPage:H.number(),totalPages:H.number(),totalItems:H.number(),pageSize:H.number(),hasNextPage:H.boolean(),hasPrevPage:H.boolean()}),NI6=H.object({name:H.string(),description:H.string(),tags:H.array(H.string())}),X3A=H.enum(["discovered","approved","archived"]),_I6=H.enum(["professional","team","collective"]),bI6=H.object({name:H.string(),kind:_I6,organization:H.string().optional(),brainName:H.string(),url:H.url(),did:H.string().optional(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.url().optional(),status:X3A,discoveredAt:H.string()}),kI6=H.object({name:H.string(),url:H.url(),status:X3A,discoveredAt:H.string().optional(),slug:H.string(),repoDid:H.string().optional(),brainDid:H.string().optional(),anchorDid:H.string().optional(),cardUri:H.string().optional(),cardCid:H.string().optional(),a2aEndpoint:H.url().optional()}),$k0=H.object({id:H.string(),entityType:H.literal(o$),content:H.string(),created:H.string(),updated:H.string(),visibility:II6,metadata:kI6,contentHash:H.string(),frontmatter:bI6,about:H.string(),skills:H.array(NI6),notes:H.string(),url:H.string().optional(),typeLabel:H.string().optional()}),PI6=H.object({agents:H.array($k0),pageTitle:H.string().optional(),pagination:LI6.nullable(),baseUrl:H.string().optional(),selectedStatus:H.union([H.literal("all"),X3A])}),fE2="/scripts/agent-proximity-map.js",MI6=new R6(XE2,{title:"Network",mappings:[{key:"kicker",label:"Kicker",type:"string"},{key:"headingLead",label:"Heading Lead",type:"string"},{key:"headingAccent",label:"Heading Accent",type:"string"},{key:"lede",label:"Lede",type:"string"},{key:"ctaLabel",label:"Cta Label",type:"string"},{key:"ctaHref",label:"Cta Href",type:"string"}]});function xE2(){return{[rGA]:$2({name:rGA,description:"Semantic agent proximity map site section",schema:u_,dataSourceId:ub0,overlayFormatter:MI6,requiredPermission:"public",runtimeScripts:[{src:fE2,defer:!0}],staticAssets:{[fE2]:Wi},layout:{component:B3A}}),[oGA]:$2({name:oGA,description:"Agent directory list page template",schema:PI6,dataSourceId:Y80,requiredPermission:"public",layout:{component:jE2}}),[sGA]:$2({name:sGA,description:"Individual agent profile template",schema:H.object({agent:$k0,prevAgent:$k0.nullable(),nextAgent:$k0.nullable()}),dataSourceId:Y80,requiredPermission:"public",layout:{component:OE2}})}}var Ui={name:"@brains/agent-discovery",version:"0.2.0-alpha.181",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 OI6=new R7;class Y3A extends jw{entityType=o$;schema=Z80;adapter=OI6;constructor(){super(ch2,Ui,{},yX)}createGenerationHandler(A){return new eGA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return xE2()}getDataSources(){return[new lb0(this.logger.child("AgentDataSource")),new ib0]}async onRegister(A){bE2(A),NE2(A,this.id)}async getInstructions(){return kE2()}}function Z3A(){return new Y3A}$A();wH();b0();$4();b0();var RE2=H.object({source:H.object({kind:H.literal("url"),url:H.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:H.boolean().optional(),confirmationToken:H.string().optional()}),fI6=new R7;function xI6(A){let Q=c_(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function RI6(A,Q){return(c_(Q)||A).toLowerCase()}async function vI6(A){let{context:Q,entityId:w,card:$}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:o$,id:w}),Y=Hi($,{status:"approved"}),W={...fI6.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:$.url};if(X){let U={...X,content:Y.content,metadata:W,updated:B};return await Q.entityService.updateEntity({entity:U}),{entity:U,created:!1}}let K={id:w,entityType:o$,content:Y.content,metadata:W,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:K}),{entity:K,created:!0}}function vE2(A,Q=globalThis.fetch){let $=new SK;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:RE2.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=RE2.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((U)=>`${U.path.join(".")}: ${U.message}`).join(", ")}`};let Z=Y.data,W=xI6(Z.source.url);if(!W)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(o$,"create",X)}catch(U){return{success:!1,error:U instanceof Error?U.message:String(U)}}if(Z.confirmed){let U=Z.confirmationToken,G=$.validate(U,Z);if(G.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let D=await Zi(W.fetchTarget,Q);if(!D)return{success:!1,error:`Could not verify an A2A Agent Card for ${W.domain}.`,code:"not_an_agent"};let z=RI6(W.domain,D.url),{entity:V,created:I}=await vI6({context:A,entityId:z,sourceUrl:Z.source.url,card:D});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:I,a2aEndpoint:D.url,skills:D.skills.map((F)=>({name:F.name,description:F.description,tags:F.tags}))}}}let K=$.create((U)=>({source:Z.source,confirmed:!0,confirmationToken:U}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${W.domain}?`,preview:`This will fetch and validate ${W.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:K}}}}b0();var CE2=H.object({}),CI6=H.object({agents:H.array(H.object({name:H.string(),url:H.string()}))}),H3A=new R7;async function hI6(A,Q,w){let $=`https://${A}/.well-known/agent-directory.json`;try{let B=await Q($,w?{signal:w}:void 0);if(!B.ok)return null;let X=CI6.safeParse(await B.json());return X.success?X.data:null}catch{if(w?.aborted)throw w.reason;return null}}async function W3A(A,Q=globalThis.fetch,w){let $=await A.entityService.listEntities({entityType:o$}),B=$.filter((F)=>F.metadata.status==="approved"),X=A.domain?.toLowerCase(),Y=new Map,Z=0;for(let F of B){w?.throwIfAborted();let _=await hI6(F.id,Q,w);if(!_){Z+=1;continue}for(let k of _.agents){let b=c_(k.url).toLowerCase();if(!b||b===X||b===F.id)continue;let f=Y.get(b)??new Set;f.add(F.id),Y.set(b,f)}}let W=new Map($.map((F)=>[F.id,F])),K=new Date().toISOString(),U=[],G=new Set,D=0,z=0,V=0,I=0;for(let[F,_]of Y){w?.throwIfAborted();let k=W.get(F);if(k){let{frontmatter:v,body:M}=H3A.parseEntity(k),y=v.introducedBy??[];if(v.status!=="discovered"||y.length===0){V+=1;continue}let S=[...y,...[..._].filter((l)=>!y.includes(l))];if(S.length===y.length)continue;await A.entityService.updateEntity({entity:{...k,content:H3A.createAgentContent({...v,introducedBy:S,about:M.about,skills:M.skills,notes:M.notes}),updated:K}}),z+=1;continue}let b=await Zi(F,Q,w);if(!b){I+=1;continue}let f=Hi(b,{status:"discovered",provenance:{introducedBy:[..._],hops:2}}),R=H3A.fromMarkdown(f.content);await A.entityService.createEntity({entity:{id:F,entityType:o$,content:f.content,metadata:{...R.metadata,...f.metadata},visibility:"public",created:K,updated:K}}),D+=1,U.push(F);for(let v of _)G.add(v)}return{peersScanned:B.length,unreachablePeers:Z,created:D,updated:z,alreadyKnown:V,unverified:I,createdDomains:U,introducingPeers:[...G],observedAt:K}}function hE2(A,Q=globalThis.fetch){return{name:"agent_scan_directories",description:"Walk each approved agent's public directory at /.well-known/agent-directory.json and record second-order sightings: agents your peers list that you are not connected to. A sighting is saved as a discovered agent with provenance (which peers introduced it, hop count) and data from its own verified Agent Card. Re-scanning is idempotent: connected agents are skipped and repeat sightings only merge new introducers. Never approves anything; promotion stays with agent_connect.",inputSchema:CE2.shape,visibility:"trusted",sideEffects:"external",handler:async(w,$)=>{let B=CE2.safeParse(w);if(!B.success)return{success:!1,error:`Invalid input: ${B.error.message}`};try{A.permissions.assertEntityActionAllowed(o$,"create",$)}catch(Y){return{success:!1,error:Y instanceof Error?Y.message:String(Y)}}let X=await W3A(A,Q,$.signal);return{success:!0,data:{peersScanned:X.peersScanned,unreachablePeers:X.unreachablePeers,created:X.created,updated:X.updated,alreadyKnown:X.alreadyKnown,unverified:X.unverified}}}}}$4();b0();var EI6=H.enum(["public","trusted"]),EE2=H.object({agent:H.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:EI6.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:H.boolean().optional(),confirmationToken:H.string().optional(),keyFingerprint:H.string().optional()}),gI6=H.object({keys:H.array(H.unknown())}),yI6=H.object({kty:H.literal("OKP"),crv:H.literal("Ed25519"),x:H.string(),kid:H.string().optional(),alg:H.literal("EdDSA").optional()}).passthrough();function gE2(A){return(c_(A)||A.trim()).toLowerCase()}async function TI6(A,Q){let w=gE2(Q),$=await A.entityService.getEntity({entityType:o$,id:w});if(!$)return null;let B=gE2($.metadata.a2aEndpoint??$.metadata.url);if(!B)return null;return{domain:B}}async function SI6(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let $=gI6.safeParse(await w.json());if(!$.success)return null;let B=$.data.keys.map((X)=>yI6.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return X9A(B.data)}catch{return null}}function yE2(A,Q=globalThis.fetch){let $=new SK;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:EE2.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=EE2.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((D)=>`${D.path.join(".")}: ${D.message}`).join(", ")}`};let Y=pX();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await TI6(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let W=X.data;if(W.confirmed){let D=$.validate(W.confirmationToken,W);if(D.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(D.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(W.level==="trusted"){if(!W.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let z=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:W.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:z.grantedLevel,keyFingerprint:z.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let K=W.level==="trusted"?await SI6(Z.domain,Q):void 0;if(W.level==="trusted"&&!K)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let U=$.create((D)=>({agent:Z.domain,level:W.level,confirmed:!0,confirmationToken:D,...K?{keyFingerprint:K}:{}})),G=W.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:G?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:G?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${K}. It will not add or remove the directory contact.`:`This will revoke inbound trusted A2A access from ${Z.domain}. The directory contact remains saved for outbound calls.`,args:U}}}}var mI6=H.object({}).strict();class K3A extends Rw{fetchFn;constructor(A){super("agent",Ui,{},mI6);this.fetchFn=A}async onRegister(A){A.recurringChecks.register({id:"directory-scan",cadence:"daily",run:async({signal:Q})=>{let w=await W3A(A,this.fetchFn,Q);if(w.created===0)return{};let $=[...w.createdDomains].sort(),B=[...w.introducingPeers].sort(),X=`${w.created} agent${w.created===1?"":"s"}`;return{alerts:[{dedupeKey:`sightings:${mw(`${w.observedAt}\x00${$.join("\x00")}`)}`,title:"New agent sightings",body:`${X} sighted through ${B.join(", ")}`}]}}})}async getTools(){return[vE2(this.getContext(),this.fetchFn),hE2(this.getContext(),this.fetchFn),yE2(this.getContext(),this.fetchFn)]}}function U3A(){return new K3A}$A();$A();b0();var GE=H.object({name:H.string(),description:H.string(),tags:H.array(H.string()),examples:H.array(H.string())}),TE2=GE,G80=n5.extend({entityType:H.literal(w9),metadata:TE2});$A();class Gi extends QQ{constructor(){super({entityType:w9,purpose:"A capability advertised by a remote agent.",schema:G80,frontmatterSchema:GE})}fromMarkdown(A){let Q=this.parseFrontMatter(A,GE);return{content:A,entityType:w9,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}$A();b0();var uI6=H.object({skills:H.array(GE).max(8)}),SE2=$2({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:uI6,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10800
10818
|
|
|
10801
10819
|
Given knowledge domains, CONSOLIDATE related topics into broader skills.
|
|
10802
10820
|
There should be FEWER skills than topics \u2014 combine related domains.
|
|
@@ -10946,9 +10964,9 @@ Context:
|
|
|
10946
10964
|
${JSON.stringify($,null,2)}
|
|
10947
10965
|
|
|
10948
10966
|
Draft SWOT:
|
|
10949
|
-
${JSON.stringify(w,null,2)}`}function Uk0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function UL6(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let $ of w){let B=new Set(A[$].map((X)=>X.theme.trim().toLowerCase()));for(let X of Q[$]){let Y=X.sourceTheme.trim().toLowerCase();if(!B.has(Y))throw Error(`SWOT refinement invented theme "${X.sourceTheme}" in ${$}`)}}}class Gk0{logger;context;adapter=new p_;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=q3A.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let $=await I3A(this.context),B;if($.summary.brainSkillCount+$.summary.approvedAgentCount+$.summary.discoveredAgentCount===0)B={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:K}=await this.context.ai.generateObject(await HL6(this.context,$),z3A),U=z3A.parse(K);await w.report({progress:0.75,message:"Refining SWOT language"});let G=await this.context.ai.generateObject(await KL6(this.context,$,U),Hk0);B=Hk0.parse(G.object),UL6(U,B)}let Y=new Date().toISOString(),Z=this.adapter.createSwotContent({strengths:Uk0(B.strengths),weaknesses:Uk0(B.weaknesses),opportunities:Uk0(B.opportunities),threats:Uk0(B.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let W=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(W)await this.context.entityService.updateEntity({entity:{...W,content:Z,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:Z,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:$.summary.brainSkillCount,approvedAgentCount:$.summary.approvedAgentCount,discoveredAgentCount:$.summary.discoveredAgentCount}),{entityId:"swot"}}}b0();import{jsxDEV as FZ}from"preact/jsx-dev-runtime";var Dk0=H.object({title:H.string(),detail:H.string().optional()}),GL6=H.discriminatedUnion("status",[H.object({status:H.literal("generating")}),H.object({status:H.literal("ready"),strengths:H.array(Dk0).default([]),weaknesses:H.array(Dk0).default([]),opportunities:H.array(Dk0).default([]),threats:H.array(Dk0).default([]),derivedAt:H.string()})]);function DL6({items:A}){if(A.length===0)return FZ("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return FZ("ul",{class:"swot-list",children:A.map((Q)=>FZ("li",{class:"swot-item",children:[FZ("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?FZ("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 qk0({title:A,tone:Q,items:w}){return FZ("section",{class:`swot-cell is-${Q}`,children:[FZ("div",{class:"swot-head",children:A},void 0,!1,void 0,this),FZ(DL6,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _3A({data:A}){let Q=GL6.safeParse(A);if(!Q.success||Q.data.status==="generating")return FZ("div",{"data-swot-widget":!0,children:FZ("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return FZ("div",{"data-swot-widget":!0,children:FZ("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[FZ(qk0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),FZ(qk0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),FZ(qk0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),FZ(qk0,{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 b3A={name:"@brains/assessment",version:"0.2.0-alpha.
|
|
10967
|
+
${JSON.stringify(w,null,2)}`}function Uk0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function UL6(A,Q){let w=["strengths","weaknesses","opportunities","threats"];for(let $ of w){let B=new Set(A[$].map((X)=>X.theme.trim().toLowerCase()));for(let X of Q[$]){let Y=X.sourceTheme.trim().toLowerCase();if(!B.has(Y))throw Error(`SWOT refinement invented theme "${X.sourceTheme}" in ${$}`)}}}class Gk0{logger;context;adapter=new p_;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=q3A.safeParse(A??{});return Q.success?Q.data:null}async process(A,Q,w){await w.report({progress:0.2,message:"Building SWOT context"});let $=await I3A(this.context),B;if($.summary.brainSkillCount+$.summary.approvedAgentCount+$.summary.discoveredAgentCount===0)B={strengths:[],weaknesses:[],opportunities:[],threats:[]};else{await w.report({progress:0.6,message:"Synthesizing SWOT analysis"});let{object:K}=await this.context.ai.generateObject(await HL6(this.context,$),z3A),U=z3A.parse(K);await w.report({progress:0.75,message:"Refining SWOT language"});let G=await this.context.ai.generateObject(await KL6(this.context,$,U),Hk0);B=Hk0.parse(G.object),UL6(U,B)}let Y=new Date().toISOString(),Z=this.adapter.createSwotContent({strengths:Uk0(B.strengths),weaknesses:Uk0(B.weaknesses),opportunities:Uk0(B.opportunities),threats:Uk0(B.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let W=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(W)await this.context.entityService.updateEntity({entity:{...W,content:Z,metadata:{derivedAt:Y}}});else await this.context.entityService.createEntity({entity:{id:"swot",entityType:"swot",content:Z,metadata:{derivedAt:Y}}});return this.logger.info("SWOT derivation complete",{derivedAt:Y,brainSkillCount:$.summary.brainSkillCount,approvedAgentCount:$.summary.approvedAgentCount,discoveredAgentCount:$.summary.discoveredAgentCount}),{entityId:"swot"}}}b0();import{jsxDEV as FZ}from"preact/jsx-dev-runtime";var Dk0=H.object({title:H.string(),detail:H.string().optional()}),GL6=H.discriminatedUnion("status",[H.object({status:H.literal("generating")}),H.object({status:H.literal("ready"),strengths:H.array(Dk0).default([]),weaknesses:H.array(Dk0).default([]),opportunities:H.array(Dk0).default([]),threats:H.array(Dk0).default([]),derivedAt:H.string()})]);function DL6({items:A}){if(A.length===0)return FZ("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return FZ("ul",{class:"swot-list",children:A.map((Q)=>FZ("li",{class:"swot-item",children:[FZ("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?FZ("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 qk0({title:A,tone:Q,items:w}){return FZ("section",{class:`swot-cell is-${Q}`,children:[FZ("div",{class:"swot-head",children:A},void 0,!1,void 0,this),FZ(DL6,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function _3A({data:A}){let Q=GL6.safeParse(A);if(!Q.success||Q.data.status==="generating")return FZ("div",{"data-swot-widget":!0,children:FZ("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return FZ("div",{"data-swot-widget":!0,children:FZ("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[FZ(qk0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),FZ(qk0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),FZ(qk0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),FZ(qk0,{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 b3A={name:"@brains/assessment",version:"0.2.0-alpha.181",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 zL6=H.object({status:H.enum(["ready","generating"])}),k3A=new p_;class P3A extends jw{entityType="swot";schema=Di;adapter=k3A;initialSyncComplete=!1;constructor(){super("swot",b3A,{},yX)}async onRegister(A){let Q=new Gk0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=hZ.from(async()=>{});if(!X)throw Error("Expected progress reporter to be created");await Q.process({reason:"eval"},"eval-swot-derive",X);let Y=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!Y)throw Error("Expected SWOT entity to be created during eval");return k3A.parseSwotContent(Y.content).frontmatter});let w=async(X)=>{try{return await A.jobs.enqueue({type:"derive",data:{reason:X},options:{source:this.id,priority:10,deduplication:"coalesce",deduplicationKey:"swot",metadata:{operationType:"data_processing",operationTarget:`swot:${X}`}}})}catch(Y){return this.logger.error("Failed to queue SWOT derivation",{error:Y,reason:X}),null}},$=async(X)=>{if(!await A.entityService.getEntity({entityType:"swot",id:"swot"}))await w(X)};A.messaging.subscribe("sync:initial:completed",async()=>{return this.initialSyncComplete=!0,await $("initial-missing-entity"),{success:!0}}),A.messaging.subscribe("system:plugins:ready",async()=>{return await A.messaging.send({type:"dashboard:register-widget",payload:{id:"swot",pluginId:this.id,title:"SWOT",group:"network",section:"secondary",priority:14,rendererName:"SwotWidget",digestProvider:(X)=>{let{status:Y}=zL6.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:_3A,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=k3A.parseSwotContent(X.content);return{status:"ready",...Y}}}}),{success:!0}});let B=async(X)=>{let{entityType:Y}=X.payload;if(!this.initialSyncComplete)return{success:!0};if(Y!=="agent"&&Y!=="skill")return{success:!0};return await w("entity-change"),{success:!0}};A.messaging.subscribe("entity:created",B),A.messaging.subscribe("entity:updated",B),A.messaging.subscribe("entity:deleted",B)}}function M3A(){return new P3A}$A();z9();b0();var Gx5=new p_,eE2=H.object({name:H.string(),description:H.string(),tags:H.array(H.string())}),Ag2=H.enum(["discovered","approved"]),JL6=H.object({name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),brainName:H.string(),url:H.string().url(),did:H.string().optional(),status:Ag2,discoveredAt:H.string().datetime()}),VL6=n5.extend({entityType:H.literal("agent"),metadata:H.object({name:H.string(),url:H.string().url(),status:Ag2,slug:H.string()})}),j3A=H.object({name:H.string(),description:H.string(),tags:H.array(H.string()),examples:H.array(H.string())}),FL6=n5.extend({entityType:H.literal("skill"),metadata:j3A}),IL6=H.object({about:H.string(),skills:H.array(eE2),notes:H.string()});function LL6(A){if(!Array.isArray(A)||A.length===0)return"";return A.map((w)=>{let $=w.tags.length>0?` [${w.tags.join(", ")}]`:"";return`- ${w.name}: ${w.description}${$}`}).join(`
|
|
10950
10968
|
`)}function NL6(A){if(!A.trim())return[];return A.split(`
|
|
10951
|
-
`).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 _L6=new R6(IL6,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:LL6,parser:NL6},{key:"notes",label:"Notes",type:"string"}]});class Qg2 extends QQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:VL6,frontmatterSchema:JL6})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=_L6.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 wg2 extends QQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:FL6,frontmatterSchema:j3A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,j3A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var Dx5=new Qg2,qx5=new wg2,bL6=H.object({name:H.string(),description:H.string(),tags:H.array(H.string()),examples:H.array(H.string())}),zx5=H.object({skills:H.array(bL6),agents:H.array(H.object({id:H.string().optional(),name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),brainName:H.string(),url:H.url(),did:H.string().optional(),status:H.enum(["discovered","approved"]),discoveredAt:H.string().datetime().optional(),about:H.string(),skills:H.array(eE2),notes:H.string().default("")}))});var kL6=H.object({}).strict();function zk0(A={}){return kL6.parse(A),[M3A()]}$A();b0();b0();var O3A=H.object({enabled:H.boolean().default(!0),pdsEndpoint:H.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:H.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:H.string().optional().describe("DID of the PDS repo that owns records"),appPassword:H.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:H.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:H.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});b0();var PL6=H.looseObject({message:H.string()}),ML6=H.looseObject({did:H.string(),handle:H.string(),accessJwt:H.string(),refreshJwt:H.string()}),f3A=H.looseObject({uri:H.string(),cid:H.string()}),jL6=f3A.extend({value:H.record(H.string(),H.unknown())}),OL6=H.looseObject({$type:H.literal("blob").optional(),ref:H.looseObject({$link:H.string()}),mimeType:H.string(),size:H.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),fL6=H.looseObject({blob:OL6});function xL6(A){return A.replace(/\/+$/,"")}var RL6=(A,Q)=>fetch(A,Q);async function q80(A,Q){let w=await A.text(),$;try{$=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 B=PL6.safeParse($);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse($)}class z80{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=xL6(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??RL6}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 q80(A,ML6);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 q80(w,f3A)}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 q80(w,f3A)}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 q80(w,jL6)}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 q80(w,fL6)}async getSession(){return this.session??=await this.createSession(),this.session}}function qE(A){return A?.startsWith("did:web:")??!1}function Jk0(A){if(!qE(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 Bg2(A){if(!qE(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((B)=>{try{return decodeURIComponent(B)}catch{return B}}).join("/")}/did.json`}function Xg2(A){return A.replace(/\/+$/,"")}function J80(A){return`did:web:${encodeURIComponent(A)}`}function Vk0(A){return`${J80(A)}:anchor`}function x3A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function Yg2(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...x3A(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:Xg2(A.pdsEndpoint)}]}}function Zg2(A){if(!qE(A.brainDid))return null;return Yg2(A,A.brainDid)}function $g2(A,Q){if(!A||!Q)return;let w=Jk0(A),$=Bg2(A);if(!w||!$)return;return{path:$,hostname:w,document:Q}}function Fk0(A){let Q=[],w=$g2(A.brainDid,Zg2(A));if(w)Q.push(w);if(qE(A.anchorDid)&&A.anchorDid!==A.brainDid){let $=$g2(A.anchorDid,x3A(A.anchorDid));if($)Q.push($)}return Q}function R3A(A,Q){let w=[];if(!A.brainDid){let $=J80(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:Yg2(A,$)})}if(!A.anchorDid){let $=Vk0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:x3A($)})}return w}function vL6(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function CL6(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function Hg2(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function Wg2(A,Q){let w=A[Q];if(!Array.isArray(w))return;let $=w.filter((B)=>typeof B==="string"&&B.length>0);return $.length>0?$:void 0}function hL6(A){let Q=A.metadata,w=Hg2(Q,"name"),$=Hg2(Q,"description");if(!w||!$)return;let B=Wg2(Q,"tags"),X=Wg2(Q,"examples");return{id:CL6(w),name:w,description:$,...B&&{tags:B},...X&&{examples:X}}}async function EL6(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>hL6(w)).filter((w)=>w!==void 0).slice(0,100)}async function v3A(A,Q,w=new Date){let $=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=vL6(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,W=Q.brainDid??J80(Z),K=Q.anchorDid??Vk0(Z);if(qE(W)){if(Jk0(W)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await EL6(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:W,name:$.name,role:$.role,purpose:$.purpose,values:$.values},anchor:{did:K,name:B.name,kind:B.kind},skills:U,model:X.model,version:X.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var Kg2={name:"@brains/atproto",version:"0.2.0-alpha.180",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 Ug2=I$["ai.rizom.brain.card"],yL6=H.looseObject({did:H.string()}),TL6=H.looseObject({service:H.array(H.looseObject({id:H.string().optional(),type:H.string().optional(),serviceEndpoint:H.string().optional()})).optional()}),SL6="ai.rizom.brain.card",mL6="self",Gg2=50;class C3A extends Rw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",Kg2,A,O3A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??fB.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=Fk0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map(($)=>$.path),...Q])].map(($)=>({path:$,method:"GET",public:!0,handler:(B)=>{let X=new URL(B.url).hostname,Y=[...Fk0(this.config),...R3A(this.config,X)].filter((W)=>W.path===$),Z=Y.find((W)=>W.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await v3A(A,this.config);B_(Ug2,w);let $=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...$&&{repo:$}};let B=this.resolveAppPassword();if(!this.config.identifier||!B)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(B),Y=await X.createSession(),Z=$??Y.did;if(!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let W=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Z,uri:W.uri,cid:W.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((X)=>X.trim()))].filter((X)=>X.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>Gg2)throw Error(`AT Protocol discovery accepts at most ${Gg2} repos per batch`);let $=new Set,B=[];for(let X of w)try{let Y=await this.resolveRepoPdsEndpoint(X),Z=this.createPublicPdsClient(Y.pdsEndpoint);if(!Z.getRecord)throw Error("AT Protocol PDS client does not support record reads");let W=await Z.getRecord({repo:Y.repoDid,collection:SL6,rkey:mL6});B_(Ug2,W.value);let K=cL6(W.uri)??Y.repoDid,U=`${K}:${W.uri}:${W.cid}`;if($.has(U)){B.push({repo:X,status:"skipped",repoDid:K,uri:W.uri,cid:W.cid,error:"Duplicate brain card in discovery batch"});continue}$.add(U),await A.messaging.send({type:eQ0,payload:{repoDid:K,uri:W.uri,cid:W.cid,record:W.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:K,uri:W.uri,cid:W.cid})}catch(Y){B.push({repo:X,status:"skipped",error:lA(Y)})}return{discovered:B.filter((X)=>X.status==="discovered").length,skipped:B.filter((X)=>X.status==="skipped").length,results:B}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:lA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let $=await this.findPublishEntity(A,Q),B=Q.entityId??Q.slug;if(!B)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!$)throw Error(`${Q.entityType} not found: ${B}`);if($.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${B}`);let X=this.config.repoDid;if(Q.dryRun){let D=await w.buildRecord({entity:$,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return B_(w.lexicon,D),{record:D,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),W=await Z.createSession(),K=X??W.did,U=await w.buildRecord({entity:$,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(B_(w.lexicon,U),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let G=await Z.putRecord({repo:K,collection:w.collection,rkey:uL6($.id),...w.validate!==void 0&&{validate:w.validate},record:U});return await w.onPublished?.({entity:$,context:A,record:U,uri:G.uri,cid:G.cid}),{record:U,repo:K,uri:G.uri,cid:G.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new z80({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 $=yL6.safeParse(await w.json());return $.success?$.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(pL6(A)):void 0,w=TL6.safeParse(Q);if(!w.success)return;return w.data.service?.find((B)=>B.id==="#atproto_pds"||B.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new z80({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function uL6(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function cL6(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function pL6(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...$]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if($.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${$.join("/")}/did.json`}function Ik0(A,Q){return new C3A(A,Q)}$A();b0();var Lk0={name:"@brains/rover",version:"0.2.0-alpha.180",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 dL6=H.looseObject({});class Dg2 extends Rw{constructor(A={}){super("rover-profile",Lk0,A,dL6)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",GR)}}function qg2(A={}){return new Dg2(A)}$A();b0();y8();$A();$A();var V80=pL.extend(GR.shape);class Nk0{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 $=w.entityService,[B,X,Y,Z]=await Promise.all([yS($,V80),FN0($,{entityType:"post",count:3,parse:o60}),FN0($,{entityType:"deck",count:3,parse:w$0}),n60($)]),W={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:mHA(Z.cta),sections:Z.sections??{}};return Q.parse(W)}}$A();class _k0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let B={profile:await yS(w.entityService,V80)};return Q.parse(B)}}import{jsxDEV as c8,Fragment as rL6}from"preact/jsx-dev-runtime";var iL6="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",nL6="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",h3A=({number:A,title:Q,blurb:w,children:$})=>c8("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:c8("div",{className:"max-w-6xl mx-auto",children:c8("div",{className:iL6,children:[c8(iXA,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),c8("div",{className:nL6,"aria-hidden":"true"},void 0,!1,void 0,this),c8("div",{className:"mt-6 md:mt-0",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E3A=({profile:A,posts:Q,decks:w,postsListUrl:$,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,W=Q.map((z)=>({id:z.id,url:z.url,title:z.metadata.title,date:z.metadata.publishedAt??z.created,description:z.frontmatter.excerpt,series:z.frontmatter.seriesName&&z.frontmatter.seriesIndex?{name:z.frontmatter.seriesName,index:z.frontmatter.seriesIndex}:void 0})),K=w.map((z)=>({id:z.id,url:z.url,title:z.frontmatter.title||z.id,date:z.frontmatter.publishedAt??z.created,description:z.frontmatter.description})),U=A.name||"Home",G=[A.intro,A.description,Z].find((z)=>z)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return c8(rL6,{children:[c8(Nw,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),c8("div",{className:"homepage-list bg-theme",children:[c8("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:c8("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&c8("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[c8("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),c8("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&c8("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:RI0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&c8("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:RI0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),c8(h3A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:c8(xI0,{items:W,viewAllUrl:$,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&c8(h3A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:c8(xI0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&c8(h3A,{number:"03",title:"About",blurb:Y.about?.blurb,children:c8("div",{className:"flex flex-col gap-8",children:[A.description&&c8("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&&c8(nXA,{subjects:A.expertise},void 0,!1,void 0,this),c8("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",c8("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),c8(RXA,{cta:X,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as w8,Fragment as oL6}from"preact/jsx-dev-runtime";var g3A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find((B)=>B)??"About page",$=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 w8(oL6,{children:[w8(Nw,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),w8("div",{className:"about-page bg-theme",children:[w8("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:w8("div",{className:"relative z-10 max-w-4xl mx-auto",children:[w8("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&&w8("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),w8("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&w8("section",{className:"content-section-reveal mb-20 md:mb-28",children:w8(L4,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&w8("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),w8("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>w8("li",{className:lw0({variant:"accent",size:"lg"}),children:B},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),w8("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&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),w8("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)&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),w8("div",{className:"space-y-4",children:[A.email&&w8("p",{className:"text-lg",children:w8("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&&w8("p",{className:"text-lg",children:w8("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&&w8("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>w8(I4,{href:B.url,external:!0,variant:"secondary",size:"md",children:B.label?.length?B.label:B.platform},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as IZ,Fragment as zg2}from"preact/jsx-dev-runtime";var y3A=()=>{return IZ(zg2,{children:[IZ(Nw,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),IZ("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IZ("div",{className:"text-center max-w-md",children:[IZ("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),IZ("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),IZ("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),IZ(I4,{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)},T3A=()=>{return IZ(zg2,{children:[IZ(Nw,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),IZ("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IZ("div",{className:"text-center max-w-md",children:[IZ("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),IZ("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),IZ("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),IZ(I4,{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)};b0();var Jg2=H.object({label:H.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:H.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),sL6={post:{label:"Post"},deck:{label:"Deck"}},Vg2=H.object({entityDisplay:H.object({post:Jg2,deck:Jg2}).default(sL6).describe("Display metadata for post and deck entity types used by the homepage")});var Fg2={name:"@brains/site-professional",version:"0.2.0-alpha.180",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 tL6=H.object({blurb:H.string().optional().describe("Short italic subtitle under the section title")}),eL6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),Ig2=H.looseObject({name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),description:H.string().optional(),avatar:H.string().optional(),website:H.string().optional(),email:H.string().optional(),socialLinks:H.array(H.object({platform:H.enum(["github","instagram","linkedin","email","website"]),url:H.string(),label:H.string().optional()})).optional(),tagline:H.string().optional(),intro:H.string().optional(),story:H.string().optional(),role:H.string().optional(),audience:H.string().optional(),expertise:H.array(H.string()).optional(),currentFocus:H.string().optional(),availability:H.string().optional(),desiredTone:H.string().optional()}),AN6=H.looseObject({id:H.string(),entityType:H.literal("post"),content:H.string(),created:H.string(),updated:H.string(),contentHash:H.string(),metadata:H.looseObject({title:H.string(),publishedAt:H.string().optional()}),frontmatter:H.looseObject({excerpt:H.string(),seriesName:H.string().optional(),seriesIndex:H.number().optional()}),body:H.string(),url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),seriesUrl:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional(),coverImageSrcset:H.string().optional(),coverImageSizes:H.string().optional()}),QN6=H.looseObject({id:H.string(),entityType:H.literal("deck"),content:H.string(),created:H.string(),updated:H.string(),contentHash:H.string(),metadata:H.looseObject({title:H.string(),publishedAt:H.string().optional()}),frontmatter:H.looseObject({title:H.string(),description:H.string().optional(),publishedAt:H.string().optional()}),body:H.string(),url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});class S3A extends Rw{dependencies=["blog","decks"];constructor(A){super("professional-site",Fg2,A,Vg2)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,$=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,B=`/${w.pluralName??w.label.toLowerCase()+"s"}`,X=new Nk0($,B);A.entities.registerDataSource(X);let Y=new _k0;A.entities.registerDataSource(Y);let Z=H.object({profile:Ig2,posts:H.array(AN6),decks:H.array(QN6),postsListUrl:H.string(),decksListUrl:H.string(),cta:eL6,sections:H.record(H.string(),tL6)}),W=H.object({profile:Ig2}),K=H.object({});A.templates.register({"homepage-list":$2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:E3A}}),about:$2({name:"about",description:"About page with full profile information",schema:W,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:g3A}}),"subscribe-thanks":$2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:y3A}}),"subscribe-error":$2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:T3A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Lg2(A){return new S3A(A??{})}var Ng2=[{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 bk0}from"preact/jsx-dev-runtime";function _g2({sections:A,siteInfo:Q,slots:w,wordmark:$}){return bk0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[bk0(EXA,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...$!==void 0?{wordmark:$}:{}},void 0,!1,void 0,this),bk0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),bk0(hXA,{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((B)=>B.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var wN6={layouts:{default:_g2},routes:Ng2,plugin:Lg2,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"}}}},F80=wN6;var bg2=`/*
|
|
10969
|
+
`).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 _L6=new R6(IL6,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:LL6,parser:NL6},{key:"notes",label:"Notes",type:"string"}]});class Qg2 extends QQ{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:VL6,frontmatterSchema:JL6})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=_L6.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 wg2 extends QQ{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:FL6,frontmatterSchema:j3A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,j3A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var Dx5=new Qg2,qx5=new wg2,bL6=H.object({name:H.string(),description:H.string(),tags:H.array(H.string()),examples:H.array(H.string())}),zx5=H.object({skills:H.array(bL6),agents:H.array(H.object({id:H.string().optional(),name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),brainName:H.string(),url:H.url(),did:H.string().optional(),status:H.enum(["discovered","approved"]),discoveredAt:H.string().datetime().optional(),about:H.string(),skills:H.array(eE2),notes:H.string().default("")}))});var kL6=H.object({}).strict();function zk0(A={}){return kL6.parse(A),[M3A()]}$A();b0();b0();var O3A=H.object({enabled:H.boolean().default(!0),pdsEndpoint:H.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:H.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:H.string().optional().describe("DID of the PDS repo that owns records"),appPassword:H.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:H.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:H.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});b0();var PL6=H.looseObject({message:H.string()}),ML6=H.looseObject({did:H.string(),handle:H.string(),accessJwt:H.string(),refreshJwt:H.string()}),f3A=H.looseObject({uri:H.string(),cid:H.string()}),jL6=f3A.extend({value:H.record(H.string(),H.unknown())}),OL6=H.looseObject({$type:H.literal("blob").optional(),ref:H.looseObject({$link:H.string()}),mimeType:H.string(),size:H.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),fL6=H.looseObject({blob:OL6});function xL6(A){return A.replace(/\/+$/,"")}var RL6=(A,Q)=>fetch(A,Q);async function q80(A,Q){let w=await A.text(),$;try{$=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 B=PL6.safeParse($);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse($)}class z80{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=xL6(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??RL6}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 q80(A,ML6);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 q80(w,f3A)}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 q80(w,f3A)}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 q80(w,jL6)}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 q80(w,fL6)}async getSession(){return this.session??=await this.createSession(),this.session}}function qE(A){return A?.startsWith("did:web:")??!1}function Jk0(A){if(!qE(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 Bg2(A){if(!qE(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((B)=>{try{return decodeURIComponent(B)}catch{return B}}).join("/")}/did.json`}function Xg2(A){return A.replace(/\/+$/,"")}function J80(A){return`did:web:${encodeURIComponent(A)}`}function Vk0(A){return`${J80(A)}:anchor`}function x3A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function Yg2(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...x3A(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:Xg2(A.pdsEndpoint)}]}}function Zg2(A){if(!qE(A.brainDid))return null;return Yg2(A,A.brainDid)}function $g2(A,Q){if(!A||!Q)return;let w=Jk0(A),$=Bg2(A);if(!w||!$)return;return{path:$,hostname:w,document:Q}}function Fk0(A){let Q=[],w=$g2(A.brainDid,Zg2(A));if(w)Q.push(w);if(qE(A.anchorDid)&&A.anchorDid!==A.brainDid){let $=$g2(A.anchorDid,x3A(A.anchorDid));if($)Q.push($)}return Q}function R3A(A,Q){let w=[];if(!A.brainDid){let $=J80(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:Yg2(A,$)})}if(!A.anchorDid){let $=Vk0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:x3A($)})}return w}function vL6(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function CL6(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function Hg2(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function Wg2(A,Q){let w=A[Q];if(!Array.isArray(w))return;let $=w.filter((B)=>typeof B==="string"&&B.length>0);return $.length>0?$:void 0}function hL6(A){let Q=A.metadata,w=Hg2(Q,"name"),$=Hg2(Q,"description");if(!w||!$)return;let B=Wg2(Q,"tags"),X=Wg2(Q,"examples");return{id:CL6(w),name:w,description:$,...B&&{tags:B},...X&&{examples:X}}}async function EL6(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>hL6(w)).filter((w)=>w!==void 0).slice(0,100)}async function v3A(A,Q,w=new Date){let $=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=vL6(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,W=Q.brainDid??J80(Z),K=Q.anchorDid??Vk0(Z);if(qE(W)){if(Jk0(W)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let U=await EL6(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:W,name:$.name,role:$.role,purpose:$.purpose,values:$.values},anchor:{did:K,name:B.name,kind:B.kind},skills:U,model:X.model,version:X.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var Kg2={name:"@brains/atproto",version:"0.2.0-alpha.181",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 Ug2=I$["ai.rizom.brain.card"],yL6=H.looseObject({did:H.string()}),TL6=H.looseObject({service:H.array(H.looseObject({id:H.string().optional(),type:H.string().optional(),serviceEndpoint:H.string().optional()})).optional()}),SL6="ai.rizom.brain.card",mL6="self",Gg2=50;class C3A extends Rw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",Kg2,A,O3A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??fB.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=Fk0(this.config),Q=[...!this.config.brainDid?["/.well-known/did.json"]:[],...!this.config.anchorDid?["/anchor/did.json"]:[]];return[...new Set([...A.map(($)=>$.path),...Q])].map(($)=>({path:$,method:"GET",public:!0,handler:(B)=>{let X=new URL(B.url).hostname,Y=[...Fk0(this.config),...R3A(this.config,X)].filter((W)=>W.path===$),Z=Y.find((W)=>W.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await v3A(A,this.config);B_(Ug2,w);let $=this.config.repoDid;if(Q.dryRun)return{record:w,dryRun:!0,...$&&{repo:$}};let B=this.resolveAppPassword();if(!this.config.identifier||!B)throw Error("AT Protocol publishing requires identifier and app password configuration");let X=this.createPdsClient(B),Y=await X.createSession(),Z=$??Y.did;if(!X.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let W=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Z,uri:W.uri,cid:W.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((X)=>X.trim()))].filter((X)=>X.length>0);if(w.length===0)throw Error("AT Protocol discovery requires at least one repo DID or handle");if(w.length>Gg2)throw Error(`AT Protocol discovery accepts at most ${Gg2} repos per batch`);let $=new Set,B=[];for(let X of w)try{let Y=await this.resolveRepoPdsEndpoint(X),Z=this.createPublicPdsClient(Y.pdsEndpoint);if(!Z.getRecord)throw Error("AT Protocol PDS client does not support record reads");let W=await Z.getRecord({repo:Y.repoDid,collection:SL6,rkey:mL6});B_(Ug2,W.value);let K=cL6(W.uri)??Y.repoDid,U=`${K}:${W.uri}:${W.cid}`;if($.has(U)){B.push({repo:X,status:"skipped",repoDid:K,uri:W.uri,cid:W.cid,error:"Duplicate brain card in discovery batch"});continue}$.add(U),await A.messaging.send({type:eQ0,payload:{repoDid:K,uri:W.uri,cid:W.cid,record:W.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:K,uri:W.uri,cid:W.cid})}catch(Y){B.push({repo:X,status:"skipped",error:lA(Y)})}return{discovered:B.filter((X)=>X.status==="discovered").length,skipped:B.filter((X)=>X.status==="skipped").length,results:B}}async validatePdsCredentials(){let A=this.resolveAppPassword();if(!this.config.identifier||!A)return!1;try{return await this.createPdsClient(A).createSession(),!0}catch(Q){return this.logger.warn("AT Protocol PDS authentication failed",{error:lA(Q)}),!1}}async getTools(){return[]}async publishProjectedEntity(A,Q,w){let $=await this.findPublishEntity(A,Q),B=Q.entityId??Q.slug;if(!B)throw Error(`${Q.entityType} publish requires entityId or slug`);if(!$)throw Error(`${Q.entityType} not found: ${B}`);if($.visibility!=="public")throw Error(`Cannot publish non-public ${Q.entityType}: ${B}`);let X=this.config.repoDid;if(Q.dryRun){let D=await w.buildRecord({entity:$,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return B_(w.lexicon,D),{record:D,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),W=await Z.createSession(),K=X??W.did,U=await w.buildRecord({entity:$,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(B_(w.lexicon,U),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let G=await Z.putRecord({repo:K,collection:w.collection,rkey:uL6($.id),...w.validate!==void 0&&{validate:w.validate},record:U});return await w.onPublished?.({entity:$,context:A,record:U,uri:G.uri,cid:G.cid}),{record:U,repo:K,uri:G.uri,cid:G.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new z80({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 $=yL6.safeParse(await w.json());return $.success?$.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(pL6(A)):void 0,w=TL6.safeParse(Q);if(!w.success)return;return w.data.service?.find((B)=>B.id==="#atproto_pds"||B.type==="AtprotoPersonalDataServer")?.serviceEndpoint}async fetchJson(A){let Q=await this.fetch(A);if(!Q.ok)return;return Q.json()}fetch(A){return(this.deps.fetch??fetch)(A)}createPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A});return new z80({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function uL6(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function cL6(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function pL6(A){let Q=A.slice(8).split(":").map(decodeURIComponent),[w,...$]=Q;if(!w)throw Error(`Invalid did:web value: ${A}`);if($.length===0)return`https://${w}/.well-known/did.json`;return`https://${w}/${$.join("/")}/did.json`}function Ik0(A,Q){return new C3A(A,Q)}$A();b0();var Lk0={name:"@brains/rover",version:"0.2.0-alpha.181",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 dL6=H.looseObject({});class Dg2 extends Rw{constructor(A={}){super("rover-profile",Lk0,A,dL6)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",GR)}}function qg2(A={}){return new Dg2(A)}$A();b0();y8();$A();$A();var V80=pL.extend(GR.shape);class Nk0{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 $=w.entityService,[B,X,Y,Z]=await Promise.all([yS($,V80),FN0($,{entityType:"post",count:3,parse:o60}),FN0($,{entityType:"deck",count:3,parse:w$0}),n60($)]),W={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:mHA(Z.cta),sections:Z.sections??{}};return Q.parse(W)}}$A();class _k0{id="professional:about";name="About Page DataSource";description="Fetches full profile data for the about page";async fetch(A,Q,w){let B={profile:await yS(w.entityService,V80)};return Q.parse(B)}}import{jsxDEV as c8,Fragment as rL6}from"preact/jsx-dev-runtime";var iL6="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",nL6="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",h3A=({number:A,title:Q,blurb:w,children:$})=>c8("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:c8("div",{className:"max-w-6xl mx-auto",children:c8("div",{className:iL6,children:[c8(iXA,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),c8("div",{className:nL6,"aria-hidden":"true"},void 0,!1,void 0,this),c8("div",{className:"mt-6 md:mt-0",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),E3A=({profile:A,posts:Q,decks:w,postsListUrl:$,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,W=Q.map((z)=>({id:z.id,url:z.url,title:z.metadata.title,date:z.metadata.publishedAt??z.created,description:z.frontmatter.excerpt,series:z.frontmatter.seriesName&&z.frontmatter.seriesIndex?{name:z.frontmatter.seriesName,index:z.frontmatter.seriesIndex}:void 0})),K=w.map((z)=>({id:z.id,url:z.url,title:z.frontmatter.title||z.id,date:z.frontmatter.publishedAt??z.created,description:z.frontmatter.description})),U=A.name||"Home",G=[A.intro,A.description,Z].find((z)=>z)??"Professional site",D=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return c8(rL6,{children:[c8(Nw,{title:U,description:G,ogType:"website"},void 0,!1,void 0,this),c8("div",{className:"homepage-list bg-theme",children:[c8("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:c8("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&c8("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[c8("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),c8("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&c8("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:RI0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&c8("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:RI0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),c8(h3A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:c8(xI0,{items:W,viewAllUrl:$,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),K.length>0&&c8(h3A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:c8(xI0,{items:K,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D&&c8(h3A,{number:"03",title:"About",blurb:Y.about?.blurb,children:c8("div",{className:"flex flex-col gap-8",children:[A.description&&c8("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&&c8(nXA,{subjects:A.expertise},void 0,!1,void 0,this),c8("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",c8("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),c8(RXA,{cta:X,variant:"editorial",socialLinks:A.socialLinks},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as w8,Fragment as oL6}from"preact/jsx-dev-runtime";var g3A=({profile:A})=>{let Q=`About ${A.name||"Me"}`,w=[A.description,A.intro].find((B)=>B)??"About page",$=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 w8(oL6,{children:[w8(Nw,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),w8("div",{className:"about-page bg-theme",children:[w8("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:w8("div",{className:"relative z-10 max-w-4xl mx-auto",children:[w8("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&&w8("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),w8("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&w8("section",{className:"content-section-reveal mb-20 md:mb-28",children:w8(L4,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&w8("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),w8("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>w8("li",{className:lw0({variant:"accent",size:"lg"}),children:B},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.currentFocus&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),w8("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&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),w8("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)&&w8("section",{children:[w8("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),w8("div",{className:"space-y-4",children:[A.email&&w8("p",{className:"text-lg",children:w8("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&&w8("p",{className:"text-lg",children:w8("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&&w8("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>w8(I4,{href:B.url,external:!0,variant:"secondary",size:"md",children:B.label?.length?B.label:B.platform},X,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{jsxDEV as IZ,Fragment as zg2}from"preact/jsx-dev-runtime";var y3A=()=>{return IZ(zg2,{children:[IZ(Nw,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),IZ("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IZ("div",{className:"text-center max-w-md",children:[IZ("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),IZ("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),IZ("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),IZ(I4,{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)},T3A=()=>{return IZ(zg2,{children:[IZ(Nw,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),IZ("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:IZ("div",{className:"text-center max-w-md",children:[IZ("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),IZ("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),IZ("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),IZ(I4,{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)};b0();var Jg2=H.object({label:H.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:H.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),sL6={post:{label:"Post"},deck:{label:"Deck"}},Vg2=H.object({entityDisplay:H.object({post:Jg2,deck:Jg2}).default(sL6).describe("Display metadata for post and deck entity types used by the homepage")});var Fg2={name:"@brains/site-professional",version:"0.2.0-alpha.181",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 tL6=H.object({blurb:H.string().optional().describe("Short italic subtitle under the section title")}),eL6=H.object({heading:H.string(),buttonText:H.string(),buttonLink:H.string()}),Ig2=H.looseObject({name:H.string(),kind:H.enum(["professional","team","collective"]),organization:H.string().optional(),description:H.string().optional(),avatar:H.string().optional(),website:H.string().optional(),email:H.string().optional(),socialLinks:H.array(H.object({platform:H.enum(["github","instagram","linkedin","email","website"]),url:H.string(),label:H.string().optional()})).optional(),tagline:H.string().optional(),intro:H.string().optional(),story:H.string().optional(),role:H.string().optional(),audience:H.string().optional(),expertise:H.array(H.string()).optional(),currentFocus:H.string().optional(),availability:H.string().optional(),desiredTone:H.string().optional()}),AN6=H.looseObject({id:H.string(),entityType:H.literal("post"),content:H.string(),created:H.string(),updated:H.string(),contentHash:H.string(),metadata:H.looseObject({title:H.string(),publishedAt:H.string().optional()}),frontmatter:H.looseObject({excerpt:H.string(),seriesName:H.string().optional(),seriesIndex:H.number().optional()}),body:H.string(),url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),seriesUrl:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional(),coverImageSrcset:H.string().optional(),coverImageSizes:H.string().optional()}),QN6=H.looseObject({id:H.string(),entityType:H.literal("deck"),content:H.string(),created:H.string(),updated:H.string(),contentHash:H.string(),metadata:H.looseObject({title:H.string(),publishedAt:H.string().optional()}),frontmatter:H.looseObject({title:H.string(),description:H.string().optional(),publishedAt:H.string().optional()}),body:H.string(),url:H.string().optional(),typeLabel:H.string().optional(),listUrl:H.string().optional(),listLabel:H.string().optional(),coverImageUrl:H.string().optional(),ogImageUrl:H.string().optional(),coverImageWidth:H.number().optional(),coverImageHeight:H.number().optional()});class S3A extends Rw{dependencies=["blog","decks"];constructor(A){super("professional-site",Fg2,A,Vg2)}async onRegister(A){let Q=this.config.entityDisplay.post,w=this.config.entityDisplay.deck,$=`/${Q.pluralName??Q.label.toLowerCase()+"s"}`,B=`/${w.pluralName??w.label.toLowerCase()+"s"}`,X=new Nk0($,B);A.entities.registerDataSource(X);let Y=new _k0;A.entities.registerDataSource(Y);let Z=H.object({profile:Ig2,posts:H.array(AN6),decks:H.array(QN6),postsListUrl:H.string(),decksListUrl:H.string(),cta:eL6,sections:H.record(H.string(),tL6)}),W=H.object({profile:Ig2}),K=H.object({});A.templates.register({"homepage-list":$2({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:E3A}}),about:$2({name:"about",description:"About page with full profile information",schema:W,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:g3A}}),"subscribe-thanks":$2({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:K,requiredPermission:"public",layout:{component:y3A}}),"subscribe-error":$2({name:"subscribe-error",description:"Newsletter subscription error page",schema:K,requiredPermission:"public",layout:{component:T3A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function Lg2(A){return new S3A(A??{})}var Ng2=[{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 bk0}from"preact/jsx-dev-runtime";function _g2({sections:A,siteInfo:Q,slots:w,wordmark:$}){return bk0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[bk0(EXA,{title:Q.title,navigation:Q.navigation.primary,showThemeToggle:!0,...Q.logo!==void 0?{logo:Q.logo}:{},...$!==void 0?{wordmark:$}:{}},void 0,!1,void 0,this),bk0("main",{className:"flex-grow flex flex-col bg-theme",children:A},void 0,!1,void 0,this),bk0(hXA,{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((B)=>B.render())},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var wN6={layouts:{default:_g2},routes:Ng2,plugin:Lg2,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"}}}},F80=wN6;var bg2=`/*
|
|
10952
10970
|
* Default theme \u2014 simplified editorial base inspired by the Rizom family.
|
|
10953
10971
|
*
|
|
10954
10972
|
* This theme is intentionally less branded than @brains/theme-rizom. It
|
|
@@ -13826,7 +13844,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});b0();var q
|
|
|
13826
13844
|
`);return this.truncateContent($||Q||Pi(A))}truncateContent(A){if(A.length<=Jy2)return A;let Q=A.slice(0,Jy2-1),w=Q.search(/\s\S*$/);return`${(w>0?Q.slice(0,w):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===$9}isDecisionEntity(A){return A.entityType===tU}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return Nz(Q)}}var c_6=5,p_6=3;function a3A(A){A.messaging.subscribe(Gf,async(Q)=>{let w=jr.parse(Q.payload);return{success:!0,data:await mk0(A,w)}})}async function mk0(A,Q){let w=N5(Q.userPermissionLevel);if(!Q.channelId)return Vy2(A,Q,{visibilityScope:w,reason:"no-channel-context",items:[]}),{items:[]};let $=new Mi(A),B=await $.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:c_6,visibilityScope:w}),X=B.results.length===0?await $.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:p_6,visibilityScope:w}):void 0,Y=B.results.length>0,Z=Y?B.results:X?.results??[];return Vy2(A,Q,{visibilityScope:w,spaceId:B.spaceId??X?.spaceId,reason:Z.length>0?"memory-injected":"no-same-space-memory",items:Z.map((W)=>l_6(W,Y))}),{items:Z.map(d_6)}}function Vy2(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 l_6(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 d_6(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}}}b0();wH();var Ly2=H.union([H.enum(["public","shared","restricted"]),H.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),Ny2=H.enum(["user","assistant"]),i_6=H.object({actorId:H.string(),canonicalId:H.string().optional(),interfaceType:H.string(),role:Ny2,displayName:H.string().optional(),username:H.string().optional(),isBot:H.boolean().optional()}),n_6=H.object({messageId:H.string().optional(),channelId:H.string().optional(),channelName:H.string().optional(),threadId:H.string().optional(),metadata:H.record(H.string(),H.unknown()).optional()}),e3A=H.object({role:Ny2,content:H.string(),timestamp:H.string().datetime().optional(),actor:i_6.optional(),source:n_6.optional()}),r_6=H.object({conversationId:H.string().default("eval-conversation"),messages:H.array(e3A)}),o_6=H.object({conversationId:H.string()}),s_6=H.object({conversationId:H.string().default("eval-conversation"),interfaceType:H.string().default("eval"),channelId:H.string().default("eval-channel"),channelName:H.string().optional(),projectionDecision:H.enum(["update","append"]).default("update"),existingSummary:H.string().optional(),existingMessageCount:H.number().int().min(0).default(0),messages:H.array(e3A)}),uk0=H.object({actorId:H.string(),canonicalId:H.string().optional(),displayName:H.string().optional()}),a_6=uk0.extend({roles:H.array(H.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:H.array(H.string()).optional()}),t_6=H.object({actorId:H.string().optional(),canonicalId:H.string().optional(),displayName:H.string()}),_y2=H.object({id:H.string(),entityType:H.enum(["summary","decision","action-item"]),content:H.string(),excerpt:H.string().optional(),score:H.number().optional(),conversationId:H.string(),interfaceType:H.string(),channelId:H.string(),channelName:H.string().optional(),updated:H.string().datetime().optional(),visibility:Ly2,status:H.string().optional(),participants:H.array(a_6).optional(),decidedBy:H.array(uk0).optional(),mentionedBy:H.array(uk0).optional(),assignedTo:H.array(t_6).optional(),requestedBy:H.array(uk0).optional()}),e_6=H.object({query:H.string().optional(),conversationId:H.string().optional(),interfaceType:H.string().optional(),channelId:H.string().optional(),limit:H.number().int().min(1).optional(),includeOtherSpaces:H.boolean().optional(),actorId:H.string().optional(),canonicalId:H.string().optional(),visibilityScope:Ly2.optional(),memory:H.array(_y2).optional()}),Ab6=H.object({conversationId:H.string().default("eval-conversation"),message:H.string(),interfaceType:H.string().default("eval"),channelId:H.string().optional(),channelName:H.string().optional(),userPermissionLevel:H.enum(["anchor","trusted","public"]).default("trusted"),memory:H.array(_y2).optional()}),Qb6=H.object({conversationId:H.string().default("eval-conversation"),existingSummary:H.string().optional(),existingMessageCount:H.number().int().min(0).default(0),messages:H.array(e3A)});function by2(A){let{context:Q,logger:w,config:$}=A;Q.eval.registerHandler("summarizeMessages",async(B)=>{let X=r_6.parse(B),Y=t3A(X.messages,X.conversationId),W=await new _i(Q,w,$).extract(Y);return W.entries.map((K)=>{let U=W.decisions.filter((D)=>D.timeRange.start>=K.timeRange.start).filter((D)=>D.timeRange.end<=K.timeRange.end).map((D)=>D.text),G=W.actionItems.filter((D)=>D.timeRange.start>=K.timeRange.start).filter((D)=>D.timeRange.end<=K.timeRange.end).map((D)=>D.text);return{...K,decisions:U,actionItems:G,keyPointsText:K.keyPoints.join(`
|
|
13827
13845
|
`),decisionsText:U.join(`
|
|
13828
13846
|
`),actionItemsText:G.join(`
|
|
13829
|
-
`)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=Qb6.parse(B),Y=t3A(X.messages,X.conversationId),Z=X.existingSummary?Fy2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null;return new HO(Q,w,$).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=e_6.parse(B),Y=X.memory?Iy2(Q,X.memory):Q;return new Mi(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=Ab6.parse(B),Y=X.memory?Iy2(Q,X.memory):Q;return mk0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=s_6.parse(B),Y=t3A(X.messages,X.conversationId),Z=wb6({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),W=X.existingSummary?Fy2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null,K=[],U=[],G=$b6({context:Q,conversation:Z,messages:Y,existing:W,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new HO(G,w,$).projectConversation(X.conversationId),summaries:K.filter((V)=>V.entityType==="summary"),decisions:K.filter((V)=>V.entityType==="decision"),actionItems:K.filter((V)=>V.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=o_6.parse(B);return new HO(Q,w,$).projectConversation(X.conversationId)})}function Fy2(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 t3A(A,Q){return A.map((w,$)=>{let B=w.timestamp??new Date(Date.UTC(2026,0,1,0,$)).toISOString();return{id:`eval-message-${$+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:B,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function wb6(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],$=Q?.timestamp??"2026-01-01T00:00:00.000Z",B=w?.timestamp??$;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:$,lastActiveAt:B,createdAt:$,updatedAt:B,metadata:{}}}function $b6(A){let Q=Nz(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 Iy2(A,Q){let w=Q.map(Bb6),$=w.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??Pi(B)}));return{...A,entityService:{...A.entityService,search:async()=>$,listEntities:async({entityType:B})=>w.filter((X)=>X.entityType===B)}}}function Bb6(A){if(A.entityType==="summary")return Xb6(A);if(A.entityType==="decision")return Yb6(A);return Zb6(A)}function ADA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:mw(A.content),visibility:A.visibility,created:Q,updated:Q}}function Xb6(A){return{...ADA(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 Yb6(A){return{...ADA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:Nz(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 Zb6(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...ADA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:Nz(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 ky2={name:"@brains/conversation-memory",version:"0.2.0-alpha.180",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 Wb6=new XD,Kb6=new Ii,Ub6=new Li,Gb6=H.object({conversationId:H.string()});class QDA extends jw{entityType=$9;schema=L80;adapter=Wb6;constructor(A={}){super(fk0,ky2,A,n3A)}getConfig(){return this.config}getTemplates(){return{"summary-list":rg2,"summary-detail":og2,"ai-response":sg2}}getDataSources(){return[new s3A(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:$9,job:{type:Tg2,handler:new Ek0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await BR(A,$9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:p3A,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:fk0}}},sourceChange:{sourceKind:la,sourceTypes:[la],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[BS],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:p3A,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:fk0}}}}}]}parseConversationMessagePayload(A){return Gb6.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),$=await A.conversations.get(w);if(!$)return!1;return FE({conversation:$,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(tU,N80,Kb6),A.entities.register(BD,_80,Ub6),eg2({context:A,pluginId:this.id}),Qy2({context:A,pluginId:this.id}),Uy2({context:A,pluginId:this.id}),qy2({context:A,pluginId:this.id,config:this.config}),a3A(A),by2({context:A,logger:this.logger,config:this.config})}}function wDA(A={}){return new QDA(A)}$A();b0();b0();z9();var Py2=H.object({label:H.string(),href:H.string()}),My2=H.object({label:H.string(),title:H.string(),detail:H.string()}),Db6=H.object({eyebrow:H.string(),name:H.string(),sub:H.string()}),qb6=H.object({tone:H.enum(["capture","synthesis","share"]),title:H.string(),text:H.string()}),$DA=H.object({captures:H.number(),links:H.number(),topics:H.number(),summaries:H.number(),peers:H.number()}),ji=H.object({eyebrow:H.string(),headline:H.string(),intro:H.string(),primaryCta:Py2,secondaryCta:Py2,inputs:H.array(My2).min(1),outputs:H.array(My2).min(1),core:Db6,legend:H.array(qb6).min(1)}),BDA=ji.extend({counts:$DA}),jy2={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."}]},Oy2=new R6(ji,{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 ck0(A){return Oy2.parse(A)}function fy2(A){return Oy2.format(A)}b0();var zb6=H.looseObject({query:H.object({routeId:H.string().default("home"),sectionId:H.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Jb6={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class XDA{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 $=zb6.parse(A??{}),B=await this.fetchContent(w,$.query.routeId,$.query.sectionId),X=await this.fetchCounts(w);return Q.parse({...B,counts:X})}async fetchContent(A,Q,w){let $=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!$?.content)return jy2;return ji.parse(ck0($.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Jb6).map(async([w,$])=>[w,await this.countOrZero(A,$)]));return $DA.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 b1}from"preact/jsx-dev-runtime";var xy2=H.object({label:H.string(),href:H.string()}),Vb6=H.object({label:H.string(),value:H.string(),note:H.string()}),Fb6=H.object({eyebrow:H.string(),headline:H.string(),intro:H.string(),primaryCta:xy2,secondaryCta:xy2,signals:H.array(Vb6)}),Ib6=H.object({phase:H.string(),title:H.string(),text:H.string()}),Lb6=H.object({eyebrow:H.string(),title:H.string(),intro:H.string(),steps:H.array(Ib6)}),Nb6=H.object({label:H.string(),title:H.string(),text:H.string()}),_b6=H.object({title:H.string(),intro:H.string(),cards:H.array(Nb6)}),bb6=H.object({title:H.string(),intro:H.string(),points:H.array(H.string())}),kb6={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."]},Pb6="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function Ry2({href:A,label:Q}){return b1("a",{href:A,className:Pb6,children:Q},void 0,!1,void 0,this)}function Mb6({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],$=A.cta??{buttonText:"Start here",buttonLink:"/about"};return b1(zi,{children:[b1("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:[b1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[b1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),b1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),b1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex items-center gap-5 md:gap-8",children:[b1("div",{className:"hidden items-center gap-6 md:flex",children:w.map((B)=>b1(Ry2,{...B},`${B.href}-${B.label}`,!1,void 0,this))},void 0,!1,void 0,this),b1("a",{href:$.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:$.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("main",{children:Q},void 0,!1,void 0,this),b1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:b1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[b1("div",{children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),b1("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),b1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map((B)=>b1(Ry2,{...B},`footer-${B.href}-${B.label}`,!1,void 0,this)),b1("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 jb6=({sections:A,siteInfo:Q})=>b1(Mb6,{siteInfo:Q,children:A},void 0,!1,void 0,this);function Ob6({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,signals:X}){return b1(ZO,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:b1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[b1("div",{children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),b1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),b1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),b1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[b1(JE,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(JE,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("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:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),b1("div",{className:"mt-5 grid gap-3",children:X.map((Y)=>b1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[b1("div",{className:"flex items-center justify-between gap-4",children:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),b1("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),b1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),b1("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 fb6({eyebrow:A,title:Q,intro:w,steps:$}){return b1(ZO,{id:"operating-loop",className:"py-section",children:[b1("div",{className:"max-w-[840px]",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),b1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:$.map((B)=>b1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[b1("p",{className:"font-label text-label-sm text-accent",children:B.phase},void 0,!1,void 0,this),b1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:B.title},void 0,!1,void 0,this),b1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function xb6({title:A,intro:Q,cards:w}){return b1(ZO,{className:"py-section",children:b1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:b1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[b1("div",{children:[b1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),b1("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),b1("div",{className:"grid gap-4",children:w.map(($)=>b1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:$.label},void 0,!1,void 0,this),b1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:$.title},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.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 Rb6({title:A,intro:Q,points:w}){return b1(ZO,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[b1("div",{className:"max-w-[920px]",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),b1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map(($)=>b1("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:$},$,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var vb6=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},Cb6=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),P80=(A,Q,w=`${Q}s`)=>`${Cb6(A)} ${A===1?Q:w}`;function hb6({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:W,counts:K}){let U=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:P80(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:P80(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:P80(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:P80(K.summaries,"summary","summaries")}];return b1(ZO,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[b1("div",{className:"mx-auto max-w-[1040px] text-center",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),b1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[b1(JE,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(JE,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("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:[b1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[b1("div",{className:"flex flex-col gap-3.5",children:X.map((G)=>b1("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:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this),b1("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:[b1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),b1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),U.map((G)=>b1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${G.className}`,children:G.label},G.key,!1,void 0,this)),b1("div",{className:"relative z-[1] px-6 text-center",children:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Z.eyebrow},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Z.name},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Z.sub},void 0,!1,void 0,this),b1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[P80(K.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex flex-col gap-3.5",children:Y.map((G)=>b1("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:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:W.map((G)=>b1("div",{className:"text-left",children:[b1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[b1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${vb6(G.tone)}`},void 0,!1,void 0,this),G.title]},void 0,!0,void 0,this),b1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:G.text},void 0,!1,void 0,this)]},G.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Eb6=$2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:BDA,formatter:{parse:(A)=>BDA.parse({...ck0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>fy2(ji.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:hb6}}),gb6=(A)=>Ob6(Fb6.parse(A)),yb6=(A)=>fb6(Lb6.parse(A)),Tb6=(A)=>xb6(_b6.parse(A)),Sb6=(A)=>Rb6(bb6.parse(A)),vy2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},Cy2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:gb6,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...vy2,label:"Primary CTA"},secondaryCta:{...vy2,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:yb6,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:Tb6,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:Sb6,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},mb6=[{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:kb6}]}],hy2=c3A({packageName:"@brains/relay/site",themeProfile:"studio",layout:jb6,routes:mb6,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":Eb6},dataSources:[new XDA]}});var Ey2={name:"@brains/relay",version:"0.2.0-alpha.180",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 gy2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],yy2=[...gy2,"image","site-info","site-content","site-builder"],pb6=[...yy2,"docs","decks"],lb6=["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."],db6=hP({name:"relay",version:Ey2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:hy2,theme:Vi,presets:{core:gy2,default:yy2,full:pb6},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:lb6,capabilities:[["prompt",KE,void 0],["note",rh,{}],["link",sh,{}],["image",a00,void 0],["topics",r_0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",wDA,{memoryVisibility:"shared"}],["docs",Y$0,void 0],["decks",$$0,void 0],["agents",Xk0,void 0],["assessment",zk0,void 0],["auth-service",u10,void 0],["notifications",Ib0,void 0],["email-resend",RF0,void 0],["cms",$E,{}],["dashboard",XO,void 0],["directory-sync",sC,{seedContent:!0,seedContentPath:cb6(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",hh,{definitions:Cy2}],["rizom-ecosystem",UE,void 0],["site-info",Eh,void 0],["site-builder",Ch,{}]],interfaces:[["mcp",IM,()=>({})],["discord",Bj,()=>({captureUrls:!0})],["a2a",$l,()=>({})],["webserver",Kj,()=>({})],["web-chat",wl,()=>({})]],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"}}}),Ty2=db6;import{readFileSync as Mj6}from"fs";import{join as jj6}from"path";import{execSync as Oj6}from"child_process";import{parseArgs as rb6}from"util";var ob6={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 _z(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function WO(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function Sy2(A){let{values:Q,positionals:w}=rb6({args:A,options:ob6,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:_z(Q,"model"),domain:_z(Q,"domain"),"content-repo":_z(Q,"content-repo"),backend:_z(Q,"backend"),"push-to":_z(Q,"push-to"),"ai-api-key":_z(Q,"ai-api-key"),"no-interactive":WO(Q,"no-interactive"),preview:WO(Q,"preview"),deploy:WO(Q,"deploy"),regen:WO(Q,"regen"),all:WO(Q,"all"),only:_z(Q,"only"),"dry-run":WO(Q,"dry-run"),"startup-check":WO(Q,"startup-check"),"storage-dir":_z(Q,"storage-dir"),yes:WO(Q,"yes"),remote:_z(Q,"remote"),token:_z(Q,"token"),outputDir:_z(Q,"outputDir")}}}M80();import{mkdirSync as Jj6}from"fs";import{join as Vj6}from"path";import{execSync as Fj6}from"child_process";var lk0={name:"@rizom/brain",version:"0.2.0-alpha.180",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 AT2,writeFileSync as O80,chmodSync as f80,existsSync as zDA,readFileSync as JDA}from"fs";import{basename as VDA,dirname as FDA,join as HB,resolve as fk6}from"path";import{fileURLToPath as xk6}from"url";var my2=`ARG BUN_VERSION=1.3.10
|
|
13847
|
+
`)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=Qb6.parse(B),Y=t3A(X.messages,X.conversationId),Z=X.existingSummary?Fy2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null;return new HO(Q,w,$).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=e_6.parse(B),Y=X.memory?Iy2(Q,X.memory):Q;return new Mi(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=Ab6.parse(B),Y=X.memory?Iy2(Q,X.memory):Q;return mk0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=s_6.parse(B),Y=t3A(X.messages,X.conversationId),Z=wb6({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),W=X.existingSummary?Fy2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null,K=[],U=[],G=$b6({context:Q,conversation:Z,messages:Y,existing:W,upserted:K,deleted:U,projectionDecision:X.projectionDecision});return{result:await new HO(G,w,$).projectConversation(X.conversationId),summaries:K.filter((V)=>V.entityType==="summary"),decisions:K.filter((V)=>V.entityType==="decision"),actionItems:K.filter((V)=>V.entityType==="action-item"),deleted:U}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=o_6.parse(B);return new HO(Q,w,$).projectConversation(X.conversationId)})}function Fy2(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 t3A(A,Q){return A.map((w,$)=>{let B=w.timestamp??new Date(Date.UTC(2026,0,1,0,$)).toISOString();return{id:`eval-message-${$+1}`,conversationId:Q,role:w.role,content:w.content,timestamp:B,metadata:{...w.actor?{actor:w.actor}:{},...w.source?{source:w.source}:{}}}})}function wb6(A){let Q=A.messages[0],w=A.messages[A.messages.length-1],$=Q?.timestamp??"2026-01-01T00:00:00.000Z",B=w?.timestamp??$;return{id:A.conversationId,sessionId:A.conversationId,interfaceType:A.interfaceType,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},startedAt:$,lastActiveAt:B,createdAt:$,updatedAt:B,metadata:{}}}function $b6(A){let Q=Nz(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 Iy2(A,Q){let w=Q.map(Bb6),$=w.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??Pi(B)}));return{...A,entityService:{...A.entityService,search:async()=>$,listEntities:async({entityType:B})=>w.filter((X)=>X.entityType===B)}}}function Bb6(A){if(A.entityType==="summary")return Xb6(A);if(A.entityType==="decision")return Yb6(A);return Zb6(A)}function ADA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:mw(A.content),visibility:A.visibility,created:Q,updated:Q}}function Xb6(A){return{...ADA(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 Yb6(A){return{...ADA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:Nz(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 Zb6(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...ADA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:Nz(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 ky2={name:"@brains/conversation-memory",version:"0.2.0-alpha.181",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 Wb6=new XD,Kb6=new Ii,Ub6=new Li,Gb6=H.object({conversationId:H.string()});class QDA extends jw{entityType=$9;schema=L80;adapter=Wb6;constructor(A={}){super(fk0,ky2,A,n3A)}getConfig(){return this.config}getTemplates(){return{"summary-list":rg2,"summary-detail":og2,"ai-response":sg2}}getDataSources(){return[new s3A(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:$9,job:{type:Tg2,handler:new Ek0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await BR(A,$9,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:p3A,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:fk0}}},sourceChange:{sourceKind:la,sourceTypes:[la],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[BS],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:p3A,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:fk0}}}}}]}parseConversationMessagePayload(A){return Gb6.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),$=await A.conversations.get(w);if(!$)return!1;return FE({conversation:$,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(tU,N80,Kb6),A.entities.register(BD,_80,Ub6),eg2({context:A,pluginId:this.id}),Qy2({context:A,pluginId:this.id}),Uy2({context:A,pluginId:this.id}),qy2({context:A,pluginId:this.id,config:this.config}),a3A(A),by2({context:A,logger:this.logger,config:this.config})}}function wDA(A={}){return new QDA(A)}$A();b0();b0();z9();var Py2=H.object({label:H.string(),href:H.string()}),My2=H.object({label:H.string(),title:H.string(),detail:H.string()}),Db6=H.object({eyebrow:H.string(),name:H.string(),sub:H.string()}),qb6=H.object({tone:H.enum(["capture","synthesis","share"]),title:H.string(),text:H.string()}),$DA=H.object({captures:H.number(),links:H.number(),topics:H.number(),summaries:H.number(),peers:H.number()}),ji=H.object({eyebrow:H.string(),headline:H.string(),intro:H.string(),primaryCta:Py2,secondaryCta:Py2,inputs:H.array(My2).min(1),outputs:H.array(My2).min(1),core:Db6,legend:H.array(qb6).min(1)}),BDA=ji.extend({counts:$DA}),jy2={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."}]},Oy2=new R6(ji,{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 ck0(A){return Oy2.parse(A)}function fy2(A){return Oy2.format(A)}b0();var zb6=H.looseObject({query:H.object({routeId:H.string().default("home"),sectionId:H.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Jb6={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class XDA{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 $=zb6.parse(A??{}),B=await this.fetchContent(w,$.query.routeId,$.query.sectionId),X=await this.fetchCounts(w);return Q.parse({...B,counts:X})}async fetchContent(A,Q,w){let $=await A.entityService.getEntity({entityType:"site-content",id:`${Q}:${w}`});if(!$?.content)return jy2;return ji.parse(ck0($.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Jb6).map(async([w,$])=>[w,await this.countOrZero(A,$)]));return $DA.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 b1}from"preact/jsx-dev-runtime";var xy2=H.object({label:H.string(),href:H.string()}),Vb6=H.object({label:H.string(),value:H.string(),note:H.string()}),Fb6=H.object({eyebrow:H.string(),headline:H.string(),intro:H.string(),primaryCta:xy2,secondaryCta:xy2,signals:H.array(Vb6)}),Ib6=H.object({phase:H.string(),title:H.string(),text:H.string()}),Lb6=H.object({eyebrow:H.string(),title:H.string(),intro:H.string(),steps:H.array(Ib6)}),Nb6=H.object({label:H.string(),title:H.string(),text:H.string()}),_b6=H.object({title:H.string(),intro:H.string(),cards:H.array(Nb6)}),bb6=H.object({title:H.string(),intro:H.string(),points:H.array(H.string())}),kb6={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."]},Pb6="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function Ry2({href:A,label:Q}){return b1("a",{href:A,className:Pb6,children:Q},void 0,!1,void 0,this)}function Mb6({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],$=A.cta??{buttonText:"Start here",buttonLink:"/about"};return b1(zi,{children:[b1("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:[b1("a",{href:"/",className:"font-nav text-[20px]","aria-label":"Relay home",children:[b1("span",{className:"font-bold text-theme",children:"relay"},void 0,!1,void 0,this),b1("span",{className:"font-bold text-accent",children:"."},void 0,!1,void 0,this),b1("span",{className:"text-theme-muted",children:"brain"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex items-center gap-5 md:gap-8",children:[b1("div",{className:"hidden items-center gap-6 md:flex",children:w.map((B)=>b1(Ry2,{...B},`${B.href}-${B.label}`,!1,void 0,this))},void 0,!1,void 0,this),b1("a",{href:$.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:$.buttonText},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("main",{children:Q},void 0,!1,void 0,this),b1("footer",{className:"relative z-[1] border-t border-theme-light px-6 py-8 md:px-10 xl:px-20",children:b1("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[b1("div",{children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.22em] text-theme-light",children:A.copyright},void 0,!1,void 0,this),b1("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),b1("div",{className:"flex flex-wrap items-center gap-5",children:[w.map((B)=>b1(Ry2,{...B},`footer-${B.href}-${B.label}`,!1,void 0,this)),b1("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 jb6=({sections:A,siteInfo:Q})=>b1(Mb6,{siteInfo:Q,children:A},void 0,!1,void 0,this);function Ob6({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,signals:X}){return b1(ZO,{className:"min-h-[92vh] pt-[152px] pb-20 md:pt-[190px]",children:b1("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_420px] lg:items-end",children:[b1("div",{children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),b1("h1",{className:"mt-7 max-w-[980px] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),b1("p",{className:"mt-7 max-w-[720px] font-body text-body-lg text-theme-muted",children:w},void 0,!1,void 0,this),b1("div",{className:"mt-10 flex flex-col gap-3 sm:flex-row",children:[b1(JE,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(JE,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("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:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.24em] text-theme-light",children:"Live relay signals"},void 0,!1,void 0,this),b1("div",{className:"mt-5 grid gap-3",children:X.map((Y)=>b1("div",{className:"rounded-[22px] border border-card-divider bg-bg-muted p-5",children:[b1("div",{className:"flex items-center justify-between gap-4",children:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.18em] text-secondary",children:Y.label},void 0,!1,void 0,this),b1("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),b1("p",{className:"mt-4 font-display text-display-sm text-theme",children:Y.value},void 0,!1,void 0,this),b1("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 fb6({eyebrow:A,title:Q,intro:w,steps:$}){return b1(ZO,{id:"operating-loop",className:"py-section",children:[b1("div",{className:"max-w-[840px]",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-secondary",children:A},void 0,!1,void 0,this),b1("h2",{className:"mt-5 font-display text-display-md text-theme",children:Q},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:$.map((B)=>b1("article",{className:"min-h-[300px] rounded-[28px] border border-card-panel-border bg-card-panel-bg p-6",children:[b1("p",{className:"font-label text-label-sm text-accent",children:B.phase},void 0,!1,void 0,this),b1("h3",{className:"mt-16 font-display text-display-sm text-theme",children:B.title},void 0,!1,void 0,this),b1("p",{className:"mt-4 font-body text-body-sm text-theme-muted",children:B.text},void 0,!1,void 0,this)]},B.phase,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function xb6({title:A,intro:Q,cards:w}){return b1(ZO,{className:"py-section",children:b1("div",{className:"rounded-[36px] border border-theme-light bg-bg-muted p-6 md:p-10",children:b1("div",{className:"grid gap-8 lg:grid-cols-[360px_1fr]",children:[b1("div",{children:[b1("h2",{className:"font-display text-display-md text-theme",children:A},void 0,!1,void 0,this),b1("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),b1("div",{className:"grid gap-4",children:w.map(($)=>b1("article",{className:"rounded-[24px] border border-card-divider bg-bg-subtle/70 p-5",children:[b1("p",{className:"font-label text-label-xs uppercase tracking-[0.22em] text-accent",children:$.label},void 0,!1,void 0,this),b1("h3",{className:"mt-3 font-nav text-heading-lg text-theme",children:$.title},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-body text-body-sm text-theme-muted",children:$.text},void 0,!1,void 0,this)]},$.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 Rb6({title:A,intro:Q,points:w}){return b1(ZO,{className:"min-h-[78vh] pt-[150px] pb-section md:pt-[190px]",children:[b1("div",{className:"max-w-[920px]",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:"Relay model"},void 0,!1,void 0,this),b1("h1",{className:"mt-6 font-display text-display-lg text-theme",children:A},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-12 grid gap-4 md:grid-cols-3",children:w.map(($)=>b1("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:$},$,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}var vb6=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},Cb6=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),P80=(A,Q,w=`${Q}s`)=>`${Cb6(A)} ${A===1?Q:w}`;function hb6({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:W,counts:K}){let U=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:P80(K.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:P80(K.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:P80(K.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:P80(K.summaries,"summary","summaries")}];return b1(ZO,{className:"pt-[150px] pb-section md:pt-[190px]",id:"diagram",children:[b1("div",{className:"mx-auto max-w-[1040px] text-center",children:[b1("p",{className:"font-label text-label-sm uppercase tracking-[0.28em] text-accent",children:A},void 0,!1,void 0,this),b1("h1",{className:"mx-auto mt-7 max-w-[22ch] font-display text-display-lg text-theme",children:Q},void 0,!1,void 0,this),b1("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),b1("div",{className:"mt-10 flex flex-col justify-center gap-3 sm:flex-row",children:[b1(JE,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(JE,{href:B.href,size:"lg",variant:"secondary",children:B.label},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("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:[b1("div",{className:"grid items-center gap-8 lg:grid-cols-[1fr_1.4fr_1fr]",children:[b1("div",{className:"flex flex-col gap-3.5",children:X.map((G)=>b1("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:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this),b1("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:[b1("div",{className:"absolute inset-0 rounded-full border border-dashed border-accent/30"},void 0,!1,void 0,this),b1("div",{className:"absolute inset-6 animate-spin rounded-full border border-dashed border-secondary/40 [animation-duration:28s]"},void 0,!1,void 0,this),U.map((G)=>b1("span",{className:`absolute whitespace-nowrap rounded-full border border-theme bg-bg px-2.5 py-1 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light ${G.className}`,children:G.label},G.key,!1,void 0,this)),b1("div",{className:"relative z-[1] px-6 text-center",children:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.28em] text-accent",children:Z.eyebrow},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-display text-[36px] leading-none text-theme",children:Z.name},void 0,!1,void 0,this),b1("p",{className:"mt-2 font-body text-[13px] text-theme-muted",children:Z.sub},void 0,!1,void 0,this),b1("p",{className:"mt-4 font-label text-[10px] uppercase tracking-[0.18em] text-theme-light",children:[P80(K.links,"link")," indexed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"flex flex-col gap-3.5",children:Y.map((G)=>b1("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:[b1("p",{className:"font-label text-[10px] uppercase tracking-[0.22em] text-secondary",children:G.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:G.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:G.detail},void 0,!1,void 0,this)]},`${G.label}-${G.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:W.map((G)=>b1("div",{className:"text-left",children:[b1("h2",{className:"font-display text-[16px] font-medium text-theme",children:[b1("span",{className:`mr-2.5 inline-block h-3 w-3 rounded-[3px] align-middle ${vb6(G.tone)}`},void 0,!1,void 0,this),G.title]},void 0,!0,void 0,this),b1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:G.text},void 0,!1,void 0,this)]},G.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var Eb6=$2({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:BDA,formatter:{parse:(A)=>BDA.parse({...ck0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>fy2(ji.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:hb6}}),gb6=(A)=>Ob6(Fb6.parse(A)),yb6=(A)=>fb6(Lb6.parse(A)),Tb6=(A)=>xb6(_b6.parse(A)),Sb6=(A)=>Rb6(bb6.parse(A)),vy2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},Cy2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:gb6,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...vy2,label:"Primary CTA"},secondaryCta:{...vy2,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:yb6,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:Tb6,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:Sb6,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},mb6=[{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:kb6}]}],hy2=c3A({packageName:"@brains/relay/site",themeProfile:"studio",layout:jb6,routes:mb6,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":Eb6},dataSources:[new XDA]}});var Ey2={name:"@brains/relay",version:"0.2.0-alpha.181",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 gy2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],yy2=[...gy2,"image","site-info","site-content","site-builder"],pb6=[...yy2,"docs","decks"],lb6=["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."],db6=hP({name:"relay",version:Ey2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:hy2,theme:Vi,presets:{core:gy2,default:yy2,full:pb6},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:lb6,capabilities:[["prompt",KE,void 0],["note",rh,{}],["link",sh,{}],["image",a00,void 0],["topics",r_0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",wDA,{memoryVisibility:"shared"}],["docs",Y$0,void 0],["decks",$$0,void 0],["agents",Xk0,void 0],["assessment",zk0,void 0],["auth-service",u10,void 0],["notifications",Ib0,void 0],["email-resend",RF0,void 0],["cms",$E,{}],["dashboard",XO,void 0],["directory-sync",sC,{seedContent:!0,seedContentPath:cb6(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",hh,{definitions:Cy2}],["rizom-ecosystem",UE,void 0],["site-info",Eh,void 0],["site-builder",Ch,{}]],interfaces:[["mcp",IM,()=>({})],["discord",Bj,()=>({captureUrls:!0})],["a2a",$l,()=>({})],["webserver",Kj,()=>({})],["web-chat",wl,()=>({})]],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"}}}),Ty2=db6;import{readFileSync as Mj6}from"fs";import{join as jj6}from"path";import{execSync as Oj6}from"child_process";import{parseArgs as rb6}from"util";var ob6={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 _z(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function WO(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function Sy2(A){let{values:Q,positionals:w}=rb6({args:A,options:ob6,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:_z(Q,"model"),domain:_z(Q,"domain"),"content-repo":_z(Q,"content-repo"),backend:_z(Q,"backend"),"push-to":_z(Q,"push-to"),"ai-api-key":_z(Q,"ai-api-key"),"no-interactive":WO(Q,"no-interactive"),preview:WO(Q,"preview"),deploy:WO(Q,"deploy"),regen:WO(Q,"regen"),all:WO(Q,"all"),only:_z(Q,"only"),"dry-run":WO(Q,"dry-run"),"startup-check":WO(Q,"startup-check"),"storage-dir":_z(Q,"storage-dir"),yes:WO(Q,"yes"),remote:_z(Q,"remote"),token:_z(Q,"token"),outputDir:_z(Q,"outputDir")}}}M80();import{mkdirSync as Jj6}from"fs";import{join as Vj6}from"path";import{execSync as Fj6}from"child_process";var lk0={name:"@rizom/brain",version:"0.2.0-alpha.181",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 AT2,writeFileSync as O80,chmodSync as f80,existsSync as zDA,readFileSync as JDA}from"fs";import{basename as VDA,dirname as FDA,join as HB,resolve as fk6}from"path";import{fileURLToPath as xk6}from"url";var my2=`ARG BUN_VERSION=1.3.10
|
|
13830
13848
|
FROM oven/bun:\${BUN_VERSION}-slim AS runtime
|
|
13831
13849
|
|
|
13832
13850
|
WORKDIR /app
|